GTK +和串行输入(UART) [英] Gtk+ and serial input (UART)

查看:94
本文介绍了GTK +和串行输入(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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆