您当前的位置:首页 > 精选问答 > 内容

java串口实时通讯 java串口通信编程实例

java串口实时通讯 java串口通信编程实例

串行通信原理1。串行通信指的是逐位发送和接收字节。虽然比逐字节并行通信慢,但串口可以用一条线发送数据,用另一条线接收数据。

2.串口是计算机上非常通用的设备通信协议(不要与通用串行总线或USB混淆)

3.串行端口用于传输ASCII字符。使用3条线路完成通信:(1)接地,(2)发送和(3)接收。因为串行通信是异步的,端口可以在一条线路上发送数据,在另一条线路上接收数据。其他线是用来握手的,但不是必须的。串行通信最重要的参数是比特率、数据位、停止位和奇偶校验。对于两个通信端口,这些参数必须匹配。

4.-232(ANSI/EIA-232标准)是IBM-PC及其兼容机的串行连接标准,RS-422(EIA RS-422-AStandard)是Apple 苹果麦金塔电脑。RS-485(EIA-485标准)是对RS-422的改进。

说到开源,我恐怕很少有人不知道不要称赞它。学生们通过开源代码学到了知识,程序员们也收获了其他人的成功经验,并能按时完成他们的项目,企业也通过开源软件赚了钱.总之,大家都开心。但是开源软件或者类库的第一个缺点就是大多缺乏详细的文档和使用实例,或者你可以随便使用软件代码,也就是文档、实例和后期服务收费。难怪,毕竟,就像一个著名的NBA球员说的那样。我要养家糊口,所以不要。不要和我谈1000万美元以下的合同,否则我就&# 039;我宁愿失业。"是的,支持开源的人要养家糊口。收点钱也不过分。如果你想在不花钱的情况下学习知识,你只能利用互联网。我只是想提供一些有价值的建议,为开源事业尽一份绵薄之力。对你的项目来说,即使是解决一个小问题也足够了。

虽然我这个系列介绍的不是Web框架,也不是开源服务器,但是我相信作为一个程序员,会遇到各种各样的问题。有时候越简单的问题越难。地方越小,你就越能I don’我找不到一个称手的人。只要你不不要只处理建筑,组件和框架一整天,我相信你会用我说的话。

串行通信简介

1.1通用Java串行包

1.2串行包的安装(Windows下)

串行API概述

2.1 javax.comm.CommPort

2.2 javax . comm . comm标识符

2.3 javax.comm.SerialPort

2.4串行API示例

2.4.1列出本机所有可用的串口。

2.4.2串口参数配置

2.4.3串口读写

串行通信的常见模式及其问题

3.1事件监控模型

3.2串口读取数据的线程模型

3.3第三种方法

4结束语

串行通信简介嵌入式系统或传感器网络的很多应用和测试都需要通过PC机与嵌入式设备或传感器节点进行通信。其中,最常用的接口是RS-232串口和并口。(考虑到USB接口的复杂性,不需要大量的数据传输,USB接口在这里用起来还是太奢侈了。此外,目前,我还没有除了SUN有一个支持USB的包之外,我没见过其他直接支持USB的Java类库。)Suncommapi分别提供对普通RS232串口和IEEE1284并口通信的支持。RS-232-C(又称EIA RS-232-C,以下简称RS232)是美国电子工业协会(EIA)于1970年联合贝尔系统公司、调制解调器制造商和计算机终端制造商制定的串行通信标准。RS232是一种全双工通信协议,可以同时接收和发送数据。

1.1通用Java串行包

目前常见的Java串行包有SUN在1998年发布的串行通信API:com m2 . 0 . jar(Windows下)和com m3 . 0 . jar(Linux/Solaris);IBM 的串行通信API和一个开源实现。鉴于孙的API在Windows下普遍使用,而IBM 的实现与SUN 的API级别,而且开源的实现不像两大厂商的产品那么让人放心,这里只是介绍一下孙Windows平台下的串行通信API。

1.2串行包的安装(Windows下)

去找孙的网站并下载javacomm20-win32.zip内容如下:

根据其说明(Readme.html),如果要使用串行包进行串行通信,除了设置环境变量之外,还应该将win32com.dll复制到《JDK》 /bin目录。将comm.jar复制到《JDK》/lib;将javax.comm.properties也复制到《JDK》 /lib目录中。但是,仅在运行串行包时这样做是不够的。通常,跑步时java MyApp ,MyApp是由JRE下的虚拟机启动的。我们只把上面的文件复制到JDK对应的目录下,所以应用程序会提示找不到串口。这个问题的解决方法很简单,我们只需要将上述文件放在JRE对应的目录下即可。

值得注意的是,在网络应用中使用串行API时,还会出现其他更复杂的问题。如果你有兴趣,可以去CSDN社区看看的帖子关于网页上Applet用javacomm20读取客户端串口的问题。

2串行API 2.1概述javax.comm.CommPort

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

2.2 javax . comm . comm标识符

该类主要用于管理和设置串口,是串口访问控制的核心类。主要包括以下方法

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

打开通信端口进行l io操作。

我决定港口的所有权。

处理端口所有权的争用。

管理由端口所有权变更引起的事件。

2.3 javax.comm.SerialPort

这个类用于描述RS-232串行通信端口的底层接口。它定义了串行通信所需的最小功能集。通过它,用户可以直接读写和设置串口。

2.4串行API示例

大段文字不如小例子清晰。让让我们来看看Serial Demo中的一小段代码,serial package的一个例子,加深我们对serial API核心类使用的理解。

2.4.1列出本机所有可用的串口。

void listPortChoices() {

通信标识符portId

enumeration en=commportidentifier . getportidentifiers();

//遍历端口。

while(en . hasmorelements()){

portId=(CommPortIdentifier)en . nextelement();

if(portid . getporttype()==CommPortIdentifier。PORT_SERIAL) {

system . out . println(portid . getname());

}

}

port choice . select(parameters . get portname());

}

上面的代码可以列出当前系统中所有可用的串口名称,在我的机器上输出结果是COM1和COM3。

2.4.2串口参数配置

通常,串行端口有以下参数,可以在串行端口打开之前进行配置:

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

SerialPort sPort

尝试{

sport . setserialportparams(BaudRate,Databits,Stopbits,Parity);

//设置输入/输出控制流

sport . setflowcontrolmode(flow control in | flow control out);

} catch(UnsupportedCommOperationException e){ }

2.4.3串口读写

在读写之前,您需要打开一个串行端口:

CommPortIdentifier portId=CommPortIdentifier . getportidentifier(port name);

尝试{

serial port sport=(serial port)portid . open(串行端口所有者名称超时等待时间);

} catch(PortInUseException e){///如果端口被占用,则抛出此异常。

抛出新的serial connection exception(e . getmessage());

}

//用于将数据写入串口

output stream OS=new BufferedOutputStream(sport . get output stream());

OS . write(int data);

//用于从串口读取数据

InputStream is=new BufferedInputStream(sport . getinputstream());

int received data=is . read();

读出的是int类型,可以转换成你需要的其他类型。

这里需要注意的是,由于Java语言中没有无符号类型,即所有类型都是有符号的,所以在从byte转换为int时要特别注意。如果byte的最高位是1,那么在转换为int类型时,它将被1占用。这样,原本10000000的字节类型数变成了int类型,变成了1111111000000,这是一个严重的问题,应该避免。

串口通信的一般模式及其问题终于唠叨完了我最讨厌的基础知识。现在让让我们开始这次的重点——串行应用的研究。因为向串口写入数据非常简单,所以这里我们只关注从串口读取数据。一般来说,串行通信应用程序有两种模式,一种是实现SerialPortEventListener接口,监控各种串行事件并进行相应的处理;另一种是建立一个独立的接收线程来负责接收数据。因为这两种方法在某些情况下存在严重的问题(至于什么问题,我这里先卖个关子J),所以我的实现是用第三种方法来解决这个问题。

3.1事件监控模型

现在让让我们看看事件监控模型是如何工作的。

首先,你需要加上implements serial portevent listener 到您的端口控制类(如SManager)

l在初始化期间添加以下代码:

尝试{

serial port sport . addevent listener(s manager);

} catch(TooManyListenersException e){

sport . close();

抛出新的SerialConnectionException("添加了太多侦听器");

}

sport . notifyondata available(true);

l覆盖公共void串行事件(串行端口事件e)方法,其中判断以下事件:

双向通信中断。

CD载体检测。

CTS-清除发送。

DATA _ AVAILABLE-数据已经到达。

DSR-数据设备准备就绪。

有限元框架误差。

OE-溢出错误。

输出缓冲区已被清空。

奇偶校验错误。

振铃指示。

一般最常用的是DATA _ AVAILABLE——串口有数据到达事件。也就是说,当数据到达串口时,可以在serialEvent中接收并处理接收到的数据。然而,在我的实践中,我遇到了一个非常严重的问题。

首先描述一下我的实验:我的应用程序需要接收传感器节点从串口发回的查询数据,并以图标的形式显示结果。串口的设定波特率为115200,川口每隔128毫秒返回一组数据(约30字节),周期(即持续时间)为31秒。测量时,一个周期应该返回4900多个字节,但我用事件监控模型最多只能收到不到1500个字节。我不我不知道这些字节都到哪里去了,我也不知道。I don’我不知道到底丢失了哪一部分数据。它值得注意的是,这是我记下serialEvent()中所有处理代码,只留下打印代码时的结果。数据丢失如此严重,以至于我无法我受不了了,所以我决定采用其他方法。

3.2串口读取数据的线程模型

顾名思义,这个模型是以线程的形式编写接收数据的操作:

public void startReadingDataThread(){

Thread read data process=new Thread(new Runnable(){

公共无效运行(){

while (newData!=-1) {

尝试{

new data=is . read();

system . out . println(new data);

//其他处理程序

………。

} catch (IOException ex) {

system . err . println(ex);

返回;

}

}

read data process . start();

}

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

就这样,我成功解决了数据丢失的问题。然而,它没有没过多久,我就发现了另一个同样严重的问题:尽管我没有这次丢数据,原来的周期(31秒)过后,传感器省电停止传输数据,但是我的串口程序还在尝试读取串口,接收到的数据还在控制台上打印。本来是因为传感器节点发送的数据太快,但是我的接收线程可以不能处理它,所以InputStream缓存已经到达但还没有到达的字节。t还未处理,导致传感器节点不再发送数据,但控制台仍能看到数据不断打印的奇怪现象。唯一的好消息是,最终接收到的数据约为4900字节,没有丢失。但是处理最后一个数据的时候,差不多是一分半钟,比节点的运行周期长很多。这种延迟对于实时显示系统来说是一场灾难!

后来我想,是不是因为两个线程的同步和通信,导致数据接收慢?于是我从接收线程的代码中去掉了所有的处理代码,只保留了打印接收数据的语句,结果还是一样。似乎并不是线程间的通信阻碍了数据接收速度,而是在发送端数据发送速率过快时,线程模型导致了数据接收延迟。这里要明确的是,在数据传输速率没有那么快的情况下,前两种模型应该还是能很好的工作,只是特殊情况要特殊对待。

3.3第三种方法

苦了半天(老板天天催),一个偶然的机会,听说TinyOS的一部分(又是开源的)是和我的应用类似的串口通信部分,于是下载了它1.x版本的Java代码部分,参考了它的处理方法。说白了,解决问题的方法其实很简单,就是从根源入手。不是接收线程引起的根本原因?嗯,我ll干脆取消接收线程和共享缓存作为中介,直接调用处理线程中的串口数据读取方法解决问题(什么,为什么不把处理线程也取消呢?——唐全部取消应用界面锁起来?所以必须保留)所以程序变成了这样:

public byte[] getPack(){

while (true) {

//PacketLength是数据包长度。

byte[] msgPack=新字节[packet length];

for(int I=0;我《包装长度;i ){

if( (newData=is.read())!=-1){

msg pack[I]=(byte)new data;

system . out . println(msg pack[I]);

}

}

返回msgPack

}

}

在处理线程中调用这个方法,返回需要的数据序列并进行处理,这样就不会有数据丢失,也不会有数据接收延迟。这里唯一需要注意的是,当串口停止发送数据或者没有数据时,is.read()总是返回-1。如果在接收数据开始时发现-1,就忽略它,继续接收,直到接收到真正的数据。

4结论本文介绍了串行通信的基础知识和几种常用的模式。通过实践,提出并最终解决了一些问题。值得注意的是,对于第一种方法,我把传感器的发送时间从128毫秒增加到了512毫秒,仍然存在严重的数据丢失现象。因此,如果您的应用程序需要非常精确的结果,并且数据传输速率非常快,您最好不要用第一种方法。至于第二种方法,因为问题是由线程引起的,所以对于不同的机器应该有不同的表现,对于那些处理多线程比较好的机器应该更好。但是我的机器是InterPentium 4 3.0双核CPU 512DDR内存,所以延迟这么厉害,你Inter强多少CPU?所以对于数据量较大的传输,最好使用第三种方法。但是,这个世界上的问题很多,未知的问题比已知的多。也许还有其他问题。欢迎你通过以下联系方式和我一起学习。

标签:通信数据问题


声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,谢谢。

上一篇: 光学鼠标和光电鼠标哪个好(光机鼠标和光电鼠标有什么不同哪个好)

下一篇: 惠威功放的全部型号(惠威功放)



推荐阅读

网站内容来自网络,如有侵权请联系我们,立即删除! | 软文发布 | 粤ICP备2021106084号