GTK +和串行输入(UART) [英] Gtk+ and serial input (UART)
问题描述
我有以下问题:
我通过UART(每10毫秒)接收传感器数据,我想在gtk中处理该数据.想法是在特定的时间间隔(例如,每100毫秒)中处理此数据.因此,我使用了 g_timeout_add()函数.所调用的函数包含用于UART通信的通用集->在我的情况下,该函数将阻塞直到收到10个字符为止.这就是问题所在-在我的read()(->系统调用)函数中,程序挂断了.
I receive sensor data via UART (every 10ms) and I want to process this data in gtk. The idea is to process this data in specific time intervalls (e.g. every 100ms). Due to that I use the g_timeout_add() function. The called function contains the common sets for UART communication -> in my case it blocks until I receive 10 chars. And here is the problem - at my read() (-> system call) function the program hang up.
我的串行设置如下:
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参数,都不会发生.
Nothing happens, no matter how I change the interval parameter in the g_timeout_add function.
关于此问题,我读了很多书,但是找不到关于我的问题的任何解释.此外,我什至找不到处理UART-GTK组合的线程.
I read a lot about this issue, but I could not find any explanation for my problem. Further I could not even find threads dealing with UART - GTK combination.
代码很长,因为我现在只想问您,您是否认为这个想法基本可行,或者我的概念是否存在根本性的问题?
The code is very long, due to that I just want to ask you for now if you think that this idea basically could work or if there is a fundamental problem in my concept?
仅供参考:我在没有GUI(-> GTK)的情况下测试了此代码,并且效果很好.在纯C语言中,我可以读取数据并进行打印.
FYI: I tested this code without GUI (->GTK) and it works perfect. In pure C I can read the data and printf it.
我很高兴得到任何答案.
Im happy for any answer.
推荐答案
GTK +是事件驱动的.事件是在主循环中分派和处理的,主循环是流程的主线程.因此,您不能执行阻塞调用(例如 sleep(5)
),也不能执行需要很长时间才能在回调中执行的处理.
GTK+ like most toolkits is event-driven. Events are dispatched and processed in a main loop, which is the main thread of your process. So you can't do blocking calls (for example a sleep(5)
) and you can't do processing that takes a long time to execute in a callback.
想想两个工人(主循环和回调)只有要挖的孔,只有一个铲子(CPU时间).主循环看到有一个超时事件要处理,并将铲子提供给回调,以便它可以正常工作.如果回调程序将挖土铲占用了5个小时,则主循环将无法完成其工作(如绘制UI窗口),也无法将挖土铲交给其他等待它的回调.
Think of two workers (the main loop and the callback) that only have holes to dig and only one shovel (CPU time). The main loop sees there's a timeout event to process and gives the shovel to the callback so it can work. If the callback takes the shovel for 5 hours, the main loop can't do its work (like painting the UI windows) nor give the shovel to any other callback waiting for it.
在您的情况下,您正在以阻塞方式等待数据.您正在等待10个字节的到来.如果这需要他们5个小时才能到达,请保留铲子.要解决此问题,您需要:
In your case, you're waiting for data in a blocking way. You're waiting for 10 bytes to arrive. Event if that takes them 5 hours to arrive, you keep the shovel. To fix that, you need to:
- 在单独的线程中执行阻塞调用(因此,两个工作人员都有一把铲子,可以并行工作)
- 还是异步执行(也许使用 GTask ?我从来没有自己使用过)
- 或(效率较低)进行一些轮询,这已经是您已经在做的事情了,因为您每100ms查找一次数据
- do your blocking calls in a separate thread (so both workers have a shovel and can work in parallel)
- or do that asynchronously (maybe using GTask? Never used it myself)
- or (less efficient) do some polling, which is already what you are already doing since you are looking for data every 100ms
对于轮询解决方案,您可以实施 VMIN =0,并且VTIME>0
情况,但是您需要处理以下事实:必须重新构建消息,因为您可能一次收到比预期更多的字节.
For the polling solution, you could probably implement the VMIN = 0 and VTIME > 0
case, but you'd need to process the fact that you'll have to rebuild the messages as you could receive more bytes than expected at once.
对于线程解决方案,我将像现在一样使用 GThread
执行阻塞的 read
调用,并删除 g_timeout_add
.您将不需要它,因为您可以从轮询模型(每秒接收到数据吗?"每秒10次)更改为通知模型(您已经接收到数据!").相反,在线程中读取某些字节后,请使用 g_idle_add
将其发送到主循环.在关联的回调中,您将接收到数据并将其呈现给用户.但是请记住,您永远不要从主线程以外的线程调用GTK +函数,因为该工具包不是线程安全的.这就是为什么我们 g_idle_add
(这是从GLib来的,没关系).
For the threading solution, I'd use a GThread
to perform the blocking read
calls like you're doing now, and remove g_timeout_add
. You won't need it as you'd change from a polling model ("did I have received data?" 10 times per second) to a notification model ("you have received data!"). Instead, when in your thread you have read some bytes, send them to the main loop with g_idle_add
. In the associated callback you'll receive your data and will be able to present it to the user. Please remember however that you should never call GTK+ functions from threads other than the main thread, as the toolkit is not-thread-safe. That's why we g_idle_add
(wich is from the GLib, which is ok).
这篇关于GTK +和串行输入(UART)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!