1. open /dev/ttyUSB0 failed 问题定位
基于虚拟机,在ubuntu上进行adaptive_hand控制调试时,发现:程序关闭,再重新运行时,有时会出现open /dev/ttyUSB0 failed;必须将串口设备重新插拔,才可以再次成功打开串口。
- 通信类的析构函数中,未使用close()显示关闭串口,加上之后,打开失败现象少很多,但偶尔也会出现,此时多尝试打开几次,或重新插拔串口;
2.串口丢包问题
参考:串口丢包受什么影响_总结一下曾经在串口方面犯的错误 https://blog.youkuaiyun.com/weixin_39772652/article/details/111262718
串口通讯丢包原因分析:
- 因为串口数据并不是一定能读到对方发的完整数据,这个和驱动性能、波特率、线长、电磁干扰等很多东西都有关
通信速率设的太高了,高的话容易丢数据
- CPU本身性能限制 或者 总线的限制 导致中断响应不过来。
高速 大数据通信时会出现。CPU本身限制 中断响应不过来,这时候一般可以选择更低的波特率、或者更小的封包,或者发包时加一些延时来解决,不过 这些都是应用层的解决方案,在驱动层能做的工作,微乎其微。
由于应用程序效率不高,导致CPU loading 过大,持续100%,可能会有中断丢失的现象,也会导致丢包。这时候优化程序显的格外重要,减少不必要的printf,printf 是非常耗时的。
调试、问题定位:
- 实际抓取一下,看一下丢包的现象是不是重复,必须排除通信线路的问题;
- 用串口调试助手测试一下硬件和驱动的性能。
- 串口BUF改大点,速度放慢点试试看
问题解决
- 串口丢包是不可避免的,因此应该从通讯协议和交互方式上着手改进,使得在偶尔数据丢包的情况下,能尽可能使双方发送的数据仍能被对方接收;
- 通讯协议不要采用一收一发的形式,最好开两个线程,一个用来接收解析数据,另外一个用来定时循环发送数据;
3.串口通讯,数据接收、解析时出现“stack smashing detected”错误,即段错误,导致上位机程序崩溃
- 上位机数据接收时,在check sum 错误的情况下,未对变量m_rcv_len清零,使得m_rcv_len越来越大,超过RCV_BUFFER[buffer_size] 的size,就会出现段错误;
tips::段错误往往难以通过gdb调试准确定位具体位置,一定要对各种情况的逻辑进行充分的梳理,根据异常打印信息逐步排查;
4. uart解析实例
参考:串口通信协议制定https://mp.youkuaiyun.com/console/editor/html/108194381代码
uart是全双工通信,可开两个线程,一个用来接收解析数据,另外一个用来定时循环发送数据;
read()和write()函数操作的是读缓存区和写缓存区,不需要进行mutex.lock();
FD_ISSET(m_fd, &rd)检查串口描述符是否准备好,以便进行接下来的处理操作;如果未准备好,会直接返回-1;
因此,串口通讯,最好有个循环一直调用recv_mcu_data()接收函数,直到接收成功.
经测试,调用一次recv_mcu_data()很多时候是接收失败的,因为串口资源未准备好(被MCU send占用);一般要2-6次调用recv_mcu_data(),才会接收成功一次。
循环可以写在recv_mcu_data()内,变成阻塞直到接收成功为止;也可在外部反复调用recv_mcu_data(),直到接收成功(一定次数内)。
5. 和多线程互斥锁mutex同用时,造成的死锁问题
一般情况下两个线程对同一个mutex进行lock,并不会造成死锁,后lock的线程会进入等待状态,直到前一个进行unlock。
但如果,在lock代码块中有串口通信(文件读写)recv_mcu_data()时,两个线程也会导致程序卡死,无法发送和接收数据(在欠驱手串口通信读、写线程中测试到,如果将串口通信recv_mcu_data()函数放在lock代码块之外,则不会造成死锁)。 因为串口通信、文件读写等输入输出操作,本身就是线程互斥的。
6.打开串口后,清除缓存
fd = open("devpath", O_RDWR|O_NOCTTY);
usleep(200000);
tcflush(fd, TCIFLUSH); //清空输入缓存
tcflush(fd, TCOFLUSH); //清空输出缓存
7.linux 串口编程详解
https://blog.youkuaiyun.com/jiesunliu3215/article/details/109674157