环境macbook pro m1pro,javad jdk17,使用JSerialComm包使用RS232连接虚拟仿真设备WT310进行串口通信时,发送命令获取数据,为什么只能获取到62个字节,应该获取65个字节,代码如下:
package org.test;
import com.fazecast.jSerialComm.SerialPort;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
public class DSerialPort1 {
public void main() throws IOException, InterruptedException {
String path = "/Users/cc/workspace/Idea/DSerialPort/serialPortOutput.txt";
File result = new File(path);
//判断文件是否存在,如果不存在,则创建一个
if(!result.exists()){
result.createNewFile();
}
//获取当前工作路径
// System.out.println(System.getProperty("user.dir"));
//查找所有串口
SerialPort[] serialPorts = SerialPort.getCommPorts();
SerialPort usbSerialPort = null;
for(int i = 0; i<serialPorts.length; i++){
if(serialPorts[i].getSystemPortName().equals("cu.usbserial-FTDEBWBU")){
// System.out.println(serialPorts[i].getSystemPortName());
usbSerialPort = serialPorts[i];
break;
}
}
if (usbSerialPort != null) {
System.out.println(usbSerialPort.getSystemPortName());
}else{
System.out.println("接口不存在!");
return;
}
//设置串口参数
//serialPort.setComPortParameters(112500, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY);
//一次性设置所有的串口参数,第一个参数为波特率,默认9600;第二个参数为每一位的大小,默认8,可以输入5到8之间的值;第三个参数为停止位大小,只接受内置常量,可以选择(ONE_STOP_BIT, ONE_POINT_FIVE_STOP_BITS, TWO_STOP_BITS);第四位为校验位,同样只接受内置常量,可以选择 NO_PARITY, EVEN_PARITY, ODD_PARITY, MARK_PARITY,SPACE_PARITY。
usbSerialPort.setBaudRate(9600);
usbSerialPort.setNumDataBits(8);
usbSerialPort.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
//打开串口
if(!usbSerialPort.isOpen()){
boolean isCommOpened = usbSerialPort.openPort();//判断串口是否打开,如果没打开,就打开串口。打开串口的函数会返回一个boolean值,用于表明串口是否成功打开了
if(isCommOpened) System.out.println("打开串口成功!");
else System.out.println("打开串口失败!");
}
//测试串口发送接收数据
if(usbSerialPort.isOpen()){
// usbSerialPort.flushIOBuffers();
//要发送的命令
String writeData = "NUMeric:NORMal:VALue?\r\n";
//将字符串转换为字节数组
byte[] bytes = writeData.getBytes();
//将字节数组全部写入串口
usbSerialPort.writeBytes(bytes,bytes.length);
//休眠0.1秒,等待下位机返回数据。如果不休眠直接读取,有可能无法成功读到数据
Thread.sleep(20);
// System.out.println("接收数据大小:"+usbSerialPort.bytesAvailable());
String readData = "";
InputStream is = usbSerialPort.getInputStream();
System.out.println("可读取的字节大小:"+is.available());
//循环读取所有的返回数据。如果可读取数据长度为0或-1,则停止读取
while(is.available()>0) {
byte[] newData = new byte[is.available()];//创建一个字节数组,长度为可读取的字节长度
//将串口中可读取的数据读入字节数组,返回值为本次读取到的字节长度
int numRead = is.read(newData);
//将新数据转为字符串
String newDataString = new String(newData);
//组合字符串
readData = readData + newDataString;
//休眠0.02秒,等待下位机传送数据到串口。如果不休眠,直接再次使用port.bytesAvailable()函数会因为下位机
//还没有返回数据而返回-1,并跳出循环导致数据没读完。休眠时间可以自行调试,时间越长,单次读取到的数据越多。
Thread.sleep(1000);
System.out.println("剩余字符串大小"+is.available());
usbSerialPort.flushIOBuffers();
}
//对获取到的数据进行处理
//根据分隔符","进行分隔,获取数组
System.out.println(readData);
String[] datas = readData.split(",");
System.out.println(datas.length);
System.out.println(Arrays.toString(datas));
//创建最终结果的数组
double[] finalData = new double[datas.length];
//对每个数组中的数据进行处理
for(int i = 0; i<datas.length; i++){
//将字符串进行划分
String baseNumber = datas[i].substring(0,6);
String indexSignal = datas[i].substring(7,8);
String index = datas[i].substring(8,10);
finalData[i] = transform(baseNumber, indexSignal, index);
System.out.println(finalData[i]);
}
System.out.println("readString:"+readData);
//获取当前时间
SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z");
Date date = new Date(System.currentTimeMillis());
String time = formatter.format(date);
System.out.println("当前时间为:"+time);
//IO写入文件
Writer writer = null;
try{
writer = new FileWriter(result);
writer.append(time);
writer.append(" ");
writer.append(Arrays.toString(finalData));
writer.append("\n");
}catch (Exception e){
e.printStackTrace();
}finally {
if(writer != null){
try{
writer.close();
}catch(IOException e){
System.out.println("文件关闭失败!!");
}
}
}
}
//关闭串口
usbSerialPort.closePort();
}
//数据处理函数,将字符串转换为double
private static double transform(String baseNumber, String indexSignal, String index){
int signal = 0;
if(indexSignal.equals("+")) signal = 1;
double number = pushIndex(signal, Double.parseDouble(baseNumber), Integer.parseInt(index));
return number;
}
//数据处理函数,底数乘指数
private static double pushIndex(int signal, double number, int index){
//0代表指数为负数,1代表指数为正数
if(signal == 0){
for(int i = 0; i<index; i++){
number = number/10;
}
}else{
for(int i = 0; i<index; i++){
number = number*10;
}
}
return number;
}
}
【以下回答由 GPT 生成】
问题分析: 根据提供的代码,可以看出在读取串口数据时,设置了读取缓冲区的大小为100字节(byte[] readBuffer = new byte[100];),然后使用inputStream.read(readBuffer)方法读取数据,最后打印出实际读取到的字节数。
根据问题描述,实际应该获取到65个字节的数据,但只获取到了62个字节。这可能是由于读取缓冲区大小的设置问题或者数据传输延迟导致的。
解决方案: 1. 调整读取缓冲区的大小:将读取缓冲区的大小增大到可容纳65个字节的大小。
修改代码为:
byte[] readBuffer = new byte[65];
int numRead = inputStream.read(readBuffer);
System.out.println("读取到的字节数:" + numRead);
修改代码为:
Thread.sleep(1000); // 延迟1秒等待数据传输完成
byte[] readBuffer = new byte[65];
int numRead = inputStream.read(readBuffer);
System.out.println("读取到的字节数:" + numRead);
请注意,以上提供的解决方案是基于对问题的初步分析,如果问题仍然存在,请确保虚拟仿真设备WT310正常工作并且向串口发送了完整的65个字节的数据。另外,还可以通过调试和日志记录来进一步排查问题。