我有以下问题:
我通过UART接收传感器数据(每10ms),我想用gtk处理这些数据。该想法是在特定时间间隔(例如,每100ms)处理该数据。因此,我使用 g_timeout_add()函数。 被调用函数包含UART通信的公共集 - >在我的情况下它会阻止,直到我收到10个字符。 这就是问题 - 在我的read()( - >系统调用)函数中程序挂起。
我的串口设置如下:
struct termios oldtio,newtio;
tcgetattr(fd,&oldtio);
bzero(&newtio, sizeof(newtio));
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;
// set input mode (non-canonical, no echo,...)
newtio.c_lflag = 0;
newtio.c_cc[VTIME] = 0; // inter-character timer unused
newtio.c_cc[VMIN] = 10; // blocking read until 10 chars received
res = read(fd,buf,20); // returns after 10 chars have been input
无论我如何更改g_timeout_add函数中的interval参数,都没有任何反应。
我读了很多关于这个问题,但我找不到任何解释我的问题。此外,我甚至找不到处理UART - GTK组合的线程。
代码很长,因为如果您认为这个想法基本上可行或者我的概念中存在根本问题,我现在只想问你?
仅供参考:我在没有GUI( - > GTK)的情况下测试了这段代码,它运行得很完美。在纯C中我可以读取数据并打印它。
我很高兴得到任何答案。
答案 0 :(得分:1)
sleep(5)
),你不能做一个需要很长时间才能在回调中执行的处理。
想想两个工人(主循环和回调)只有挖洞和只有一个铲子(CPU时间)。主循环看到有一个超时事件要处理并将铲子提供给回调以便它可以工作。如果回调占用铲子5个小时,主循环无法完成其工作(如绘制UI窗口),也不会让铲子等待任何其他回调。
在您的情况下,您正在以阻止的方式等待数据。你正在等待10个字节到达。事件,如果他们需要5个小时到达,你保持铲子。要解决这个问题,您需要:
对于轮询解决方案,您可能可以实现VMIN = 0 and VTIME > 0
情况,但是您需要处理这样一个事实:您必须重建消息,因为您可能会收到比预期更多的字节。< / p>
对于线程解决方案,我会使用GThread
来执行您现在正在执行的阻止read
调用,并删除g_timeout_add
。您不需要它,因为您从轮询模型(“我是否已收到数据?”每秒10次)更改为通知模型(“您已收到数据!”)。相反,当你在线程中读取了一些字节时,用g_idle_add
将它们发送到主循环。在相关的回调中,您将收到您的数据,并能够将其呈现给用户。但是请记住你绝不应该从主线程以外的线程调用GTK +函数,因为工具包不是线程安全的。这就是为什么我们g_idle_add
(来自GLIB,这没关系)。