=CR&&a!
=LF;i++){
//读入数据包,如果溢出或者回车则结束
str[i]=a;
scanf("%c",&a);
}
str[i]=ENDP;//为数据包添加结束符,“/0”
printf("%s",str);//输出输入值
/*Todosomethingbyyourself*/
}
returnACK;
}
printf("/n%s/n>>",wrong);
returnERROR;
}
/*END*/
2配置运行环境(JDK)
Java通讯库函数JavaCommunicationsAPI,Java开发工具JBuilderX。
此Java(TM)CommunicationsAPISpecification2.0(WindowsPlatform)是Sun公司为Windows平台提供的一个串口API扩展,可以到下载。
Sun公司还提供了其他操作系统下的API下载,移植性是Java先天的优势,如果需要在其他操作系统运行程序,不需要改动程序本身,只要在操作系统下植入相应的API库函数即可实现。
JBuilder是Borland公司出品的一款功能强大的可视化Java集成开发工具,可以快速开发包括复杂企业级应用系统的各种Java程序,本文的程序都用其实现。
当然我们以可使用其他优秀的开发工具,例如开放源代码的Eclipse,功能强大,插件丰富。
在下载JavaCommunicationsAPI压缩文件里找到三个文件:
comm.jar,win32comm.dll,m.properties,这三个文件是把API安装到Windows环境中的重要文件,我们把他们放在我们的JDK里面。
把comm..jar复制到%JAVA_HOME%/jre/lib/ext,m.properties复制到%JAVA_HOME%/jre/lib,win32comm.dll复制到%JAVA_HOME%/bin即可。
这样我们的程序就可以在Windows环境中运行了,JavaCommunicationsAPI压缩文件中自带有例子,我们可以尝试一下。
接下来我们要把JavaCommunicationsAPI安装到JBuilder里面,如果JBuilder不是使用的外部的JDK,照上面的的步骤再做一次。
假如我们外部的JDK和JBuilder的JDK是同一的JDK,我们就直接跳到下一步。
1)打开JBuilder,为我们的任务建立一个工程,给它起个有意义的名字,不多讲了。
JBuilder会自动生成两个文件,如,工程名为comm,就会生成文件commApplication和commFrame。
2)选择Tools菜单,选择ConfigureLibraries…,如图1所示。
3)点击New按钮,为JBuilder增加一个函数库。
如图2,点击OK即可。
4)下一步为你的工程增加这个库函数,以便你在工程里调用它们。
选择Project菜单中的ProjectProperities选项,左侧选中Paths,右侧选中RequiredLibraries,单击Add,出现一个小的对话框,选择我们刚才增加的comm函数库,如图3,点击OK两次即可。
现在环境已经配置好了,我们要开始正式工作了。
图2ConfigureLibrary
图2NewLibrariyWizard
图3Selectcomm.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)首先定义串口,输入输出流等,如下所示:
packagecomm;
importjava.awt.*;
importjava.awt.event.*;
importjavax.swing.*;
importm.*;//包含comm类包,才能使用其API函数
importjava.io.*;
importjava.util.*;
publicclassCommFrameextendsJFrameimplementsRunnable,SerialPortEventListener{
JPanelcontentPane;//定义一个JPanel,将视图Bean包含进来
BorderLayoutborderLayout1=newBorderLayout();
IOBeanioBean=newIOBean();//右侧视图Bean类事例化
ControlBeancontrolBean=newControlBean();//左侧视图Bean类事例化
//Communinationdefine
staticCommPortIdentifierportName;//定义串口
intportId;
staticEnumerationportList;
InputStreaminputStream;//定义输入流
OutputStreamoutputStream;//定义输出流
SerialPortserialPort;
ThreadreadThread;//定义一个线程,程序全双工通讯
staticStringTimeStamp;
//Constructtheframe
publicCommFrame(){
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try{
jbInit();//程序初始化
commInit();//串口初始化
}catch(Exceptione){
e.printStackTrace();
}
}
privatevoidjbInit()throwsException{……}
publicvoidcommInit(){……}
publicvoidcommClose(){……}
publicvoidcommWrite(){……}
publicvoidCommRead(){……}
publicvoidrun(){……}
publicvoidserialEvent(SerialPortEventevent){…….}//代码如下
//Overriddensowecanexitwhenwindowisclosed
protectedvoidprocessWindowEvent(WindowEvente){
super.processWindowEvent(e);
if(e.getID()==WindowEvent.WINDOW_CLOSING){
commClose();
System.exit(0);
}
}
}
2)串口初始化,首先监测串口是否被占用,如果没有被占用则打开串口。
打开输入输出流以便下面的程序从串口读写数据,定义串口的波特率,位数,停止位,奇偶校验,在使用过程中可以改变这些内容以适应不同的需求。
publicvoidcommInit(){
//Communinationportsownedornot
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=newjava.util.Date().toString();
portId++;
}elseif(portName.getName().equals("COM"+portId)){
break;
}
}
}
//Communinationportsinit
try{
serialPort=(SerialPort)portName.open("Gooseli_MCU_Control_App",2000);//打开串口
controlBean.CommPortID.setText("COM"+portId);
controlBean.OnOff.setText("ON");//开关按钮置开状态
controlBean.OnOff.setSelected(true);
TimeStamp=newjava.util.Date().toString();
System.out.println(TimeStamp+":
msg2-SerialPortCOM"+portId+"isopend");
ioBean.Receiver.append("/nCOM"+portId+"isopend");//显示区域显示串口被打开
}catch(PortInUseExceptione){
System.out.println(e);
ioBean.Receiver.append("/nCOM"+portId+""+e);
}
try{
inputStream=serialPort.getInputStream();//打开输入流
}catch(IOExceptione){}
try{
outputStream=serialPort.getOutputStream();
outputStream.write((byte)0x01);//向串口写入启始符开始传送数据包
ioBean.Receiver.setText("/nCOM"+portId+">>"+"Start");
controlBean.begin.setSelected(true);
}catch(IOExceptione){}
try{
serialPort.setSerialPortParams(9600,//波特率
SerialPort.DATABITS_8,//数据位
SerialPort.STOPBITS_1,//停止位
SerialPort.PARITY_NONE);//校验位
}catch(UnsupportedCommOperationExceptione){}
CommRead();//程序开始从串口读数据
}catch(Exceptione){}
}
publicvoidcommClose(){
try{
inputStream.close();
outputStream.close();
serialPort.close();
System.out.println(TimeStamp+":
msg2-SerialPortCOM"+portId+"isclosing");
ioBean.Receiver.append("/nCOM"+portId+"isclosing");
}catch(Exceptione){
System.out.println(e);
}
}
3)程序初始化,这里定义了一些事件,以便控制程序的运行。
例如开始按钮的事件定义如下:
privatevoidjbInit()throwsException{
contentPane=(JPanel)this.getContentPane();
contentPane.setLayout(borderLayout1);
this.setSize(newDimension(400,300));
this.setTitle("SerialPortsCommunicationCurrent");
contentPane.add(ioBean,BorderLayout.CENTER);
contentPane.add(controlBean,BorderLayout.WEST);
controlBean.OnOff.addActionListener(
newActionListener(){
publicvoidactionPerformed(ActionEventae){
JToggleButtontoggle=(JToggleButton)ae.getSource();
if(toggle.isSelected()){
controlBean.OnOff.setText("ON");
commInit();
}else{
controlBean.OnOff.setText("OFF");
commClose();
}
}
}
);
controlBean.begin.addActionListener(
newActionListener(){
publicvoidactionPerformed(ActionEventae){
JToggleButtontoggle=(JToggleButton)ae.getSource();
if(toggle.isSelected()){//如果按钮被按下,则开始
controlBean.begin.setText("Start");
try{
outputStream.write((byte)0x01);//发送起始符
ioBean.Receiver.setText("/nCOM"+portId+""+"Start");
}catch(IOExceptione){}
}else{//如果按纽复位
controlBean.begin.setText("Stop");
try{
outputStream.write((byte)0x00);//发送结束符
ioBean.Receiver.append("/nCOM"+portId+""+"Stop");
}catch(IOExceptione){}
}
}
}
);
ioBean.jButton2.addActionListener(
newActionListener(){
publicvoidactionPerformed(ActionEventae){
commWrite();
}
}
);
}
4)读写串口,使用多线程,实现全双工通讯。
主函数CommFrame实现了Runnable接口,在程序中只需要重写run函数即可实现多线程。
publicvoidcommWrite(){
StringoutString=ioBean.jTextField1.getText();
if(outString.e