您的位置 首页 厂商

根据Java言语的51单片机串口通讯PC机程序

1硬件部分(KeilC)图1硬件电路图串口通讯硬件部分电路,收发器件采用max232,5V供电。J31接一单片机如AT89C52,单片机的串口与max232的10…

1硬件部分(KeilC)

图1硬件电路图

串口通讯硬件部分电路,收发器材选用max232,5V供电。J31接一单片机如AT89C52,单片机的串口与max232的10和11脚相连。

max232与微机经过9针接头相连。

本文的试验环境是AT89C52,单片机的内部程序是用KeilC言语编写的,程序功用十分简略,检测到开端信号后从串口读数据,然后把读入的数据发送给串口,遇到完毕符中止。C言语代码如下供咱们参阅。在uv3中含有两个文件comm.h和comm.c,代码分别为:

//

/* comm.h*/

/* serial port define, only use in comm project */

//

#define ucharunsigned char

#define uint unsigned int

#define length0x0F //数据包长度

ucharCR = 0x0D;

ucharLF = 0x0A;

ucharESC = 0x1B;

ucharSYNC = 0x01; //数据包启始符

ucharPID = 0x00; //数据包怂恿字

ucharADDR; //串口接纳外部指令(片内地址)

ucharDATA; //串口回来片内数据

ucharENDP = 0x00; //数据包完毕符

ucharACK = 0x06; //串口结语

ucharERROR = 0x18; //串口过错

ucharwrong[] = “Bad command”;

/*END*/

/*/

/*comm..c*/

/* Write time is 2005.4.15,By Gooseli*/

/* Copyright is changsha HUNU unversity gooseli.com */

/* Cpu is At89C51,Fclk is 11.059MHz */

/* Compiler is keilC51 compiler */

/*/

#include

#include

#include

#include

void commInit(){

////

// 8051串口初始化//

////

SCON = 0x52;

PCON = 0x80;

TMOD = 0x21;

TH1 = 0x0FA;

TL1 = 0x0FA;

TCON = 0x40;

//*//

//串口控制器作业于办法1,8位,频率可变。接纳答应//

//串口波特率系数SMOD = 1 //

//定时器1作业于办法1,8位自动装载。定时器0办法1,16位//

// 11.059M晶振,波特率= 9600,TH1 = 0x0FA;//

//19200 0x0FD //

//57600 0x0FF //

// 3.6864M晶振9600 0x0FE //

//19200 0x0FF //

// #3.6864M晶振作业于办法2 //

// #在SMOD = 1时,波特率= 115200//

//开中止TR1 = 1//

//*//

}

uchar flag;

uchar readln();

void println( uchar *str );

main(){

commInit(); //初始化串口

while(1){

flag = readln();

}

}

uchar readln(){

uchar a;

uchar str[length];

int i;

scanf(“%c”,&a); //寻觅开端符,回车则开端

if( a==SYNC || a==LF ){

while(1){

printf(“\n>>”);

//printf(“>>”);

scanf(“%c”,&a);

if( a==ENDP || a == ESC ){ //假设ESC则对话完毕

break;

}

for( i=”0″; i

//读入数据包,假设溢出或许回车则完毕

str[i] = a;

scanf(“%c”,&a);

}

str[i] = ENDP; //为数据包添加完毕符,“\0”

printf(“%s”,str); //输出输入值

/*To do something by yourself*/

}

return ACK;

}

printf(“\n%s\n>>”,wrong);

return ERROR;

}

/*END*/

2装备运转环境(JDK)

Java通讯库函数Java Communications API,Java开发工具JBuilderX。

此Java(TM) Communications API Specification 2.0(Windows Platform)是Sun公司为Windows渠道供给的一个串口API扩展,能够到http://java.sun.com/products/javacomm/下载。Sun公司还供给了其他操作体系下的API下载,移植性是Java先天的优势,假设需求在其他操作体系运转程序,不需求改动程序自身,只要在操作体系下植入相应的API库函数即可完成。

JBuilder是Borland公司出品的一款功用强壮的可视化Java集成开发工具,能够快速开发包含杂乱企业级运用体系的各种Java程序,本文的程序都用其完成。当然咱们以可运用其他优异的开发工具,例如开放源代码的Eclipse,功用强壮,插件丰厚。

在下载Java Communications API压缩文件里找到三个文件:comm.jar,win32comm.dll,javax.comm.properties,这三个文件是把API安装到Windows环境中的重要文件,咱们把他们放在咱们的JDK晒干。

把comm..jar到%JAVA_HOME%\jre\lib\ext,javax.comm.properties到%JAVA_HOME%\jre\lib,win32comm.dll到%JAVA_HOME%\bin即可。这样咱们的程序就能够在Windows环境中运转了,Java Communications API压缩文件中自带有比如,咱们能够测验一下。

接下来咱们要把Java Communications API安装到JBuilder晒干,假设JBuilder不是运用的外部的JDK,照上面的的过程再做一次。假设咱们外部的JDK和JBuilder的JDK是同一的JDK,咱们就直接跳到下一步。

1)翻开JBuilder,为咱们的使命树立一个工程,给它起个有意义的姓名,不多讲了。JBuilder会自动生成两个文件,如,工程名为comm,就会生成文件commApplication和commFrame。

2)挑选Tools菜单,挑选Configure Libraries…,如图1所示。

3)点击New按钮,为JBuilder添加一个函数库。如图2,点击OK即可。

4)下一步为你的工程添加这个库函数,以便你在工程里调用它们。挑选Project菜单中的Project Properities选项,左边选中Paths,右侧选中Required Libraries,单击Add,呈现一个小的对话框,挑选咱们方才添加的comm函数库,如图3,点击OK两次即可。

现在环境现已装备好了,咱们要开端正式作业了。

图2 Configure Library

图2 New Librariy Wizard


图3 Select comm. Library

3程序开发(JBuilderX)

1.与51单片机交互信息,数据库存取(Data)

为了确保数据传输的顺利进行,单片机与PC之间通讯要树立一个协议,在本实例中,选用如下协议:

程序翻开串口后,程序发送“启始”符(0x01)一共通讯开端。

通讯开端后,程序就开端发送和接纳数据包,数据包以“完毕”符(0x00,0x0D, 0x0A)一共完毕。咱们单片机受控于PC机,所以单片机一般不自动发送数据,只要在PC机发送一个“指令”,它才会发送一个“回应”。

假设程序“中止”符(0x00),则通讯完毕。

2.界面规划(View)

这部分规划主程序的视图,即运用者看到的部分,包含按钮,下拉菜单,文字编辑框等。

为了程序的可读性,咱们将一切的视图从主程序中分离出来,作成Bean的方式,然后在主程序中调用它们。Java供给了五种布局办理方式FlowLayout,,GridLayout,GridBagLayout,BorderLayout,,CardLayout。灵敏的运用这些布局,能够到达各式各样的作用,其间GridBagLayout功用强壮,运用灵敏,本文首要选用这种布局。

3.主程序规划(Control)

这部分规划程序的完成办法,逻辑过程。

1)首要界说串口,输入输出流等,如下所示:

package comm;

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import javax.comm.*;//包含comm类包,才干运用其API函数

import java.io.*;

import java.util.*;

public class CommFrame extends JFrame implements Runnable, SerialPortEventListener {

JPanel contentPane; //界说一个JPanel,将视图Bean包含进来

BorderLayout borderLayout1 = new BorderLayout();

IOBean ioBean = new IOBean();//右侧视图Bean类案例化

ControlBean controlBean = new ControlBean();//左边视图Bean类案例化

//Communination define

static CommPortIdentifier portName;//界说串口

int portId;

static Enumeration portList;

InputStream inputStream;//界说输入流

OutputStream outputStream;//界说输出流

SerialPort serialPort;

Thread readThread;//界说一个线程,程序全双工通讯

static String TimeStamp;

//Construct the frame

public CommFrame() {

enableEvents(AWTEvent.WINDOW_EVENT_MASK);

try {

jbInit();//程序初始化

commInit();//串口初始化

}catch(Exception e) {

e.printStackTrace();

}

}

private void jbInit() throws Exception{……}

public void commInit() {……}

public void commClose() {……}

public void commWrite() {……}

public void CommRead() {……}

public void run() {……}

public void serialEvent(SerialPortEvent event) {…….}//代码如下

//Overridden so we can exit when window is closed

protected void processWindowEvent(WindowEvent e) {

super.processWindowEvent(e);

if (e.getID() == WindowEvent.WINDOW_CLOSING) {

commClose();

System.exit(0);

}

}

}

2)串口初始化,首要监测串口是否被占用,假设没有被占用则翻开串口。翻开输入输出流以便下面的程序从串口读写数据,界说串口的波特率,位数,中止位,奇偶校验,在运用过程中能够改动这些内容以习惯不同的需求。

public void commInit() {

//Communination ports owned or not

portId = 1;

try{

portList = CommPortIdentifier.getPortIdentifiers();

while (portList.hasMoreElements()) {

portName = (CommPortIdentifier) portList.nextElement();

if (portName.getPortType() == CommPortIdentifier.PORT_SERIAL) {

if (portName.isCurrentlyOwned()) {//串口是否被占用

ioBean.Receiver.append(“\nCOM”+portId+”Ownedby”+ portName.getCurrentOwner());

TimeStamp = new java.util.Date().toString();

portId ++;

}else if (portName.getName().equals(“COM” + portId)) {

break;

}

}

}

//Communination ports init

try {

serialPort = (SerialPort) portName.open(“Gooseli_MCU_Control_App”, 2000);//翻开串口

controlBean.CommPortID.setText(“COM” + portId);

controlBean.OnOff.setText(“ON”);//开关按钮置开状况

controlBean.OnOff.setSelected(true);

TimeStamp = new java.util.Date().toString();

System.out.println(TimeStamp + “: msg2 – SerialPort COM” + portId + ” is opend”);

ioBean.Receiver.append(“\nCOM” + portId + ” is opend”);//显现区域显现串口被翻开

} catch (PortInUseException e) {

System.out.println(e);

ioBean.Receiver.append(“\nCOM” + portId + ” ” + e);

}

try {

inputStream = serialPort.getInputStream();//翻开输入流

} catch (IOException e) {}

try {

outputStream = serialPort.getOutputStream();

outputStream.write((byte)0x01);//向串口写入启始符开端传送数据包

ioBean.Receiver.setText(“\nCOM” + portId + “>>” + “Start”);

controlBean.begin.setSelected(true);

} catch (IOException e) {}

try {

serialPort.setSerialPortParams(9600,//波特率

SerialPort.DATABITS_8,//数据位

SerialPort.STOPBITS_1,//中止位

SerialPort.PARITY_NONE);//校验位

} catch (UnsupportedCommOperationException e) {}

CommRead();//程序开端从串口读数据

}catch(Exception e) {}

}

public void commClose() {

try {

inputStream.close();

outputStream.close();

serialPort.close();

System.out.println(TimeStamp + “: msg2 – SerialPort COM” + portId + ” is closing”);

ioBean.Receiver.append(“\nCOM” + portId + ” is closing”);

}catch (Exception e) {

System.out.println(e);

}

}

3)程序初始化,这儿界说了一些事情,以便控制程序的运转。例如开端按钮的事情界说如下:

private void jbInit() throws Exception{

contentPane = (JPanel) this.getContentPane();

contentPane.setLayout(borderLayout1);

this.setSize(new Dimension(400, 300));

this.setTitle(“Serial Ports Communication Current”);

contentPane.add(ioBean,BorderLayout.CENTER);

contentPane.add(controlBean, BorderLayout.WEST);

controlBean.OnOff.addActionListener(

new ActionListener() {

public void actionPerformed(ActionEvent ae) {

JToggleButton toggle = (JToggleButton) ae.getSource();

if (toggle.isSelected()) {

controlBean.OnOff.setText(“ON”);

commInit();

} else {

controlBean.OnOff.setText(“OFF”);

commClose();

}

}

}

);

controlBean.begin.addActionListener(

new ActionListener() {

public void actionPerformed(ActionEvent ae) {

JToggleButton toggle = (JToggleButton) ae.getSource();

if (toggle.isSelected()) {//假设按钮被按下,则开端

controlBean.begin.setText(“Start”);

try {

outputStream.write((byte)0x01);//发送开端符

ioBean.Receiver.setText(“\nCOM” + portId + ” ” + “Start”);

} catch (IOException e) {}

} else {//假设按纽复位

controlBean.begin.setText(“Stop”);

try {

outputStream.write((byte)0x00);//发送完毕符

ioBean.Receiver.append(“\nCOM” + portId + ” ” + “Stop”);

} catch (IOException e) {}

}

}

}

);

ioBean.jButton2.addActionListener(

new ActionListener() {

public void actionPerformed(ActionEvent ae) {

commWrite();

}

}

);

}

4)读写串口,运用多线程,完成全双工通讯。主函数CommFrame完成了Runnable接口,在程序中只需求重写run函数即可完成多线程。

public void commWrite() {

String outString = ioBean.jTextField1.getText();

if (outString.equals(“clear”)) {

ioBean.Receiver.setText(“\nCOM” + portId +” Receive:”);

}

ioBean.jTextField1.setText(“Gooseli:”);

try {

//outputStream.write((byte)0x01);

outputStream.write(outString.getBytes());

outputStream.write((byte)0x0D);

//outputStream.write((byte)0x00);

ioBean.Receiver.setText(“\nCOM” + portId + “>>” + outString);

} catch (IOException e) {}

}

public void CommRead() {

try {

serialPort.addEventListener(this);

} catch (TooManyListenersException e) {}

serialPort.notifyOnDataAvailable(true);

readThread = new Thread(this);

readThread.start();

}

public void run() {

try {

Thread.sleep(20000);

}

catch (InterruptedException e) {}

}

public void serialEvent(SerialPortEvent event) {

switch(event.getEventType()) {

case SerialPortEvent.BI:

case SerialPortEvent.OE:

case SerialPortEvent.FE:

case SerialPortEvent.PE:

case SerialPortEvent.CD:

case SerialPortEvent.CTS:

case SerialPortEvent.DSR:

case SerialPortEvent.RI:

case SerialPortEvent.OUTPUT_BUFFER_EMPTY:

break;

case SerialPortEvent.DATA_AVAILABLE:

StringBuffer readBuffer = new StringBuffer();

String scannedInput = null;

int c;

try {

while ((c = inputStream.read()) != 0x00 && c != 0x0D && c != 0x0A) {

readBuffer.append( (char) c);//数据包以回车或许换行一共完毕

}

scannedInput = readBuffer.toString();

ioBean.Receiver.append(“\n” + scannedInput);

TimeStamp = new java.util.Date().toString();

System.out.println(TimeStamp + “: scanned input received:” + scannedInput);

inputStream.close();

} catch (IOException e) {}

break;

}

}

4.测验程序

程序运转后如图四所示。

为了便利程序运转,咱们作一个批处理文件,和程序生成的jar文件放在一个目录里,这样就能够很便利的在含有Java虚拟机的体系里运转咱们的程序了。能够将JBuilder运转窗口(Messages)的信息直接劳动过来,当然也能够自己树立。

我的批处理文件如下所示:

@echo off

@REM设置途径包含Java虚拟机和程序jar文件途径

set path=%JAVA_HOME%\bin

set classpath=%cd%\comm.jar

@REM运转程序,注意在主程序前添加包名,不然找不到主函数

echo Now initializing the program,please wait a minite…

java comm.CommApplication

图4 Test my programme

4展望

Java作为一个逐步老练的程序规划言语,在网络和嵌入式体系越来越多地得到广泛的运用,可是微机底层程序开发发展缓慢。本文运用Java作为串口上位机程序开发言语,是考虑到Java言语的各种优越性,首要是其渠道无关性,强壮的可移植性,这一点在不久的将来会遭到更多的注重。

本文代码可免费运用,假设需求本文程序的源代码,请于本作者联络,gooseli@163.com。

参阅资料:

1.A How-To on Accessing serial ports in the Windows environment using the Java Communications API,By Rick Proctor,www.borland.com,2004年3月14日,http://bdn.borland.com/article/0,1410,31915,00.html

2.The Java Communications API Documentations,www.sun.com,2004年11月

3.JBuilder 9集成开发实例解析,张洪斌编,机械工业出版社,2004年1月

4.通晓JBuilder 9,飞思科技产品措辞中心编,电子工业出版社,2003年8月

5.单片微机原理及运用,丁元杰、赵秀菊、陈瀛清编,机械工业出版社,1999年8月

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/changshang/263626.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部