本人在程序中要用到串口,在处理串口的过程中碰到一个令我感到极为疑惑的现象,希望有知道的大侠指点一下!
下面我将问题详细描述一下:处理串口的方式我参考了CSerialPort类,因为感觉CSerialPort类在接收方面效率较低,又不好怎么处理modbus rtu类的协议,所以我将接收方面做了修改,另外写串口没有在线程函数内。具体思路是:初始化串口后,建立读监视线程,调用WaitCommEvent函数,如果函数返回FALSE,调用GetLastError,如果为IO_PENDING,转入WaitForSingleObject后续处理,如果是其他,报错处理。如果WaitCommEvent返回TRUE,调用ClearCommError看cbInQue,如果为0,continue(和CSerialPort同)。接下来WaitForSingleObject阻塞线程等待,如果为OBJECT_0,调用接收函数RecvChar处理,RecvChar处理和CSerialPort有点不同,具体是在for(;;)中每次读1个字符,一直读缓冲区,直到cbInQue为0,再用Sleep等待5ms,如果确实无后续字符到达,结束接收并发送消息。(由于断定调用RecvChar时cbInQue肯定不为0,因为为0时监视线程continue掉了,同时后续的处理用到了即使为0仍等待5ms才判断结束,所以一开始没有cbInQue== 0的判断)。
我的问题是,当我在一收一发的应用中,发现当我发送一帧查询命令,程序收到了两次通知接收的消息。第一条消息后,数据全部被接收,是完整的,第二次接收长度为0。按照程序的设想,在RecvChar处理过程中,后续字符可能到达,并置位EV_RXCHAR,和WaitForSingleObject中的事件,当从RecvChar返回监视线程,WaitCommEvent应该返回TRUE,并continue掉,根本不会发出第二条通知接收的消息。但是情况是第二条消息确实发出了。我猜测除非是这样一种情况:在调用RecvChar处理接收时,每调用一次ReadFile系统都清除一次EV_RXCHAR,由于在WINDOWS中EV_RXCHAR产生的次数总是等于或比接收到的字符数少(这点和单片机不同),这样在RecvChar返回时已经没有EV_RXCHAR了,只有WaitForSingleObject中的事件了(ReadFile并不复位这一事件)。再返回监视线程时,调用WaitCommEvent结果是FALSE,转入WaitForSingleObject处理,触发了第二次读,因为缓冲区没有字符,所以仅触发了一次接收消息。由于没有找到EV_RXCHAR触发,复位的相关信息,所以不知道自己的猜测对不对,还望知道的回复一下!

解决方案 »

  1.   

    搜“Xon Xoff”
      

  2.   

    建议使用CxSerial类
    http://www.cnblogs.com/EdmundDwyane/p/3161524.html
      

  3.   

    串口收发,俺习惯
    发送---主动调用
    接收---线程接收在主程序中不停的判断某一帧是否接收完成。使用多级大缓冲,一级只管接收,循环缓冲区,大小为2^n字节,一般为64K字节,用一个unsigned short的变量当成写入下标。for( 本次接收的数量 )
    buffer_level_1[ io_read++ ] = 本次接收的字符[ i ];1级存放完整的数据根据业务要求,再设置2级,或3级缓冲,有时发送一条,会收到多条响应,那么2级中就会存放分成帧的数据,一般还是在线程中进行分帧,只要io_read与io_recv不一致,则在线程中不停的等待。