说明
由于我用的这台设备和上面的超声波雷达年代比较久远,之前让项目经理找配套的资料和文档也没找到,所以只能自己摸索数据格式和接收方法,另外声明,我还是个小卡拉米,仅在此记录工作中遇到的问题,如果有更好的解决方案欢迎在评论区留言,大家共同进步。
遇到的问题
1:linux中cutecom上的数据和windows串口助手显示不一致
1.超声波雷达使用的是串口RS485,用windows的串口调试助手接收,将接受设置的ASCII改为HEX,收到的数据是非常整齐的、固定为15个十六进制数的数据,经过测试,发现这里的数据从第4位到第9位是六个激光雷达的距离参数。。。。
but。。。把RS485接口插到linux工控机上,用cutecom收到的数据确是这样:
然后我勾选了底下的HEX output,数据变为:
这个数据显然符合了我的要求,可是我看了一会后发现,这里的每行数据仅在开始那段时间正常,过了一段时间,数据开始发生位移,如图:
不合理,这显然不合理。。。。我想要的就是像windows串口助手那样整齐的数据。
2:C++代码调试串口,收不到数据
在问题一没有得到解决的情况下,我接着又去试了一下之前用C++获取串口的方法,
结果居然 根本接收不到数据了!!!
后来我又找了一个接收串口数据的代码,代码内容我就不放了,传送门:C++读取串口数据并显示16进制
收到的数据是这样:
虽然确是收到了部分我要的内容,但是格式很乱。
解决问题并实现C++获取规范的十六进制串口数据
Step1:解决WzSerialPort.cpp文件无法获取串口数据的问题
WzSerialPort.cpp参考我上一篇文章:C++收发串口数据(并解决C++多文件编译问题)
摸索后发现,之前的接收串口数据的C++代码收不到数据的原因出在文件打开方式上,打开上一章讲的WzSerialPort.cpp文件,如下图红框位置。
第一个参数是可读可写,第二个是不让打开的文件成为该进程的控制终端,第三个参数是不阻塞方式打开文件。
问题也许就出现在上图的以不阻塞方式打开,如果遇到收不到数据的情况,像我一样把这里改成只读就行,并把O_NONBLOCK删掉:
pHandle[0] = ::open(portname, O_RDONLY | O_NOCTTY);
再运行main函数:
运行效果:
此时说明已经可以接收到ASCII编码
Step2:将串口ASCII编码转换为16进制格式
修改main.cpp中的receiveDemo()函数,主要是while循环里面那个for循环里的内容,这里也是对另外一个搜索来的代码稍作了一部分的修改,可以参考上面那个传送门:C++读取串口数据并显示16进制
void receiveSoundRadar()
{
WzSerialPort w;
bool o_flag = w.open("/dev/ttyUSB2", 115200, 0, 8, 1);
cout << o_flag << endl;
while (!o_flag)
{
cout << "looping ..." << endl;
o_flag = w.open("/dev/ttyUSB2", 115200, 0, 8, 1);
}
if (o_flag)
{
char buf[1024];
int usLadars[6];
int i = 0;
while (true)
{
memset(buf, 0, 1024);
int flag = w.receive(buf, 1024);
if (flag && strlen(buf) == 9)
{
int j = 0;
for (int i = 0; i < 15; i++)
{
//3-8位为激光雷达数据
if (i > 2 && i < 9)
{
stringstream s1;
s1 << std::hex;
s1 << std::setw(2) << std::setfill('0') << (int)buf[i];
usLadars[j++] = stoi(s1.str(), 0, 16);
}
}
// 16进制显示
cout << "datas:";
for (int i = 0; i < 6; i++)
{
cout << usLadars[i] << " ";
}
cout << endl;
}
}
}
}
运行效果
分别对应六个激光雷达传来的数据,已经转换为了十进制。