我想在Linux和Windows上以一致的方式从串行端口读取数据。我注意到read()
和ReadFile()
的行为略有不同。考虑以下代码:
// on Linux
int r = read(fd, buf, 256);
// on Windows
ReadFile(handle, buf, 256, &r, NULL);
这两个函数将永远阻塞直到数据到达。到目前为止,一切都很好。但是,有一点区别:read()
将在至少1个字节到达时立即返回,而ReadFile()
在所有256个字节到达之前不会返回。
因此,我想问:是否有一种方法可以使ReadFile()
像Linux上的read()
一样,即即使请求了256个字节,只要有至少1个字节就返回?
答案 0 :(得分:0)
IMO最好的方法是实现循环缓冲区,使用您喜欢的函数从缓冲区中的流位置读取1个字节,然后调用receive回调函数-或仅轮询循环缓冲区以获取数据。
它可以解决所有问题-当数据到达时,您会收到通知(或可以轮询存在的数据),并且不会覆盖缓冲区(当然,如果缓冲区已满,则需要读取数据)您将忽略新数据)
这里您有一个非常简单的实现
unsigned char buff[128];
struct
{
unsigned head:8;
unsigned tail:8;
}control = {.head = 0, .tail = 0};
int isFull(void)
{
return (control.head + 1) == control.tail;
}
int isEmpty()
{
return control.head == control.tail;
}
int push(int ch)
{
if(!isFull())
{
buff[control.head++] = ch;
return 0;
}
return -1;
}
int pop(void)
{
if(!isEmpty())
{
return buff[control.tail++];
}
return -1;
}
简单用法
void (*rcvcallback)(void);
initReceive(void (*callback)(void))
{
rcvcallback = callback;
}
void receive(void)
{
int r = 0;
#ifdef LINUX
read(fd, &r, 1);
#endif
#ifdef WINDOWS
size_t size;
ReadFile(handle, &r, 1, &size, NULL);
#endif
push(r);
rcvcallback();
}
#ifdef WINDOWS
#define EL "\n\r"
#endif
#ifdef LINUX
#define EL "\n"
#endif
void myRCVcallback(void)
{
printf("Byte received: %d"EL, pop());
}
int main()
{
printf("Starting ......"EL);
while(1)
{
receive();
}
return 0;
}