JAVA提供的串口操作的包(javax,comm),可以用于PC的串口一般操作,其包内的方法基本有如下几个
addPortName(String, int, CommDriver) 添加端口名到端口列表里
addPortOwnershipListener(CommPortOwnershipListener) 添加端口拥有的兼听器
removePortOwnershipListener(CommPortOwnershipListener) 移除端口拥有的兼听器
getCurrentOwner() 得到当前占有端口的对象或应用程序
getName() 得到端口名称
getPortIdentifier(CommPort) 得到参数打开的端口的CommPortIdentifier类型对象
getPortIdentifier(String) 得到以参数命名的端口的CommPortIdentifier类型对象
getPortIdentifiers() 得到系统中的端口列表
getPortType() 得到端口的类型
isCurrentlyOwned() 判断当前端口是否被占用
open(FileDescriptor) 用文件描述的类型打开端口
open(String, int) 打开端口,两个参数:程序名称,延迟时间(毫秒数)
有了以上方法,基本就可以对串口操作了。而JAVA开发起来也比较容易,我第一次用JAVA开发桌面程序就没有想象中那么艰辛。
一般的单片机都有串口,所以与PC机通信的时候,一般均会选择串口将采集到数据或者是其他什么发送出来,然后PC机进行接收,进行或简单或复杂的数据处理,然后予以显示。这一般就是一个上位机的搭建吧!
基本的串口操作就是这么几个步骤:枚举本机可用串口,选定串口并打开,设置串口,数据通信!
在SUN公司给的DOME中,基本的串口操作就都有了,只要稍加修改就可。
步骤1:枚举本机串口
在网上搜了几个代码,基本都是差不多的。使用 getPortIdentifiers() 方法得到系统中的串口列表,然后通过portId.getPortType() == CommPortIdentifier.PORT_SERIAL ,判断是否为COM端口,然后我把结果放入了COMBOBOX(组合框中)。
private void listPortChoices()
{
//Enumeration 为枚举型类
Enumeration en = CommPortIdentifier.getPortIdentifiers();
while (en.hasMoreElements())
{
portId = (CommPortIdentifier) en.nextElement();
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL)
{
comboBoxCommPort.addItem(portId.getName());
}
}
}
步骤2:选定串口,并打开。
上一步我将串口的名称放入了组合框COMBOBOX中,那么,只要加入监@听,当有选择的动作时候,返回所选择的字符串,再通过放方法getPortIdentifier(CommPort) 打开所选择的串口。代码如下。
try
{
portId = CommPortIdentifier.getPortIdentifier(CommChoose);
}
catch (NoSuchPortException e)
{
MessagetextArea.append("端口不存在"+"/n");
}
如果抛出异常,就该检查端口是否正常连接了。不过一般这不会出错。
然后是打开串口,只需使用open(String, int) 这个方法就好。String为工程的名字,int则为延时。
try
{//打开所选择的串口
serialPort = (SerialPort)portId.open("Comm",2000);
}
catch (PortInUseException e)
{
MessagetextArea.append("打开串口"+portId.getName()+"失败"+"/n");
}
按照以上代码,那么,就成功的打开串口了。但是还需要对串口进行配置。
步骤3:串口的配置
配置代码如下,
try
{//获得输入输出流
inputStream = serialPort.getInputStream();
outputStream = serialPort.getOutputStream();
}
catch (IOException e)
{
MessagetextArea.append("获取串口"+portId.getName()+"输入输出流失败"+"/n");
serialPort.close();
MessagetextArea.append("已关闭串口"+portId.getName()+"/n");
}
try
{//为串口添加兼听器
CommProtDateAction CommProtDateAction = new CommProtDateAction("GetDate");
serialPort.addEventListener(CommProtDateAction);
}
catch (TooManyListenersException e)
{
MessagetextArea.append("兼听串口"+portId.getName()+"失败"+"/n");
serialPort.close();
MessagetextArea.append("已关闭串口"+portId.getName()+"/n");
}
serialPort.notifyOnDataAvailable(true); //设置数据事件有效,中断?!
try
{//配置串口
serialPort.setSerialPortParams(9600,//波特率9600bps
SerialPort.DATABITS_8,//8位数据位
SerialPort.STOPBITS_1,//1位停止位
SerialPort.PARITY_NONE);//无校验
MessagetextArea.append("串口波特率:9600"+"/n");
MessagetextArea.append("串口数据位:8位"+"/n");
MessagetextArea.append("串口停止位:1位"+"/n");
MessagetextArea.append("串口校验方式:无校验"+"/n");
}
catch (UnsupportedCommOperationException e)
{
MessagetextArea.append("配置串口"+portId.getName()+"失败"+"/n");
serialPort.close();
MessagetextArea.append("已关闭串口"+portId.getName()+"/n");
}
上位机需与下位机进行通讯,所以首先须获得输入输出流,保证自身能接受下位机数据,自身也可以发数据至下位机。
至于兼听串口,这个我的理解是,有数据则产生“中断”,之后程序将进行“中断”的“服务函数”。这个理解始终还是未脱离单片机,不是那么的地道,但按照程序执行的来看,确实是相当于中断。
然后是统一数据格式,波特率,数据位多少,停止位多少,是否检验。只要上位机与下位机之间保持一致,那么数据就能良好的传输。
至此,已经可以进行数据通信了。
对于PC机(上位机)来说,发送数据的代码如下。
private void sendDate(String SendData)
{
try //发送~~~~~~~~~~~~!!!!
{
outputStream = serialPort.getOutputStream();
outputStream.write(SendData.getBytes());
}
catch (IOException e)
{
MessagetextArea.append("发送数据"+"“"+SendData+"”"+"失败"+"/n");
}
MessagetextArea.append("发送数据"+"“"+SendData+"”"+"成功"+"/n");
}
接收数据的代码如下。
private class CommProtDateAction implements SerialPortEventListener
{
private String Mas;
public CommProtDateAction(String Message)
{
Mas = Message;
}
public void serialEvent(SerialPortEvent event)
{
try //延时0.5秒
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
MessagetextArea.append("延时失败"+"/n");
}
//GetTextArea.append("数据到达"+"/n");
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: MessagetextArea.append("数据未通过校验"+"/n");
break;
case SerialPortEvent.DATA_AVAILABLE://如果有数据到达
byte[] readBuffer = new byte[20];
try
{
while (inputStream.available()>0)
{ //读取一个字节到readBuffer
int number = inputStream.read(readBuffer);
getDate = readBuffer[0];
MessagetextArea.append("数据" + getDate + "到达/n");
}
}
}
catch (IOException e)
{
MessagetextArea.append("串口"+portId.getName()+"接收数据失败"+"/n");
}
}
}
}
最后,接收的数据就存储在getDate之中。如果数据不是单个的,那么就加点数据处理的语句。以上为我删减的后的代码,我进行了数据的处理,这个就按照自己的意愿或者要求来就好,并不是一定的必须怎么处理。