串口无法读取完整传输

时间:2013-07-21 18:59:16

标签: c++ c serial-port

我试图修改Teunis van Beelen的Rs232库,从Polling到事件驱动和非重叠以适合我的项目。 RS232 Library

我希望每200毫秒收到一些数据块(大约100到200个字符)。

我遇到的问题是收到的数据非常不一致,它在随机点被切断,而且不完整。

我希望ReadFile()只在读完一整个数据块后才能返回。(或其他类似的东西)

我觉得问题在于超时设置,因为通过改变数字我会得到不同的结果,但我不能正确,我的最佳结果到目前为止已将所有超时值设置为0并让ReadFile ()期望150个字节,这样ReadFile()不会返回,除非它读取150个字符,但这只是在几次传输后失去同步,因为我不知道要预期多少数据。

这些是Teunis代码中轮询功能的主要变化,除了超时设置外,所有其他设置都保持不变:

//Using the EV_RXCHAR flag will notify the thread that a byte arrived at the port
 DWORD dwError  = 0;
//use SetCommMask and WaitCommEvent to see if byte has arrived at the port
//SetCommMask sets the desired events that cause a notification.
if(!SetCommMask(Cport[comport_number],EV_RXCHAR)){
    printf("SetCommMask Error");
    dwError = GetLastError();
    // Error setting com mask
    return FALSE;
}
//WaitCommEvent function detects the occurrence of the events.
DWORD dwCommEvent;
for( ; ; )
{
    //wait for event to happen
    if (WaitCommEvent(Cport[comport_number],&dwCommEvent,NULL))
    {
        if(ReadFile(Cport[comport_number], buf, 1, (LPDWORD)((void *)&n), NULL)){
            //Byte has been read, buf is processed in main
        }
        else{
            //error occoured in ReadFile call
            dwError = GetLastError();
            break;
            }
    else{
        //error in WaitCommEvent
        break;
    }

    break;  //break after read file
}

按照MSDN article on serial com的建议尝试2使用Do While循环缓冲区中的每个字符,这种方法也没有产生任何好的结果。

DWORD dwError  = 0;

/*
Using the EV_RXCHAR flag will notify the thread that a byte arrived at the port
*/
//use SetCommMask and WaitCommEvent to see if byte has arrived at the port
//SetCommMask sets the desired events that cause a notification.
if(!SetCommMask(Cport[comport_number],EV_RXCHAR)){
    printf("SetCommMask Error");
    dwError = GetLastError();
    // Error setting com mask
    return FALSE;
}
//WaitCommEvent function detects the occurrence of the events.
DWORD dwCommEvent;
for( ; ; )
{
    //wait for event to happen
    if (WaitCommEvent(Cport[comport_number],&dwCommEvent,NULL))
    {
        //Do while loop will cycle ReadFile until bytes-read reach 0,
        do{
        if(ReadFile(Cport[comport_number], buf, size, (LPDWORD)((void *)&n), NULL)){
            //Byte has been read, buf is processed in main
        }
        else{
            //error occoured in ReadFile call
            dwError = GetLastError();
            break;
            }
            }while(n);
        }
    else{
        //error in WaitCommEvent
        break;
    }
    break;  //break after read file
}

我想知道在重叠模式下重写代码是否会改进,但我没有看到优点,因为我不需要多线程。任何建议都会很棒!

谢谢。

1 个答案:

答案 0 :(得分:3)

ReadFile无法检测“数据块”是什么。您不应该期望它能够理解您的数据或数据的时间。解决此问题的唯一方法是让您处理它提供的任何内容,使用您自己的数据知识将其划分为“块”以进行进一步处理。如果你得到一个部分块保留它,并在下一次读取时附加到它。

无需为数据调用WaitCommEvent。 ReadFile将等待数据。但是给它一个适当大小的缓冲区,一次要求多个字节。只调用一个字节是非常低效的。选择请求的计数和超时,以便ReadFile将在可接受的时间内返回,无论是否有数据。