Java串口通信详解
- 格式:doc
- 大小:275.50 KB
- 文档页数:33
java调用coms端口串口通信的方法。
首先需要下到串口驱动。
javacomm20-win32.zip去sun的主页应该有下的。
在这个驱动中有comm.jar,m.properties,win32com.dll这么3个重要的文件。
1、首先配置驱动,把m.properties,win32com.dll拷贝到你的jdk 中具体位置为C:\Program Files\Java\jdk1.6.0_06\bin然后配置windows系统环境变量,在path中加入C:\ProgramFiles\Java\jdk1.6.0_06\bin;打开你的java工程,配置user library,并导入comm.jar包。
2、现在就可以开始写代码了。
串口读写代码如下CommPortIdentifier portID =CommPortIdentifier.getPortIdentifier(com);//1,先拿到Identifier//其中com是String类型的,传入的是串口名com="COM1";SerialPort port = (SerialPort)portID.open("MyComm", 100000000);//2,打开串口//"MyComm"是串口名,100000000是串口过期时间(ms)。
port.setSerialPortParams(rate, databits,stopbit, parity);//3,设置串口属性//rate 波特率(默认9600),databits载波位(默认8),stopbit停止位(默认1),parity校验位(默认0无校验)port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);//4(可选)设置数据流控制模式,默认为无port.close();//关闭串口3、串口读入写出流。
java串⼝通信java串⼝通信,由于没有相应的串⼝硬件,选了⼀款windows串⼝虚拟机机器1. 准备串⼝模拟器Launch Virtual Serial Port Driver模拟两对四个串⼝,COM1发送数据给COM2,COM3发送数据给COM4java包<dependency><groupId>com.fazecast</groupId><artifactId>jSerialComm</artifactId><version>[2.0.0,3.0.0)</version></dependency>2. java源代码mport com.fazecast.jSerialComm.SerialPort;import com.fazecast.jSerialComm.SerialPortDataListener;import com.fazecast.jSerialComm.SerialPortEvent;import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/*** @Classname ComTest* @Description com串⼝通信* @Date 2021/9/4 10:44* @Created by huangsm*/public class ComTest {/*** <com名称,SerialPort>串⼝通信map,存储串⼝名称与串⼝信息*/private Map<String, SerialPort> comMap = new HashMap<>();/*** com⼝列表*/private List<String> comList = new ArrayList<>();public ComTest() {//将所有的串⼝信息放⼊comlist,comMap中SerialPort[] commPorts = SerialPort.getCommPorts();for (SerialPort commPort : commPorts) {comList.add(commPort.getSystemPortName());comMap.put(commPort.getSystemPortName(), commPort);//监听所有串⼝通信的数据commPort.openPort();commPort.addDataListener(new SerialPortDataListener() {@Overridepublic int getListeningEvents() {return SerialPort.LISTENING_EVENT_DATA_RECEIVED;}@Overridepublic void serialEvent(SerialPortEvent serialPortEvent) {byte[] newData = serialPortEvent.getReceivedData();System.err.println(String.format("串⼝%s接收到数据⼤⼩:%s,串⼝数据内容:%s",serialPortEvent.getSerialPort().getSystemPortName(),newData.length,new String(newData))); }});}}public static void main(String[] args) throws Exception {ComTest comTest = new ComTest();List<String> comList = List;Map<String, SerialPort> comMap = Map;BufferedReader systemIn = new BufferedReader(new InputStreamReader(System.in));while (true) {System.out.println("你的可以通信的串⼝列表");for (String comName : comList) {System.out.println("========" + comName + "========"); }System.out.println("请输⼊你的串⼝:");String com = systemIn.readLine();if(!comList.contains(com)){System.out.println("输⼊的串⼝不正确:");continue;}System.out.println("输⼊你要发送的消息:");String msg = systemIn.readLine();SerialPort serialPort = comMap.get(com);serialPort.writeBytes(msg.getBytes(),msg.getBytes().length);//这⾥是让串⼝先接收到数据再重新发送数据Thread.sleep(1000);}}}3. 运⾏结果你的可以通信的串⼝列表========COM1================COM2================COM3================COM4========请输⼊你的串⼝:COM3输⼊你要发送的消息:137912037串⼝COM4接收到数据⼤⼩:9,串⼝数据内容:137912037你的可以通信的串⼝列表========COM1================COM2================COM3================COM4========请输⼊你的串⼝:。
Javaspringboot串⼝通信基于win10 环境1. Virtual Serial Port Driver Pro 开通两个虚拟串⼝2. 打开串⼝调试助⼿3. 代码逻辑<?xml version="1.0" encoding="UTF-8"?><project xmlns="/POM/4.0.0" xmlns:xsi="/2001/XMLSchema-instance" xsi:schemaLocation="/POM/4.0.0 https:///xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.10.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>port</artifactId><version>0.0.1-SNAPSHOT</version><name>port</name><description>Demo Serial Port project for Spring Boot</description><properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><lombok.version>1.18.16</lombok.version><ng3.version>3.11</ng3.version><fastjson.version>1.2.75</fastjson.version></properties><dependencies><dependency><groupId>com.RXTXcomm</groupId><artifactId>RXTXcomm</artifactId><version>1.0.1</version><scope>system</scope><systemPath>${project.basedir}/src/main/resources/lib/RXTXcomm.jar</systemPath> </dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version><scope>provided</scope></dependency><dependency><groupId>mons</groupId><artifactId>commons-lang3</artifactId><version>${ng3.version}</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>${fastjson.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></configuration></plugin></plugins><resources><resource><directory>src/main/resources</directory><includes><include>**/*.*</include></includes><filtering>true</filtering></resource><resource><directory>src/main/lib</directory><targetPath>BOOT-INF/lib/</targetPath><includes><include>**/*.jar</include></includes></resource></resources></build></build></project>package com.example.port;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import javax.annotation.PreDestroy;@SpringBootApplicationpublic class PortApplication {public static void main(String[] args) {SpringApplication.run(PortApplication.class, args);}@PreDestroypublic void destory() {//关闭应⽤前关闭端⼝SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();serialPortUtil.removeListener(PortInit.serialPort, new MyLister());serialPortUtil.closePort(PortInit.serialPort);}}package com.example.port;import gnu.io.SerialPort;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.ApplicationArguments;import org.springframework.boot.ApplicationRunner;import ponent;import java.util.ArrayList;@Componentpublic class PortInit implements ApplicationRunner {public static SerialPort serialPort = null;@Value("${portname}")private String portname;@Overridepublic void run(ApplicationArguments args) {//TestA();//查看所有串⼝SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();ArrayList<String> port = serialPortUtil.findPort();System.out.println("发现全部串⼝:" + port);System.out.println("打开指定portname:" + portname);//打开该对应portname名字的串⼝PortInit.serialPort = serialPortUtil.openPort(portname, 9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);//给对应的serialPort添加监听器serialPortUtil.addListener(PortInit.serialPort, new MyLister());}}package com.example.port;/*** @author 7788* @version 1.0* @date 2021/4/6 上午 9:26* @location wuhan*/import gnu.io.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.slf4j.LoggerFactory;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.ArrayList;import java.util.Enumeration;import java.util.TooManyListenersException;public class SerialPortUtil {private static final Logger logger = LoggerFactory.getLogger(SerialPortUtil.class);private static SerialPortUtil serialPortUtil = null;static {//在该类被ClassLoader加载时就初始化⼀个SerialTool对象if (serialPortUtil == null) {serialPortUtil = new SerialPortUtil();}}//私有化SerialTool类的构造⽅法,不允许其他类⽣成SerialTool对象private SerialPortUtil() {}/*** 获取提供服务的SerialTool对象** @return serialPortUtil*/public static SerialPortUtil getSerialPortUtil() {if (serialPortUtil == null) {serialPortUtil = new SerialPortUtil();}return serialPortUtil;}/*** 查找所有可⽤端⼝** @return可⽤端⼝名称列表*/public ArrayList<String> findPort() {//获得当前所有可⽤串⼝Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();ArrayList<String> portNameList = new ArrayList<>();//将可⽤串⼝名添加到List并返回该Listwhile (portList.hasMoreElements()) {String portName = portList.nextElement().getName();portNameList.add(portName);}return portNameList;}/*** 打开串⼝** @param portName 端⼝名称* @param baudrate 波特率* @param databits 数据位* @param parity 校验位(奇偶位)* @param stopbits 停⽌位* @return串⼝对象* // * @throws SerialPortParameterFailure 设置串⼝参数失败* // * @throws NotASerialPort 端⼝指向设备不是串⼝类型* // * @throws NoSuchPort 没有该端⼝对应的串⼝设备* // * @throws PortInUse 端⼝已被占⽤*/public SerialPort openPort(String portName, int baudrate, int databits, int parity, int stopbits) { try {//通过端⼝名识别端⼝CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);//打开端⼝,并给端⼝名字和⼀个timeout(打开操作的超时时间)CommPort commPort = portIdentifier.open(portName, 2000);//判断是不是串⼝if (commPort instanceof SerialPort) {SerialPort serialPort = (SerialPort) commPort;try {//设置⼀下串⼝的波特率等参数serialPort.setSerialPortParams(baudrate, databits, stopbits, parity);} catch (UnsupportedCommOperationException e) {}System.out.println("Open " + portName + " sucessfully !");return serialPort;} else {logger.error("不是串⼝");}} catch (NoSuchPortException e1) {logger.error("没有找到端⼝");e1.printStackTrace();} catch (PortInUseException e2) {logger.error("端⼝被占⽤");e2.printStackTrace();}return null;}/*** 关闭串⼝** @param serialPort 待关闭的串⼝对象*/public void closePort(SerialPort serialPort) {if (serialPort != null) {serialPort.close();}}/*** 往串⼝发送数据** @param serialPort 串⼝对象* @param order 待发送数据* // * @throws SendDataToSerialPortFailure 向串⼝发送数据失败* // * @throws SerialPortOutputStreamCloseFailure 关闭串⼝对象的输出流出错 */public void sendToPort(SerialPort serialPort, byte[] order) {OutputStream out = null;try {out = serialPort.getOutputStream();out.write(order);out.flush();} catch (IOException e) {e.printStackTrace();} finally {try {if (out != null) {out.close();}} catch (IOException e) {e.printStackTrace();}}}/*** 从串⼝读取数据** @param serialPort 当前已建⽴连接的SerialPort对象* @return读取到的数据* // * @throws ReadDataFromSerialPortFailure 从串⼝读取数据时出错* // * @throws SerialPortInputStreamCloseFailure 关闭串⼝对象输⼊流出错*/public byte[] readFromPort(SerialPort serialPort) {InputStream in = null;byte[] bytes = null;try {in = serialPort.getInputStream();int bufflenth = in.available();while (bufflenth != 0) {bytes = new byte[bufflenth];in.read(bytes);bufflenth = in.available();}} catch (IOException e) {e.printStackTrace();} finally {} finally {try {if (in != null) {in.close();}} catch (IOException e) {e.printStackTrace();}}return bytes;}/*** 添加监听器** @param port 串⼝对象* @param listener 串⼝监听器* // * @throws TooManyListeners 监听类对象过多*/public void addListener(SerialPort port, SerialPortEventListener listener) {try {//给串⼝添加监听器port.addEventListener(listener);//设置当有数据到达时唤醒监听接收线程port.notifyOnDataAvailable(true);//设置当通信中断时唤醒中断线程port.notifyOnBreakInterrupt(true);} catch (TooManyListenersException e) {// throw new TooManyListeners();logger.error("太多监听器");e.printStackTrace();}}/*** 删除监听器** @param port 串⼝对象* @param listener 串⼝监听器* // * @throws TooManyListeners 监听类对象过多*/public void removeListener(SerialPort port, SerialPortEventListener listener) {//删除串⼝监听器port.removeEventListener();}}package com.example.port;import com.alibaba.fastjson.JSON;import com.example.port.ISO8583.ISO8583;import com.example.port.ISO8583.TransISO8583MessageUtil;import gnu.io.SerialPortEvent;import gnu.io.SerialPortEventListener;import lombok.SneakyThrows;import java.util.Date;/*** @author best*/public class MyLister implements SerialPortEventListener {@SneakyThrows@Overridepublic void serialEvent(SerialPortEvent arg0) {if (arg0.getEventType() == SerialPortEvent.DATA_AVAILABLE) {SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();byte[] bytes = serialPortUtil.readFromPort(PortInit.serialPort);String byteStr = new String(bytes, 0, bytes.length).trim();// System.out.println(new Date() + "【读到的字节数组】:-----" + byteStr);// ISO8583 aiISO8583DTO = (ISO8583) TransISO8583MessageUtil.unpackISO8583(ISO8583.class, byteStr); // System.out.println("UNPACK ISO8583: " + JSON.toJSONString(aiISO8583DTO));System.out.println("===========start===========");System.out.println(new Date() + "【读到的字节数组】:-----" + byteStr);String needData = printHexString(bytes);System.out.println(new Date() + "【字节数组转字符串】:-----" + needData);System.out.println(new Date() + "【16进制字符串转字符串】:" + hexStringToString(needData));System.out.println("===========end===========");// ISO8583 aiiso8583DTO = new ISO8583();//// aiiso8583DTO.setCardNo02(String.valueOf(System.currentTimeMillis()));// aiiso8583DTO.setTransProcCode03("123456");// aiiso8583DTO.setTransAmt04("000010000000");// aiiso8583DTO.setSysTrackNo11("888888");// aiiso8583DTO.setServiceInputModeCode22("100");// aiiso8583DTO.setServiceConditionCode25("66");// aiiso8583DTO.setCardAcceptorTerminalID41("08022206");// aiiso8583DTO.setCardAcceptorID42("000100000000005");// aiiso8583DTO.setAdditionalDataPrivate48("0000");// aiiso8583DTO.setCurrencyCode49("168");// aiiso8583DTO.setEWalletTransInfo58("53560118FFFFFFFFFFFF03104890100000006059FFFFFFFF0101000200000064020000080000032017122310225672FB4788000 // aiiso8583DTO.setFld60Domain60("41000006666");// aiiso8583DTO.setOriginalInfoDomain61("000666000181");// aiiso8583DTO.setFld63Domain63("0000000000000000");// String maxBitmap = "7020048000C1805B";// final String TPDU = "6000000000";// final String HEAD = "612200000000";// String sendMsg = TransISO8583MessageUtil.packISO8583(aiiso8583DTO, maxBitmap, TPDU, HEAD, "0300");//接收到消息后回复⼀个当前时间serialPortUtil.sendToPort(PortInit.serialPort, new Date().toString().getBytes());}}// 字节数组转字符串private String printHexString(byte[] b) {StringBuffer sbf = new StringBuffer();for (int i = 0; i < b.length; i++) {String hex = Integer.toHexString(b[i] & 0xFF);if (hex.length() == 1) {hex = '0' + hex;}sbf.append(hex.toUpperCase() + " ");}return sbf.toString().trim();}/*** 16进制转换成为string类型字符串** @param s* @return*/public static String hexStringToString(String s) {if (s == null || s.equals("")) {return null;}s = s.replace(" ", "");byte[] baKeyword = new byte[s.length() / 2];for (int i = 0; i < baKeyword.length; i++) {try {baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));} catch (Exception e) {e.printStackTrace();}}try {s = new String(baKeyword, "UTF-8");new String();} catch (Exception e1) {e1.printStackTrace();}return s;}}接下来启动项⽬就可以了,可以完善MyLister的功能对收到的消息进⾏处理,然后回复消息⽐如ISO8583的报⽂解析并http调⽤接⼝更新数据。
Java串口通信编程指导Java串口通信编程概述在java中,利用Java Communication包能够操作串口,但官方的包在3.0之后就只支持Linux和Solaris平台了,Windows平台的只支持到98年出的2.0版本,只是在XP下还能使用。
另外,也能够用开源的Rxtx实现串口通信,那个地点仅以Java Communication包,在Windows平台实现串口通信进行讲明。
前期预备下载Java Communication包下载地址如下:/Jolt/javacomm20-win32.zip。
配置解压缩javacomm20-win32.zip把win32com.dll拷贝到{JA V A_HOME}\jre\bin把comm.jar拷贝到{JA V A_HOME}\jre\lib\extset CLASSPATH={JA V A_HOME}\jre \lib\ext \comm.jar;%classpath%实现过程要紧步骤包括:获得串口标识打开串口设置串行端口通讯参数猎取输入(出)流进行读写操作获得串口标识指定串口的端口号,生成串口的标识类的实例。
a. 通过驱动决定通讯端口是可用的。
b. 打开通讯端口为了I/O操作。
c. 决定端口的拥有者。
d. 解析端口拥有者的争夺。
e. 治理事件显示在端口拥有者的中的状态改变。
示例代码如下:代码:打开串口示例代码如下:代码:5000(毫秒)是超时时刻。
设置串行端口通讯参数设置串口传输的波特率、数据位、停止位、奇偶校验等参数。
示例代码如下:代码:try {// 通信条件の設定// 通信速度 9600 baud// データビット 8bit// ストップビット 1bit// パリティなし// フローコントロールの設定// 無制御を使用port.setSerialPortParams(9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);} catch (UnsupportedCommOperationException ex) {ex.printStackTrace();System.exit(1);}猎取输入(出)流利用getInputStream()以及getOutputStream()从每个串口产生对应的输入输出流对象。
java 串口通信案例Java串口通信是指使用Java编程语言实现与串口设备之间的数据通信。
串口通信在很多应用场景中都有广泛的应用,比如物联网、工业自动化、智能家居等领域。
本文将列举十个以Java串口通信为题的案例,介绍其实现方法和应用场景。
1. 串口读取数据通过Java编程语言实现串口读取数据的功能,可以使用Java的串口通信库,如RXTX、JavaComm等。
首先需要打开串口,并设置串口参数,然后通过监听串口数据的方式实时读取串口传入的数据。
这个案例适用于需要实时监控串口设备数据的应用场景,比如环境监测。
2. 串口发送数据通过Java编程语言实现串口发送数据的功能,可以使用Java的串口通信库。
首先需要打开串口,并设置串口参数,然后通过写入数据的方式将数据发送到串口设备。
这个案例适用于需要向串口设备发送指令或数据的应用场景,比如控制外部设备。
3. 串口数据解析通过Java编程语言实现串口数据解析的功能,可以将从串口读取的原始数据进行解析,提取出有用的信息。
可以根据数据格式进行解析,比如按照特定的协议解析数据。
这个案例适用于需要对串口设备传输的数据进行处理和分析的应用场景。
4. 串口数据存储通过Java编程语言实现串口数据存储的功能,可以将从串口读取的数据保存到本地文件或数据库中。
可以根据需求选择适当的存储方式,比如文本文件、二进制文件或数据库。
这个案例适用于需要对串口设备传输的数据进行长期存储和分析的应用场景。
5. 串口数据转发通过Java编程语言实现串口数据转发的功能,可以将从一个串口读取的数据转发到另一个串口。
可以实现串口设备之间的数据交互,比如串口设备之间的数据通信或设备之间的数据同步。
这个案例适用于需要多个串口设备之间进行数据交互的应用场景。
6. 串口数据监控通过Java编程语言实现串口数据监控的功能,可以监控串口设备的状态和传输数据。
可以实时显示串口设备的连接状态、波特率、数据位、停止位等信息,并实时显示串口传输的数据。
使⽤Java实现简单串⼝通信没想到挺多⼈需要这个的,很⾼兴这篇⽂章能对⼤家有帮助,主要的⼯具类博⽂⾥已经有了,当然,要⼩⼯具源码的留⾔邮箱即可。
2019.09.05最近接触到了串⼝及其读写,在此记录java进⾏串⼝读写的过程。
1.导⼊⽀持java串⼝通信的jar包:在maven项⽬的pom.xml中添加RXTXcomm的依赖或者下载RXTXcomm.jar并导⼊到项⽬中。
⽀持Java串⼝通信操作的jar包,m⽐较⽼,⽽且不⽀持64位系统,推荐使⽤Rxtx这个jar包(32位/64位均⽀持)。
下载地址:注意:运⾏过程中抛出ng.UnsatisfiedLinkError错误或gnu.io下的类找不到时,将rxtx解压包中的rxtxParallel.dll,rxtxSerial.dll 这两个⽂件复制到C:\Windows\System32 ⽬录下可解决该错误。
2.编写代码操作串⼝:串⼝必要参数类:包含连接串⼝所必须的参数,⽅便在调⽤串⼝时设置和传递串⼝参数/*** 串⼝必要参数接收类* @author: LinWenLi* @date: 2018年7⽉21⽇下午4:30:40*/public class ParamConfig {private String serialNumber;// 串⼝号private int baudRate; // 波特率private int checkoutBit; // 校验位private int dataBit; // 数据位private int stopBit; // 停⽌位public ParamConfig() {}/*** 构造⽅法* @param serialNumber 串⼝号* @param baudRate 波特率* @param checkoutBit 校验位* @param dataBit 数据位* @param stopBit 停⽌位*/public ParamConfig(String serialNumber, int baudRate, int checkoutBit, int dataBit, int stopBit) {this.serialNumber = serialNumber;this.baudRate = baudRate;this.checkoutBit = checkoutBit;this.dataBit = dataBit;this.stopBit = stopBit;}getter()...setter()...}串⼝操作类:(其中包含的CustomException是⾃定义异常类,仅⽤于抛出异常原因。
基于无线传感定位系统的通信软件一、运行环境:Windows操作系统下运行,由于作品是基于java虚拟机的,所以需要安装jvm 该作品是属于基于硬件的通信软件,所以在对数据的接收上要求无线传感器支持,这个软件主要任务是对无线传感器发送来的数据进行准确,形象的整理和分析。
二、开发环境:软件开发环境是在eclipse这个平台上,基于java的RXTX串口通信技术完成的。
三、功能说明:1、各类结点数据的接受处理和统计;2、界面面板缩进的控制;3、温度数据湿度数据的对比图像;4、图像的缩放功能。
5、室内平面图的上传和缩放以及定位。
6、节点位置信息处理,显示在相对位置图上,每个节点要能够通过颜色反映出节点周围的温度状况。
7、数据的发送功能,我及时的向底层硬件发送数据帧,实现软硬件的实时联系和交互。
8、常用信息的设置功能,比如室温,串口属性信息,数据接受格式等四、作品整体效果展示温湿度曲线显示、控制和对比结点位置信息和温度信息的图像反映五、操作以及功能说明:1、串口设置:要针对电脑接入串口时的属性,和底层数据发送帧的格式在如下面板中设置。
2、常用命令的设置,设置这些向底层发出请求的命令,可以灵活的控制我们所需要的数据,比如我们可以选择请求结点的温度信息,请求结点的湿度信息,或者是位置信息等等。
3、温湿度曲线的控制,设置好之后,点击ok,点击开始按钮,便会接受到底层硬件发来的数据,但是我们的硬件可能是很多个结点,如果都反映在图像上,可能略显混乱,所以我们可以在结点数据面板中控制哪个结点的显示状况。
4、结点位置信息的查看,下面的截图反映了结点的位置信息,大的圆圈是参考结点的位置和温度信息的反映,从内向外温度不断的接近室温,颜色越深的部分表示温度越高,小的绿园是我们要定位的盲几点的位置信息的反映,随着盲几点的实际位置信息的变化,图像中会做出准确的变化。
,5、盲结点和参考结点相关参数的设定,我们选中单选框,信息会出现在文本框中,设置好后,点击update,发送到底层。
小技巧:如何辨别TXD和RXD端口?搞电子的人手边应该常备一个电表,用来测测电压,电阻什么的会很有用。
你只要分别测一下RS232端口的2--5或3--5针脚之间的电压,通常TXD针脚与GND之间会有3~15V左右的负电压,表示它是TXD针脚。
安装JavaCommunicationsAPISun的J2SE中并没有直接提供以上提到的任何一种串行通讯协议的开发包,而是以独立的jar包形式发布在网站上(从这里下载)----即comm.jar,称之为Javatm CommunicationsAPI,它是J2SE的标准扩展。
comm.jar并不是最近才有,早在1998年时,sun就已经发布了这个开发包。
comm.jar分别提供了对常用的RS232串行端口和IEEE1284并行端口通讯的支持。
目前sun发布的comm.jar只有Windows和Solaris平台两个版本,如果你需要Linux平台下的,可以在/~kevinh/linuxcomm.html找到。
在使用comm.jar之前,必须知道如何安装它。
这也是困扰许多初学javaRS232通讯者的一个难题。
如果我们电脑上安装了JDK,它将同时为我们安装一份JRE(Java RuntimeEntironment),通常我们运行程序时都是以JRE来运行的。
所以以下的安装适用于JRE。
如果你是用JDK来运行程序的,请将相应的改成。
下载了comm.jar开发包后,与之一起的还有两个重要的文件,win32com.dll和m.properties。
comm.jar提供了通讯用的javaAPI,而win32com.dll提供了供comm.jar调用的本地驱动接口。
而m.properties是这个驱动的类配置文件。
首先将comm.jar复制到\lib\ext目录。
再将win21com.dll复制到你的RS232应用程序运行的目录,即user.dir。
然后将m.properties复制到\lib目录。
java串口通信API说明java串口通信Java提供了 CommunicationAPI(包含于m包中)用于通过与机器无关的方式,控制各种外部设备。
Communications API,是标准的Java的扩展部分,它在JavaAPI中是没有附带的。
因此,必须先在SUN公司网站的Java站点()上下载这个扩展类库。
1.1Communications API 简介Communications API 的核心是抽象的CommPort类及其两个子类:SerialPort类和ParallePort类。
其中,SerialPort类是用于串口通信的类,ParallePort类是用于并行口通信的类。
CommPort类还提供了常规的通信模式和方法,例如:getInputStream( )方法和getOutputStream( )方法,专用于与端口上的设备进行通信。
然而,这些类的构造方法都被有意的设置为非公有的(non-public)。
所以,不能直接构造对象,而是先通过静态的CommPortIdentifer.getPortIdentifiers()获得端口列表;再从这个端口列表中选择所需要的端口,并调用CommPortIdentifer对象的Open( )方法,这样,就能得到一个CommPort对象。
当然,还要将这个CommPort对象的类型转换为某个非抽象的子类,表明是特定的通讯设备。
该子类可以是SerialPort类和ParallePort类中的一个。
下面将分别对CommPort类,CommPortIdentifier类,串口类SerialPort进行详细的介绍。
1.2 CommPortIdentifier类CommPortIdentifier类的方法如下:方法说明addPortName(String, int, CommDriver) 添加端口名到端口列表里addPortOwnershipListener(CommPortOwnershipListener) 添加端口拥有的监听器removePortOwnershipListener(CommPortOwnershipListener) 移除端口拥有的监听器getCurrentOwner() 得到当前占有端口的对象或应用程序getName() 得到端口名称getPortIdentifier(CommPort) 得到参数打开的端口的CommPortIdentifier类型对象getPortIdentifier(String) 得到以参数命名的端口的CommPortIdentifier类型对象getPortIdentifiers() 得到系统中的端口列表getPortType() 得到端口的类型isCurrentlyOwned() 判断当前端口是否被占用open(FileDescriptor) 用文件描述的类型打开端口open(String, int) 打开端口,两个参数:程序名称,延迟时间(毫秒数)1.3 SerialPort类SerialPort关于串口参数的静态成员变量成员变量说明成员变量说明成员变量说明DATABITS_5 数据位为5 STOPBITS_2 停止位为2 PARITY_ODD 奇检验DATABITS_6 数据位为6 STOPBITS_1 停止位为1 PARITY_MARK 标记检验DATABITS_7 数据位为7 STOPBITS_1_5 停止为1.5 PARITY_NONE 空格检验DATABITS_8 数据位为8 PARITY_EVEN 偶检验 PARITY_SPACE 无检验SerialPort对象的关于串口参数的函数方法说明方法说明getBaudRate() 得到波特率 getParity() 得到检验类型getDataBits() 得到数据位数 getStopBits() 得到停止位数setSerialPortParams(int, int, int, int) 设置串口参数依次为(波特率,数据位,停止位,奇偶检验)SerialPort关于事件的静态成员变量成员变量说明成员变量说明BI Break interrupt中断 FE Framing error错误CD Carrier detect载波侦听 OE Overrun error错误CTS Clear to send清除以传送 PE Parity error奇偶检验错误DSR Data set ready数据备妥 RI Ring indicator响铃侦测DATA_AVAILABLE 串口中的可用数据 OUTPUT_BUFFER_EMPTY 输出缓冲区空SerialPort中关于事件的方法方法说明方法说明方法说明isCD() 是否有载波 isCTS() 是否清除以传送 isDSR() 数据是否备妥isDTR() 是否数据端备妥 isRI() 是否响铃侦测 isRTS() 是否要求传送addEventListener(SerialPortEventListener) 向SerialPort对象中添加串口事件监听器removeEventListener() 移除SerialPort对象中的串口事件监听器notifyOnBreakInterrupt(boolean) 设置中断事件true有效,false 无效notifyOnCarrierDetect(boolean) 设置载波监听事件true有效,false无效notifyOnCTS(boolean) 设置清除发送事件true有效,false无效notifyOnDataAvailable(boolean) 设置串口有数据的事件true有效,false无效notifyOnDSR(boolean) 设置数据备妥事件true有效,false无效notifyOnFramingError(boolean) 设置发生错误事件true有效,false无效notifyOnOutputEmpty(boolean) 设置发送缓冲区为空事件true有效,false无效notifyOnParityError(boolean) 设置发生奇偶检验错误事件true 有效,false无效notifyOnRingIndicator(boolean) 设置响铃侦测事件true有效,false无效getEventType() 得到发生的事件类型返回值为int型sendBreak(int) 设置中断过程的时间,参数为毫秒值setRTS(boolean) 设置或清除RTS位setDTR(boolean) 设置或清除DTR位SerialPort中的其他常用方法方法说明close() 关闭串口getOutputStream() 得到OutputStream类型的输出流getInputStream() 得到InputStream类型的输入流一年半前在jbuilder2006下写过串口通信程序,最近做一个GPS-SMS 项目,用到串口通信,在JBUILDER 配置了comm.jar却发现找不到端口,经过几番查找才发现自己配置的路径错了,浪费了不少时间,有必要记下来,防止下次出错,此次还暴露了自己看文章一目十行,走马观花的毛病。
Java串口通信 RXTX 实现方案1.背景介绍由于第一次用Java与硬件通信,网上查了许多资料,在这进行整理,便于以后学习。
本人串口测试是USB串口设备连接电脑,在设备管理器中找到端口名称(也可以通过一些虚拟串口工具模拟)。
下面主要简述获取串口消息返回值的一些问题,在最下面已经附上完整代码。
2.准备工作RXTX包:mfz-rxtx-2.2-20081207-win-x64.zip,解压,RXTXcomm.jar加入项目依赖库里,rxtxParallel.dll和rxtxSerial.dll放入jdk的bin目录下(我使用的jdk1.8)1.RXTX工具类编写编写基础方法:获取可用端口名,开启端口,发送命令,接受命令,关闭端口import gnu.io.*;import javax.sound.midi.SoundbankResource;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import java.util.ArrayList;import java.util.Enumeration;import java.util.List;import java.util.TooManyListenersException;import static com.why.rxtx.utill.HexadecimalUtil.get16NumAdd0;import static com.why.rxtx.utill.HexadecimalUtil.hexStringToByteArray;import static com.why.rxtx.utill.OrderUtil.retuenLogOrder;import static com.why.rxtx.utill.OrderUtil.send;/*** 使用rxtx连接串口工具类*/public class RXTXUtil {private static final String DEMONAME = "串口测试";/*** 检测系统中可用的端口*/private CommPortIdentifier portId;/*** 获得系统可用的端口名称列表*/private static Enumeration<CommPortIdentifier> portList;/*** 输入流*/private static InputStream inputStream;/*** RS-232的串行口*/private static SerialPort serialPort;/*** 返回结果*/private static String res=null;/*** 获得系统可用的端口名称列表*@return可用端口名称列表*/@SuppressWarnings("unchecked")public static void getSystemPort(){List<String> systemPorts =new ArrayList<>();//获得系统可用的端口portList = CommPortIdentifier.getPortIdentifiers();while(portList.hasMoreElements()) {String portName= portList.nextElement().getName();//获得端口的名字 systemPorts.add(portName);}}/*** 开启串口*@param serialPortName 串口名称*@param baudRate 波特率*@return串口对象*/public static void openSerialPort(String serialPortName,int baudRate) {try {//通过端口名称得到端口CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(serialPortName);//打开端口,(自定义名字,打开超时时间)CommPort commPort = portIdentifier.open(serialPortName, 5000);//判断是不是串口if (commPort instanceof SerialPort) {serialPort= (SerialPort) commPort;//设置串口参数(波特率,数据位8,停止位1,校验位无) serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);// System.out.println("开启串口成功,串口名称:"+serialPortName); }else {//是其他类型的端口throw new NoSuchPortException();}}catch (NoSuchPortException e) {e.printStackTrace();}catch (PortInUseException e) {e.printStackTrace();}catch (UnsupportedCommOperationException e) {e.printStackTrace();}}/*** 向串口发送数据*@param order 发送的命令*/public static void sendData( String order) {//16进制表示的字符串转换为字节数组byte[] data =hexStringToByteArray(order);OutputStream os=null;try {os= serialPort.getOutputStream();//获得串口的输出流 os.write(data);os.flush();}catch (IOException e) {e.printStackTrace();}finally {//关闭流操作try {if (os !=null) {os.close();os=null;}}catch (IOException e) {e.printStackTrace();}}}/*** 从串口读取数据*@return读取的数据*/public static String readData() {//保存串口返回信息StringBuffer res=new StringBuffer(40);InputStream is=null;byte[] bytes =null;try {is= serialPort.getInputStream();//获得串口的输入流int bufflenth = is.available();//获得数据长度while (bufflenth != 0) {bytes=new byte[bufflenth];//初始化byte数组 is.read(bytes); bufflenth= is.available();}if(bytes!=null) {for (int i = 0; i < bytes.length; i++) {//转换成16进制数(FF)res.append(get16NumAdd0((bytes[i]&0xff)+"",2));}}System.out.println("res: "+res.toString());}catch (IOException e) {e.printStackTrace();}finally {try {if (is !=null) {is.close();is=null;}}catch(IOException e) {e.printStackTrace();}}return res.toString();}/*** 关闭串口**/public static void closeSerialPort() {if(serialPort !=null) {serialPort.close();//System.out.println("关闭了串口:"+serialPort.getName());2.编写测试代码/*** 串口命令执行*@param order 命令*@param portName 端口名*@param baudRate 波特率*@return*@throws UnsupportedEncodingException*/public synchronized static String executeOrder(String order,String portName,int baudRate) {String str="";if (serialPort==null) {openSerialPort(portName, baudRate);}//发送消息 sendData(order);//接收消息String str=readData();return res;}很遗憾上面代码输入命令,端口号等等后,返回结果一直是null, 突然间发现和以前写读写io流还是有一定区别的。
Java串口通信详解序言说到开源,恐怕很少有人不挑大指称赞。
学生通过开源代码学到了知识,程序员通过开源类库获得了别人的成功经验及能够按时完成手头的工程,商家通过开源软件赚到了钱……,总之是皆大欢喜。
然而开源软件或类库的首要缺点就是大多缺乏详细的说明文档和使用的例子,或者就是软件代码随便你用,就是文档,例子和后期服务收钱。
这也难怪,毕竟就像某个著名NBA 球员说的那样:“我还要养家,所以千万美元以下的合同别找我谈,否则我宁可待业”。
是啊,支持开源的人也要养家,收点钱也不过分。
要想既不花钱又学到知识就只能借助网络和了,我只是想抛砖引玉,为开源事业做出点微薄共献,能为你的工程解决哪怕一个小问题,也就足够了。
虽然我的这个系列介绍的东西不是什么Web框架,也不是什么开源服务器,但是我相信,作为一个程序员,什么样的问题都会遇到。
有时候越是简单的问题反而越棘手;越是小的地方就越是找不到称手的家伙。
只要你不是整天只与“架构”、“构件”、“框架”打交道的话,相信我所说的东西你一定会用到。
1串口通信简介1.1常见的Java串口包1.2串口包的安装(Windows下)2串口API概览mPortmPortIdentifierm.SerialPort2.4串口API实例2.4.1列举出本机所有可用串口2.4.2串口参数的配置2.4.3串口的读写3串口通信的通用模式及其问题3.1事件监听模型3.2串口读数据的线程模型3.3第三种方法4结束语1串口通信简介嵌入式系统或传感器网络的很多应用和测试都需要通过PC机与嵌入式设备或传感器节点进行通信。
其中,最常用的接口就是RS-232串口和并口(鉴于USB接口的复杂性以及不需要很大的数据传输量,USB接口用在这里还是显得过于奢侈,况且目前除了SUN有一个支持USB 的包之外,我还没有看到其他直接支持USB的Java类库)。
SUN的CommAPI分别提供了对常用的RS232串行端口和IEEE1284并行端口通讯的支持。
RS-232-C(又称EIARS-232-C,以下简称RS232)是在1970年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。
RS232是一个全双工的通讯协议,它可以同时进行数据接收和发送的工作。
1.1 常见的Java串口包目前,常见的Java串口包有SUN在1998年发布的串口通信API:comm2.0.jar(Windows 下)、comm3.0.jar(Linux/Solaris);IBM的串口通信API以及一个开源的实现。
鉴于在Windows下SUN的API比较常用以及IBM的实现和SUN的在API层面都是一样的,那个开源的实现又不像两家大厂的产品那样让人放心,这里就只介绍SUN的串口通信API在Windows 平台下的使用。
1.2 串口包的安装(Windows下)到SUN的网站下载javacomm20-win32.zip,包含的东西如下所示:按照其使用说明(Readme.html)的说法,要想使用串口包进行串口通信,除了设置好环境变量之外,还要将win32com.dll复制到<JDK>\bin目录下;将comm.jar复制到<JDK>\lib;把m.properties也同样拷贝到<JDK>\lib目录下。
然而在真正运行使用串口包的时候,仅作这些是不够的。
因为通常当运行“java MyApp”的时候,是由JRE下的虚拟机启动MyApp的。
而我们只复制上述文件到JDK相应目录下,所以应用程序将会提示找不到串口。
解决这个问题的方法很简单,我们只须将上面提到的文件放到JRE相应的目录下就可以了。
值得注意的是,在网络应用程序中使用串口API的时候,还会遇到其他更复杂问题。
有兴趣的话,你可以查看CSDN社区中“关于网页上Applet用javacomm20读取客户端串口的问题”的帖子。
2串口API概览mPort这是用于描述一个被底层系统支持的端口的抽象类。
它包含一些高层的IO控制方法,这些方法对于所有不同的通讯端口来说是通用的。
SerialPort 和ParallelPort都是它的子类,前者用于控制串行端口而后者用于控这并口,二者对于各自底层的物理端口都有不同的控制方法。
这里我们只关心SerialPort。
mPortIdentifier这个类主要用于对串口进行管理和设置,是对串口进行访问控制的核心类。
主要包括以下方法l确定是否有可用的通信端口l为IO操作打开通信端口l决定端口的所有权l处理端口所有权的争用l管理端口所有权变化引发的事件(Event)m.SerialPort这个类用于描述一个RS-232串行通信端口的底层接口,它定义了串口通信所需的最小功能集。
通过它,用户可以直接对串口进行读、写及设置工作。
2.4 串口API实例大段的文字怎么也不如一个小例子来的清晰,下面我们就一起看一下串口包自带的例子---SerialDemo中的一小段代码来加深对串口API核心类的使用方法的认识。
2.4.1列举出本机所有可用串口void listPortChoices() {CommPortIdentifier portId;Enumeration en = CommPortIdentifier.getPortIdentifiers();// iterate through the ports.while (en.hasMoreElements()) {portId = (CommPortIdentifier) en.nextElement();if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { System.out.println(portId.getName());}}portChoice.select(parameters.getPortName());}以上代码可以列举出当前系统所有可用的串口名称,我的机器上输出的结果是COM1和COM3。
2.4.2串口参数的配置串口一般有如下参数可以在该串口打开以前配置进行配置:包括波特率,输入/输出流控制,数据位数,停止位和齐偶校验。
SerialPort sPort;try {sPort.setSerialPortParams(BaudRate,Databits,Stopbits,Parity);//设置输入/输出控制流sPort.setFlowControlMode(FlowControlIn | FlowControlOut);} catch (UnsupportedCommOperationException e) {}2.4.3串口的读写对串口读写之前需要先打开一个串口:CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier(PortName);try {SerialPort sPort = (SerialPort) portId.open("串口所有者名称", 超时等待时间);} catch (PortInUseException e) {//如果端口被占用就抛出这个异常throw new SerialConnectionException(e.getMessage());}//用于对串口写数据OutputStream os = new BufferedOutputStream(sPort.getOutputStream());os.write(int data);//用于从串口读数据InputStream is = new BufferedInputStream(sPort.getInputStream());int receivedData = is.read();读出来的是int型,你可以把它转换成需要的其他类型。
这里要注意的是,由于Java语言没有无符号类型,即所有的类型都是带符号的,在由byte 到int的时候应该尤其注意。
因为如果byte的最高位是1,则转成int类型时将用1来占位。
这样,原本是10000000的byte类型的数变成int型就成了1111111110000000,这是很严重的问题,应该注意避免。
3串口通信的通用模式及其问题终于唠叨完我最讨厌的基础知识了,下面开始我们本次的重点--串口应用的研究。
由于向串口写数据很简单,所以这里我们只关注于从串口读数据的情况。
通常,串口通信应用程序有两种模式,一种是实现SerialPortEventListener接口,监听各种串口事件并作相应处理;另一种就是建立一个独立的接收线程专门负责数据的接收。
由于这两种方法在某些情况下存在很严重的问题(至于什么问题这里先卖个关子J),所以我的实现是采用第三种方法来解决这个问题。
3.1 事件监听模型现在我们来看看事件监听模型是如何运作的:l首先需要在你的端口控制类(例如SManager)加上“implements SerialPortEventListener”l在初始化时加入如下代码:try {SerialPort sPort.addEventListener(SManager);} catch (TooManyListenersException e) {sPort.close();throw new SerialConnectionException("too many listeners added");}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中接收并处理所收到的数据。
然而在我的实践中,遇到了一个十分严重的问题。
首先描述一下我的实验:我的应用程序需要接收传感器节点从串口发回的查询数据,并将结果以图标的形式显示出来。
串口设定的波特率是115200,川口每隔128毫秒返回一组数据(大约是30字节左右),周期(即持续时间)为31秒。
实测的时候在一个周期内应该返回4900多个字节,而用事件监听模型我最多只能收到不到1500字节,不知道这些字节都跑哪里去了,也不清楚到底丢失的是那部分数据。