做外贸网站义乌,重庆市工程建设造价信息网官网,做一个公司网站一般需要多少钱,wordpress如何显示文章列表一、串口通信与串行通信的原理 串行通信是指仅用一根接收线和一根发送线#xff0c;将数据以位进行依次传输的一种通讯方式#xff0c;每一位数据占据一个固定的时间长度。 串口通信#xff08;Serial Communications#xff09;的概念非常简单#xff0c;串口按位#x…一、串口通信与串行通信的原理 串行通信是指仅用一根接收线和一根发送线将数据以位进行依次传输的一种通讯方式每一位数据占据一个固定的时间长度。 串口通信Serial Communications的概念非常简单串口按位bit发送和接收字节的通信方式。 串口通信时首先要约定好帧格式与波特率并且串口通信采用TTL逻辑Transistor-Transistor Logic 是指晶体管-晶体管逻辑。 TTL逻辑门的标准输出状态是
高电平逻辑“1”或HIGH典型值为2.4V至5V对于标准5V电源供电的TTL代表有效信号。 低电平逻辑“0”或LOW典型值接近于地电压0V至0.4V代表无效信号。 这种通信方式抗干扰能力弱下图中静电让某一个低电平变高就会导致通信距离很短越1米。 所以为了提示通信的稳定性与距离产生了由美国制订的推荐标准RS232、RS485都是在基础串口通信的基础上加了特定的电平转换芯片改变电压传输值。
串口通信主要可分为232、485、422三种通信方式。
232通信 232通信主要是由RX、TX、GND三根线组成。RX接TXTX接RXGND接GND。发送和接收由不同的线路处理所以能够同时进行发送和接收数据因此232是全双工通信。
485通信 为了解决232通信距离受限问题于是有了485通信。 485通信只需要、-两根线也叫A、B两根线A、B两根线的差分电平信号就是作为数据信号传输。发送和接收都用这两根线每次只能发送数据或者接收数据因此485是半双工通信。
422通信 422通信兼具232与485的特点既能实现全双工通信又能增大传输距离。422也常被标注为485-4而485被标注为485-2。因为485-2是2根线485-4是4根线。 并行和串行的区别 并行传输: 多根线路传输每条物理线代表一个比特位可以同时发送和接受多个字节 串行传输: 只用一条线路传输逐位传输字节内允许出现延迟如开始或结束等而每个字节之间必须有完整的停止和起始位置。
同步传输和异步传输的差别 同步传输在知道对方状态下进行全双工传输需要调节系统时钟使得传送速度不超过缓存容量并保持包络上均衡。 异步传输既能针对字符流也可针对比特流。异步传输没有明确定义的“帧”模式,因此不需要同步时钟但会增加一个帧同步域用于在接收端恢复字节边界并通过位数逐个地进行帧的识别。
在实际应用中串口通常使用异步技术来发送和接收数据。异步传输可以按需动态调整数据传输速率以便快速响应用户操作或自动控制事件的发生。
二、Java 实现串口通信
准备工作
要想使用串口包进行串口通信除了设置好环境变量之外还要准备对应的串口通信的jar包 1. 下载对应版本的rxtx 解压后得到三个文件 rxtxParallel.dll、rxtxSerial.dll、RXTXcomm.jar/
下载地址如下RXTX for Java (fizzed.com) 2. 将rxtxParallel.dll、rxtxSerial.dll 放进当前使用的jdk的bin目录 jdk版本必须与下载的rxtx一致 区分32位/64位 AMD/IA 3. (windows x64系统可以将当前项目libs下的 rxtxParallel.dll、rxtxSerial.dll 直接放入jdk下的bin目录) 4. 需要将libs下的RXTXcomm.jar加入项目依赖将javax.usb.properties复制到 JRE\lib或者JDK\lib.
dependencygroupIdorg.rxtx/groupIdartifactIdrxtx/artifactIdversion2.2/versionscopesystem/scopesystemPath${project.basedir}/src/main/resources/lib/RXTXcomm.jar/systemPath
/dependency
说明如果没有正常引入将会出现这个错误 代码实现
package com.ss.serialport.controller;import gnu.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;public class SerialPortTool {public static void main(String[] args) {// 查询串口findSystemAllComPort();// //发送16进制数据——实际应用中串口通信传输的数据大都是 16 进制String hexStrCode 455A432F5600;SerialPort serialPort SerialPortTool.openComPort(null, 38400, 8, 1, 0);// 设置串口监听SerialPortTool.setListenerToSerialPort(serialPort, new SerialPortEventListener() {Overridepublic void serialEvent(SerialPortEvent arg0) {if (arg0.getEventType() SerialPortEvent.DATA_AVAILABLE) {//数据通知byte[] bytes SerialPortTool.readData(serialPort);System.out.println(收到的数据长度 bytes.length);System.out.println(收到的数据 new String(bytes));}}});new Thread(new Runnable() {Overridepublic void run() {int i 1;while (i 1000) {byte[] bytes hexStrCode.getBytes();SerialPortTool.sendDataToComPort(serialPort, bytes);//发送数据i;try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}}).start();}/*** 查找电脑上所有可用 com 端口** return 可用端口名称列表没有时 列表为空*/public static final ArrayListString findSystemAllComPort() {/*** getPortIdentifiers获得电脑主板当前所有可用串口*/EnumerationCommPortIdentifier portList CommPortIdentifier.getPortIdentifiers();ArrayListString portNameList new ArrayList();/*** 将可用串口名添加到 List 列表*/System.out.println(串口信息start);while (portList.hasMoreElements()) {CommPortIdentifier commPortIdentifier portList.nextElement();StringBuffer returnStr new StringBuffer();String portName commPortIdentifier.getName();//名称如 COM1、COM2....String isOwner String.valueOf(commPortIdentifier.isCurrentlyOwned());returnStr.append(isOwner).append(\t 占用情况:).append(isOwner);System.out.println(returnStr);portNameList.add(portName);}System.out.println(串口信息end);return portNameList;}/*** 打开电脑上指定的串口** param portName 端口名称如 COM1为 null 时默认使用电脑中能用的端口中的第一个* param b 波特率(baudrate)如 9600* param d 数据位datebits如 SerialPort.DATABITS_8 8* param s 停止位stopbits如 SerialPort.STOPBITS_1 1* param p 校验位 (parity)如 SerialPort.PARITY_NONE 0* return 打开的串口对象打开失败时返回 null*/public static final SerialPort openComPort(String portName, int b, int d, int s, int p) {CommPort commPort null;try {//当没有传入可用的 com 口时默认使用电脑中可用的 com 口中的第一个if (portName null || .equals(portName)) {ListString comPortList findSystemAllComPort();if (comPortList ! null comPortList.size() 0) {portName comPortList.get(0);}}System.out.println(开始打开串口portName portName ,baudrate b ,datebits d ,stopbits s ,parity p);//通过端口名称识别指定 COM 端口CommPortIdentifier portIdentifier CommPortIdentifier.getPortIdentifier(portName);/*** open(String TheOwner, int i)打开端口* TheOwner 自定义一个端口名称随便自定义即可* i打开的端口的超时时间单位毫秒超时则抛出异常PortInUseException if in use.* 如果此时串口已经被占用则抛出异常gnu.io.PortInUseException: Unknown Application*/commPort portIdentifier.open(portName, 5000);/*** 判断端口是不是串口* public abstract class SerialPort extends CommPort*/if (commPort instanceof SerialPort) {SerialPort serialPort (SerialPort) commPort;/*** 设置串口参数setSerialPortParams( int b, int d, int s, int p )* b波特率baudrate* d数据位datebitsSerialPort 支持 5,6,7,8* s停止位stopbitsSerialPort 支持 1,2,3* p校验位 (parity)SerialPort 支持 0,1,2,3,4* 如果参数设置错误则抛出异常gnu.io.UnsupportedCommOperationException: Invalid Parameter* 此时必须关闭串口否则下次 portIdentifier.open 时会打不开串口因为已经被占用*/serialPort.setSerialPortParams(b, d, s, p);System.out.println(打开串口 portName 成功...);return serialPort;} else {System.out.println(当前端口 commPort.getName() 不是串口...);}} catch (NoSuchPortException e) {e.printStackTrace();} catch (PortInUseException e) {System.out.println(串口 portName 已经被占用请先解除占用...);e.printStackTrace();} catch (UnsupportedCommOperationException e) {System.out.println(串口参数设置错误关闭串口数据位[5-8]、停止位[1-3]、验证位[0-4]...);e.printStackTrace();if (commPort ! null) {//此时必须关闭串口否则下次 portIdentifier.open 时会打不开串口因为已经被占用commPort.close();}}System.out.println(打开串口 portName 失败...);return null;}/*** 往串口发送数据** param serialPort 串口对象* param orders 待发送数据*/public static void sendDataToComPort(SerialPort serialPort, byte[] orders) {OutputStream outputStream null;try {if (serialPort ! null) {outputStream serialPort.getOutputStream();outputStream.write(orders);outputStream.flush();System.out.println(往串口 serialPort.getName() 发送数据 Arrays.toString(orders) 完成...);} else {System.out.println(gnu.io.SerialPort 为null取消数据发送...);}} catch (IOException e) {e.printStackTrace();} finally {if (outputStream ! null) {try {outputStream.close();} catch (IOException e) {e.printStackTrace();}}}}/*** 从串口读取数据** param serialPort 要读取的串口* return 读取的数据*/public static byte[] readData(SerialPort serialPort) {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();}} catch (IOException e) {e.printStackTrace();} finally {try {if (is ! null) {is.close();is null;}} catch (IOException e) {e.printStackTrace();}}return bytes;}/*** 给串口设置监听** param serialPort* param listener*/public static void setListenerToSerialPort(SerialPort serialPort, SerialPortEventListener listener) {try {//给串口添加事件监听serialPort.addEventListener(listener);} catch (TooManyListenersException e) {e.printStackTrace();}serialPort.notifyOnDataAvailable(true);//串口有数据监听serialPort.notifyOnBreakInterrupt(true);//中断事件监听}/*** 关闭串口** param serialPort 待关闭的串口对象*/public static void closeComPort(SerialPort serialPort) {if (serialPort ! null) {serialPort.close();System.out.println(关闭串口 serialPort.getName());}}/*** 16进制字符串转十进制字节数组* 这是常用的方法如某些硬件的通信指令就是提供的16进制字符串发送时需要转为字节数组再进行发送** param strSource 16进制字符串如 455A432F5600每两位对应字节数组中的一个10进制元素* 默认会去除参数字符串中的空格所以参数 45 5A 43 2F 56 00 也是可以的* return 十进制字节数组, 如 [69, 90, 67, 47, 86, 0]*/public static byte[] hexString2Bytes(String strSource) {if (strSource null || .equals(strSource.trim())) {System.out.println(hexString2Bytes 参数为空放弃转换.);return null;}strSource strSource.replace( , );int l strSource.length() / 2;byte[] ret new byte[l];for (int i 0; i l; i) {ret[i] Integer.valueOf(strSource.substring(i * 2, i * 2 2), 16).byteValue();}return ret;}}整合成串口工具类
package com.ss.serialport.utils;import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;/*** ClassName DLSC_SerialPort* Description 串口工具类 打开串口 接受数据 发送数据* Version 1.0*/
public class DLSC_SerialPort {private SerialPort serialPort;private InputStream inputStream;private OutputStream outputStream;private BlockingQueueString receivedDataQueue new LinkedBlockingQueue();private volatile boolean isRunning true;private void connect(String portName) throws Exception {// 获取串口通信端口实例CommPortIdentifier portId CommPortIdentifier.getPortIdentifier(portName);if (portId.isCurrentlyOwned()) {System.err.println(Error: Port is currently in use);} else {// 打开端口并获取输入、输出流serialPort (SerialPort) portId.open(SerialCommExample, 2000);inputStream serialPort.getInputStream();outputStream serialPort.getOutputStream();// 设置串口参数serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);// 启动读取数据的线程Thread readThread new Thread(() - {try {while (isRunning) {int available inputStream.available();if (available 0) {byte[] bytes new byte[available];inputStream.read(bytes);String data new String(bytes, UTF-8);receivedDataQueue.put(data); // 将数据放入队列}Thread.sleep(100); // 等待一段时间再检查是否有新数据}} catch (IOException | InterruptedException e) {e.printStackTrace();}});readThread.start();}}private void sendData(String data) throws IOException {if (outputStream ! null) {outputStream.write(data.getBytes(UTF-8));outputStream.flush(); // 确保数据被发送出去}}private String receiveData(long timeout) throws InterruptedException {return receivedDataQueue.poll(timeout, TimeUnit.MILLISECONDS); // 尝试从队列中获取数据超时则返回null}private void disconnect() throws Exception {isRunning false; // 设置标志位以停止读取数据的线程if (serialPort ! null) {serialPort.removeEventListener();serialPort.close();}}public static void send (String msg) {DLSC_SerialPort example new DLSC_SerialPort();try {// 连接到串口example.connect(COM3); // 替换为你的串口名称// 发送数据example.sendData(msg \r\n);// 断开连接example.disconnect();} catch (Exception e) {e.printStackTrace();}}public static Double sendAndReceives(String msg) {DLSC_SerialPort example new DLSC_SerialPort();try {// 连接到串口example.connect(COM1); // 替换为你的串口名称// 发送数据example.sendData(msg \r\n);// 等待并接收数据String receivedData example.receiveData(5000); // 等待最多5秒来获取数据if (receivedData ! null) {Double backData Double.valueOf(receivedData);System.out.println(Received data: backData);return backData;} else {System.out.println(No data received within the timeout period.);}// 断开连接example.disconnect();} catch (Exception e) {e.printStackTrace();}return null;}// public static String sendAndReceive(String msg) {
//
// SerialPortUtil serialPortUtil SerialPortUtil.getSerialPortUtil();
// ArrayListString port serialPortUtil.findPort();
// if (port ! null !port.isEmpty()) {
// System.out.println(没有发现任何端口);
// }
// String portName port.get(2);
// SerialPort serialPort serialPortUtil.openPort(
// portName, 9600, 8, 1, 0);
// if (serialPort null) {
// System.out.println(打开串口 portName 失败);
// }
// System.out.println(成功连接串口 portName);serialPortUtil.sendToPort(serialPort, SOUR:VOLT 28\r\n.getBytes());
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// serialPortUtil.sendToPort(serialPort, SOUR:CURR:LIMIT:HIGH?\r\n.getBytes());
// byte[] bytes serialPortUtil.readFromPort(serialPort);
// if (bytes ! null) {
// return new String(bytes);
// }
// serialPortUtil.closePort(serialPort);
// return null;
// }// public static String sendAndReceive(String msg) {
//
// SerialPortUtil serialPortUtil SerialPortUtil.getSerialPortUtil();
// ArrayListString port serialPortUtil.findPort();
// if (port ! null !port.isEmpty()) {
// System.out.println(没有发现任何端口);
// }
// String portName port.get(0);
// SerialPort serialPort serialPortUtil.openPort(
// portName, 9600, 8, 1, 0);
// if (serialPort null) {
// System.out.println(打开串口 portName 失败);
// }
// System.out.println(成功连接串口 portName);serialPortUtil.sendToPort(serialPort, SOUR:VOLT 28\r\n.getBytes());
// try {
// Thread.sleep(6000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// serialPortUtil.sendToPort(serialPort, SOUR:CURR:LIMIT:HIGH?\r\n.getBytes());
// byte[] bytes serialPortUtil.readFromPort(serialPort);
// if (bytes ! null) {
// return new String(bytes);
// }
// System.out.println(serialPort);
// serialPortUtil.closePort(serialPort);
// return null;
// }public static String sendAndReceive(String msg) {SerialPortUtil serialPortUtil SerialPortUtil.getSerialPortUtil();ArrayListString port serialPortUtil.findPort();System.out.println(port);if (port null || port.isEmpty()) {System.out.println(没有发现任何端口);return null;}String portName port.get(0);SerialPort serialPort serialPortUtil.openPort(portName, 9600, 8, 1, 0);if (serialPort null) {System.out.println(打开串口 portName 失败);return null;}System.out.println(成功连接串口 portName);try {// serialPortUtil.sendToPort(serialPort, SOUR:VOLT 28\r\n.getBytes());Thread.sleep(6000);serialPortUtil.sendToPort(serialPort, SOUR:CURR:LIMIT:HIGH?\r\n.getBytes());byte[] bytes serialPortUtil.readFromPort(serialPort);if (bytes ! null) {return new String(bytes);} else {System.out.println(未读取到任何数据);return null;}} catch (InterruptedException e) {e.printStackTrace();return null;} finally {// 确保串口在所有情况下都关闭serialPortUtil.closePort(serialPort);}}
}