首页编程java 串口(Java串口通信总结)

java 串口(Java串口通信总结)

编程之家2023-11-03103次浏览

很多朋友对于java 串口和Java串口通信总结不太懂,今天就由小编来为大家分享,希望可以帮助到大家,下面一起来看看吧!

java 串口(Java串口通信总结)

编程技巧:Java串口通信简介

嵌入式系统或传感器网络的很多应用和测试都需要通过PC机与嵌入式设备或传感器节点进行通信其中最常用的接口就是RS串口和并口(鉴于USB接口的复杂性以及不需要很大的数据传输量 USB接口用在这里还是显得过于奢侈况且目前除了SUN有一个支持USB的包之外我还没有看到其他直接支持USB的Java类库) SUN的CommAPI分别提供了对常用的RS串行端口和IEEE并行端口通讯的支持 RS C(又称EIA RS C以下简称RS)是在年由美国电子工业协会(EIA)联合贝尔系统调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准 RS是一个全双工的通讯协议它可以同时进行数据接收和发送的工作

常见的Java串口包

目前常见的Java串口包有SUN在年发布的串口通信API m jar(Windows下) m jar(Linux/Solaris);IBM的串口通信API以及一个开源的实现鉴于在Windows下SUN的API比较常用以及IBM的实现和SUN的在API层面都是一样的那个开源的实现又不像两家大厂的产品那样让人放心这里就只介绍SUN的串口通信API在Windows平台下的使用

串口包的安装(Windows下)

到SUN的网站下载javam win zip包含的东西如下所示

java 串口(Java串口通信总结)

按照其使用说明(l)的说法要想使用串口包进行串口通信除了设置好环境变量之外还要将win dll复制到 \bin目录下;将m jar复制到 \lib;把m properties也同样拷贝到 \lib目录下然而在真正运行使用串口包的时候仅作这些是不够的因为通常当运行 java MyApp的时候是由JRE下的虚拟机启动MyApp的而我们只复制上述文件到JDK相应目录下所以应用程序将会提示找不到串口解决这个问题的方法很简单我们只须将上面提到的文件放到JRE相应的目录下就可以了

值得注意的是在网络应用程序中使用串口API的时候还会遇到其他更复杂问题有兴趣的话你可以查看CSDN社区中关于网页上Applet用javam读取客户端串口的问题的帖子

串口API概览

m CommPort

这是用于描述一个被底层系统支持的端口的抽象类它包含一些高层的IO控制方法这些方法对于所有不同的通讯端口来说是通用的 SerialPort和ParallelPort都是它的子类前者用于控制串行端口而后者用于控这并口二者对于各自底层的物理端口都有不同的控制方法这里我们只关心SerialPort

m CommPortIdentifier

java 串口(Java串口通信总结)

这个类主要用于对串口进行管理和设置是对串口进行访问控制的核心类主要包括以下方法

l确定是否有可用的通信端口

l为IO操作打开通信端口

l决定端口的所有权

l处理端口所有权的争用

l管理端口所有权变化引发的事件(Event)

m SerialPort

这个类用于描述一个RS串行通信端口的底层接口它定义了串口通信所需的最小功能集通过它用户可以直接对串口进行读写及设置工作

串口API实例

大段的文字怎么也不如一个小例子来的清晰下面我们就一起看一下串口包自带的例子 SerialDemo中的一小段代码来加深对串口API核心类的使用方法的认识

列举出本机所有可用串口

voidlistPortChoices(){ CommPortIdentifierportId; Enumerationen=CommPortIdentifier getPortIdentifiers();//iteratethroughtheports while(en hasMoreElements()){ portId=(CommPortIdentifier)en nextElement(); if(portId getPortType()==CommPortIdentifier PORT_SERIAL){ System out println(portId getName());}} portChoice select(parameters getPortName());}

以上代码可以列举出当前系统所有可用的串口名称我的机器上输出的结果是和

串口参数的配置

串口一般有如下参数可以在该串口打开以前配置进行配置

包括波特率输入/输出流控制数据位数停止位和齐偶校验

SerialPortsPort; try{ sPort setSerialPortParams(BaudRate Databits Stopbits Parity);//设置输入/输出控制流 sPort setFlowControlMode(FlowControlIn|FlowControlOut);}catch(UnsupportedCommOperationExceptione){}

串口的读写

对串口读写之前需要先打开一个串口

CommPortIdentifierportId=CommPortIdentifier getPortIdentifier(PortName); try{ SerialPortsPort=(SerialPort)portId open(串口所有者名称超时等待时间);}catch(PortInUseExceptione){//如果端口被占用就抛出这个异常 thrownewSerialConnectionException(e getMessage());}//用于对串口写数据 OutputStreamos=newBufferedOutputStream(sPort getOutputStream()); os write(intdata);//用于从串口读数据 InputStreamis=newBufferedInputStream(sPort getInputStream()); intreceivedData=is read();

读出来的是int型你可以把它转换成需要的其他类型

这里要注意的是由于Java语言没有无符号类型即所有的类型都是带符号的在由byte到int的时候应该尤其注意因为如果byte的最高位是则转成int类型时将用来占位这样原本是的byte类型的数变成int型就成了这是很严重的问题应该注意避免

串口通信的通用模式及其问题

终于唠叨完我最讨厌的基础知识了下面开始我们本次的重点串口应用的研究由于向串口写数据很简单所以这里我们只关注于从串口读数据的情况通常串口通信应用程序有两种模式一种是实现SerialPortEventListener接口监听各种串口事件并作相应处理;另一种就是建立一个独立的接收线程专门负责数据的接收由于这两种方法在某些情况下存在很严重的问题(至于什么问题这里先卖个关子J)所以我的实现是采用第三种方法来解决这个问题

事件监听模型

现在我们来看看事件监听模型是如何运作的

l首先需要在你的端口控制类(例如SManager)加上 implements SerialPortEventListener

l在初始化时加入如下代码

try{ SerialPortsPort addEventListener(SManager);}catch(TooManyListenersExceptione){ sPort close(); thrownewSerialConnectionException( toomanylistenersadded);} sPort notifyOnDataAvailable(true);

l覆写public void serialEvent(SerialPortEvent e)方法在其中对如下事件进行判断

BI通讯中断

CD载波检测

CTS清除发送

DATA_AVAILABLE有数据到达

DSR数据设备准备好

FE帧错误

OE溢位错误

OUTPUT_BUFFER_EMPTY输出缓冲区已清空

PE奇偶校验错

RI振铃指示

一般最常用的就是DATA_AVAILABLE串口有数据到达事件也就是说当串口有数据到达时你可以在serialEvent中接收并处理所收到的数据然而在我的实践中遇到了一个十分严重的问题

首先描述一下我的实验我的应用程序需要接收传感器节点从串口发回的查询数据并将结果以图标的形式显示出来串口设定的波特率是川口每隔毫秒返回一组数据(大约是字节左右)周期(即持续时间)为秒实测的时候在一个周期内应该返回多个字节而用事件监听模型我最多只能收到不到字节不知道这些字节都跑哪里去了也不清楚到底丢失的是那部分数据值得注意的是这是我将serialEvent()中所有处理代码都注掉只剩下打印代码所得的结果数据丢失的如此严重是我所不能忍受的于是我决定采用其他方法

串口读数据的线程模型

这个模型顾名思义就是将接收数据的操作写成一个线程的形式:

publicvoidstartReadingDataThread(){ ThreadreadDataProcess=newThread(newRunnable(){ publicvoidrun(){ while(newData!=){ try{ newData=is read(); System out println(newData);//其他的处理过程………}catch(IOExceptionex){ System err println(ex); return;}} readDataProcess start();}

在我的应用程序中我将收到的数据打包放到一个缓存中然后启动另一个线程从缓存中获取并处理数据两个线程以生产者—消费者模式协同工作数据的流向如下图所示

这样我就圆满解决了丢数据问题然而没高兴多久我就又发现了一个同样严重的问题虽然这回不再丢数据了可是原本一个周期(秒)之后传感器节电已经停止传送数据了但我的串口线程依然在努力的执行读串口操作在控制台也可以看见收到的数据仍在不断的打印原来由于传感器节点发送的数据过快而我的接收线程处理不过来所以InputStream就先把已到达却还没处理的字节缓存起来于是就导致了明明传感器节点已经不再发数据了而控制台却还能看见数据不断打印这一奇怪的现象唯一值得庆幸的是最后收到数据确实是左右字节没出现丢失现象然而当处理完最后一个数据的时候已经快分半钟了这个时间远远大于节点运行周期这一延迟对于一个实时的显示系统来说简直是灾难!

后来我想是不是由于两个线程之间的同步和通信导致了数据接收缓慢呢?于是我在接收线程的代码中去掉了所有处理代码仅保留打印收到数据的语句结果依然如故看来并不是线程间的通信阻碍了数据的接收速度而是用线程模型导致了对于发送端数据发送速率过快的情况下的数据接收延迟这里申明一点就是对于数据发送速率不是如此快的情况下前面者两种模型应该还是好用的只是特殊情况还是应该特殊处理

第三种方法

痛苦了许久(Boss天天催我L)之后偶然的机会我听说TinyOS中(又是开源的)有一部分是和我的应用程序类似的串口通信部分于是我下载了它的 x版的Java代码部分参考了它的处理方法解决问题的方法说穿了其实很简单就是从根源入手根源不就是接收线程导致的吗那好我就干脆取消接收线程和作为中介的共享缓存而直接在处理线程中调用串口读数据的方法来解决问题(什么为什么不把处理线程也一并取消?都取消应用程序界面不就锁死了吗?所以必须保留)于是程序变成了这样

publicbyte[]getPack(){ while(true){//PacketLength为数据包长度 byte[]msgPack=newbyte[PacketLength]; for(inti=;i<PacketLength;i++){ if((newData=is read())!=){ msgPack[i]=(byte)newData; System out println(msgPack[i]);}} returnmsgPack;}}

在处理线程中调用这个方法返回所需要的数据序列并处理之这样不但没有丢失数据的现象行出现也没有数据接收延迟了这里唯一需要注意的就是当串口停止发送数据或没有数据的时候is read()一直都返回如果一旦在开始接收数据的时候发现就不要理它继续接收直到收到真正的数据为止

结束语

lishixinzhi/Article/program/Java/hx/201311/26605

Java串口通信总结

最近在研究一个东西要用到串口的读写通过读取串口获取一个指令然后根据该指令通过配置文件获取其他的信息再通过串口进行做下一步的一系列操作

java读写串口要用到的是javax扩展类库javam它是一系列的标准该类库在sun的官网上只提供linux版本由于我所应用的平台是win所以找了个win的实现在此过程中遇到了一系列的问题后来终于解决问题并完成了通过读写串口进行通信的功能在此对其java读写串口的情况做个简要说明

首先下载javam包然后将其解压解压后需要做的就是配置串口通信相关东西下面是自己使用的时候的配置

把m properties文件拷贝到Java运行时环境的lib目录中即

C:\Program Files\Java\jdk _ \lib\m properties

C:\Program Files\Java\jdk _ \jre\lib\m properties

把win dll拷贝到C:\windows\system \和 C:\Program Files\Java\jdk _ \jre\bin\下

把m jar放到Java运行时环境的lib目录中即C:\Program Files\Java\jdk _ \lib\m jar

在环境变量的CLASSPATH中添加m jar如%JAVA_HOME%\lib\m jar;

然后通过的API来实现串口的读写其实API相当简单如下代码

Java代码

CommPortIdentifier serialPortId= CommPortIdentifier getPortIdentifier();

SerialPort port=(SerialPort) serialPortId open( Read);//打开串口其中参数是用来设置打开串口的超时时间

port setSerialPortParams();//设置的波特率数据位停止位校验方式等

//从串口中得到输入输出流了

OutputStream out= port getOutputStream();

out write(buffer);

out flush();

InputStream in= port getInputStream();

in read(data);//data是一个byte[]

CommPortIdentifier serialPortId= CommPortIdentifier getPortIdentifier(); SerialPort port=(SerialPort) serialPortId open( Read);//打开串口其中参数是用来设置打开串口的超时时间 port setSerialPortParams();//设置的波特率数据位停止位校验方式等//从串口中得到输入输出流了 OutputStream out= port getOutputStream(); out write(buffer); out flush(); InputStream in= port getInputStream(); in read(data);//data是一个byte[]

lishixinzhi/Article/program/Java/hx/201311/26266

如何使用Java实现两台PC机之间的串口通信

//SocketClient

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.io.PrintWriter;

import java.net.Socket;

import java.util.Scanner;

import org.apache.log4j.Logger;

import com.sitinspring.server.ResponseThread;

/**

* Socket客户端

*@author: sitinspring(junglesong@gmail.com)

*@date: 2007-11-16

*/

public class SocketClient{

private static Logger logger= Logger.getLogger(ResponseThread.class);

public static void main(String[] args){

try{

Socket socket=new Socket("127.0.0.1",2009);

logger.info("客户端向服务器发起请求.");

try{

InputStream inStream= socket.getInputStream();

OutputStream outStream= socket.getOutputStream();

Scanner in= new Scanner(inStream);

PrintWriter out= new PrintWriter(outStream);

out.println("地震高岗一派溪山千古秀");

out.flush();

while(in.hasNextLine()){

String line= in.nextLine();

logger.info("客户端获得响应文字="+ line);

}

} finally{

socket.close();

}

} catch(IOException ex){

ex.printStackTrace();

}

}

}

//Member

import java.util.Comparator;

public class Member implements Comparable{

private String name;

private int age;

public Member(String name, int age){

this.name= name;

this.age= age;

}

public int compareTo(Object obj){

Member another=(Member) obj;

//return this.name.compareTo(another.name);

return this.age-another.age;

}

public String toString(){

return"Member name="+name+" age="+age;

}

}

//Main

import java.util.Arrays;

import java.util.List;

public class Main{

public static void main(String[] args){

String[] arr={"Andy","Bill","Cindy","Dell"};

List<String> ls=Arrays.asList(arr);

for(String str:ls){

System.out.println(str);

}

/*List<String> ls=new ArrayList<String>();

ls.add("Felex");

ls.add("Gates");

ls.add("Andy");

ls.add("Bill");

ls.add("Cindy");

ls.add("Dell");

Object[] arr=ls.toArray();

for(Object obj:arr){

System.out.println((Object)obj);

}*/

/*Collections.sort(ls);

for(Member member:ls){

System.out.println(member);

}*/

/*Member member=new Member("Edin",28);

ls.remove(member);

ls.remove(2);

ls.clear();

List ls2=new ArrayList();*/

/*for(Member member:ls){

// member

}*/

/*for(int i=0;i<ls.size();i++){

Member member=ls.get(i);

}*/

/*for(Iterator it=ls.iterator();it.hasNext();){

Member member=(Member)it.next();

}

List<Member> ls2=new ArrayList<Member>();

ls2.add(new Member("Felex",21));

ls2.add(new Member("Gates",23));

ls.addAll(ls2);

ls2.*/

/*List ls3=null;

System.out.println(ls3.isEmpty());*/

/*List ls3=null;

System.out.println(ls2.isEmpty());*/

/*ls.

ls.indexOf(o)

ls.contains(o)*/

//ls2.add(1);

}

}

//ResponseThread这个是server的先启动client(服务器)再启动它。上面三个类是client放在一个文件夹中

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.io.PrintWriter;

import java.net.ServerSocket;

import java.net.Socket;

import java.util.Scanner;

import org.apache.log4j.Logger;

/**

*响应线程,建立ServerSocket响应客户端Socket请求

*@author: sitinspring(junglesong@gmail.com)

*@date: 2007-11-16

*/

public class ResponseThread implements Runnable{

private static Logger logger= Logger.getLogger(ResponseThread.class);

//用于与客户端通信的Socket

private Socket incomingSocket;

public ResponseThread(Socket incomingSocket){

this.incomingSocket= incomingSocket;

}

public void run(){

try{

try{

//输入流

InputStream inStream= incomingSocket.getInputStream();

//输出流

OutputStream outStream= incomingSocket.getOutputStream();

Scanner in= new Scanner(inStream);

PrintWriter out= new PrintWriter(outStream,true);

while(in.hasNextLine()){

String line= in.nextLine();

logger.info("从客户端获得文字:"+line);

String responseLine=line+"门朝大海三河合水万年流";

out.println(responseLine);

logger.info("向客户端送出文字:"+responseLine);

}

} finally{

incomingSocket.close();

}

} catch(IOException ex){

ex.printStackTrace();

}

}

public static void main(String[] args){

try{

ServerSocket socket=new ServerSocket(2009);

logger.info("开始监听");

while(true){

Socket incomingSocket=socket.accept();

logger.info("获得来自"+incomingSocket.getInetAddress()+"的请求.");

ResponseThread responseThread=new ResponseThread(incomingSocket);

Thread thread=new Thread(responseThread);

thread.start();

}

} catch(IOException ex){

ex.printStackTrace();

}

}

}

END,本文到此结束,如果可以帮助到大家,还望关注本站哦!

大型门户网站建设(网站建设的目的是什么)软件开发公司(知名的软件开发公司有哪些)