最近做一个串口和FPGA通信的程序,Linux环境下,使用select+read去读取串口。在使用的过程中开始总是提示接收的数据有误。一直没有去仔细核对过read读取的数据长度。才导致了这个问题的产生。
select其实只能监控串口fd文件的写入变化,不能监控到是否写入了合格字节数。比如我串口发送端发送了10个字节,而select很可能在fd接收到1个字节时就已经检测到了,而等待read去读取的时候,串口发送端只写入了8个字节的,这个时候,假如你不判断read读取返回字节数,那你接收到的数据肯定是不完整的。
解决方案有两个:
1、延时。假如你串口设定115200的波特率,那么你可以算算,传输一个位,你需要8.6μs,10bit(8个数据位+1个stop+1个开始bit)就是86μs,10个字节你再乘以10你就能算出来了,期间可以忽略cpu的指令周期耗时,太短了。我使用的usleep()这个系统调用。
2、每次读取一个字节,让read循环读取,直到达到预期的字节数为止,因为read是阻塞的,会一直等待串口数据,read的fd指针会根据每次读取的结果往后移,没有数据是不会后移的,所以,你不用关心,已经读取过的字节是否会影响。不放心你可以做个试验便知。
方案2中比方案一中的好处是显而易见的,假如你读取的数据量非常大,而且,非常的密集。吞吐量也相当大,建议使用第二种方案,因为10字节,你就可以在一个read周期内节省下1ms,对于cpu你可以干很多事情了。当然2中也会造成数据处理的麻烦,因为是单字节的,后期可能造成的问题,是相当多的。所以,在没有相当复杂的功能面前,建议使用第一种方式。追求完美的,可以考虑第二种。
其实,这里讲的是串口收发的安全性,select+read是存在安全问题的。