0

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

我希望每 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 文章在串行 com 上使用 Do While 循环遍历缓冲区中的每个字符所建议的尝试 2 ,这种方法也没有产生任何好的结果。

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
}

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

谢谢你。

4

1 回答 1

3

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

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

于 2013-07-21T20:41:56.857 回答