MiniGUI串口.docx

上传人:b****5 文档编号:6909117 上传时间:2023-01-12 格式:DOCX 页数:42 大小:114.70KB
下载 相关 举报
MiniGUI串口.docx_第1页
第1页 / 共42页
MiniGUI串口.docx_第2页
第2页 / 共42页
MiniGUI串口.docx_第3页
第3页 / 共42页
MiniGUI串口.docx_第4页
第4页 / 共42页
MiniGUI串口.docx_第5页
第5页 / 共42页
点击查看更多>>
下载资源
资源描述

MiniGUI串口.docx

《MiniGUI串口.docx》由会员分享,可在线阅读,更多相关《MiniGUI串口.docx(42页珍藏版)》请在冰豆网上搜索。

MiniGUI串口.docx

MiniGUI串口

目前,嵌入式Linux设备已广泛应用到计算机、通信和工业控制等领域,负责各种数据的处理和存储,并进行控制决策。

MiniGUI是一种面向嵌入式系统和实时系统的图形用户界面支持系统。

在MiniGUI环境下实现多个RS-232串口通信,多串口实时协同工作,可满足许多工控和通信场合需要。

该文实现平台为扩展了5个串口的IntelPXA255Sitsang的嵌入式硬件平台以及基于嵌入式Linux2.4.19的软件平台,采用MiniGUI作为图形用户界面,在MiniGUI的两个运行模式下设计并实现了多个串口的实时双工通信。

1 MiniGUI及其两个运行模式

   目前,在Linux之上进行(实时)嵌入式系统开发,一般选择如下几种GUI系统:

紧缩的XWindow系统、MiniGUI、MicroWindows、OpenGUI、QT/Embedded等。

该文采用MiniGUI1.3.0版本作为系统GUI,应用程序建立在图形界面和嵌入式Linux内核之上。

   MiniGUI可以编译成两个截然不同的运行模式:

一个是MiniGUI-Threads,一个是MiniGUI-Lite。

MiniGUI-Threads具有非常高的实时性,采用了线程机制。

MiniGUI-Threads的应用程序,可以具有多个线程,每个线程有不同的功能和任务,可以在不同的线程中建立多个窗口,但所有的窗口在一个进程或者地址空间中运行。

不同的线程之间可通过MiniGUI的消息传递机制进行事件传送和同步。

但显然,这种基于线程的结构也导致了系统整体的脆弱,如果某个线程因为非法的数据访问而终止运行,则整个进程都将受到影响。

不过,这种体系结构对实时控制系统等时间关键的系统来讲,还是非常适合的。

为了改变Threads版本体系上的脆弱,MiniGUI-Lite版本使用进程机制。

和MiniGUI-Threads相反,MiniGUI-Lite上的每个程序是单独的进程,每个进程也可以建立多个窗口。

在Lite版本中,可以同时运行多个MiniGUI应用程序。

首先需要启动一个服务器程序mginit,然后启动其他作为客户端运行的MiniGUI应用程序。

如果因为某种原因客户终止,服务器不受影响,可以继续运行。

2 MiniGUI-Threads下多线程串口通信

  串口通信程序要做到实时性高,吞吐量大,程序的输出与输入是两个需要并发执行的操作,因此在MiniGUI-Threads下采用多线程技术。

在多串口的MiniGUI环境下,通信程序至少应具备如下两个线程:

主线程和串口*线程。

主线程是串口通信程序的管理者,用来进行人机交互的操作、部分串口操作和数据处理及协调好各线程运行;串口*线程的职责是实时*各个串口的状态,一旦发生预定的事件,需要判断是哪个串口有数据到来,然后进行一定的数据处理,并立即向主线程发送相应消息,请求主线程对其进行相应处理。

主线程在接到串口*线程发送来的消息后,立即调用相应的过程函数进行处理。

串口通信程序可以在MiniGUIMain()中通过CreateThreadForMainWindow函数创建了两个并发的线程,定义线程的入口函数地址并返回线程标识符。

   在主线程中配置termios结构完成对串口的初始化操作,创建主窗口,建立控键并进入消息循环。

*线程和主线程同时启动,此后串口*线程在后台对各个串口进行实时*,在*到预定事件时,立即通过SendMessage向主线程发送相应的消息。

与此同时,主线程对*线程发送来的消息作出相应的处理,读取串口数据到缓冲区。

主线程在处理完该消息后,串口*线程继续执行后面的程序代码,对串口继续*。

主线程还可以同时进行其他工作,比如接收或处理键盘、鼠标一类的消息,数据显示和响应控件事件等。

   MiniGUI-Threads下的SendMessage的传递机制,可以用来发送“同步消息”。

如果发送消息的线程和接收消息的线程不是同一个线程,发送消息的线程将阻塞并等待另一个线程的处理结果,然后继续运行;如果发送消息的线程和接收消息的线程是同一个线程,则与MiniGUI-Lite的SendMessage一样,直接调用接收消息窗口的过程函数。

   MiniGUI定义了MSG_USER宏,用户能够自定义消息,并利用自定义消息传递数据。

应用程序可如下定义自己的消息:

#defineMSG_MYMESSAGE1(MSG_USER+1);

#defineMSG_MYMESSAGE2(MSG_USER+2)。

   这种方式能有效防止数据的堵塞,避免线程出现死锁等情况的出现。

MiniGUI-Threads下串口通信程序过程如图1所示。

图1 串口通信程序框图

3 MiniGUI-Lite下多进程串口通信

  Lite版本是支持客户服务器(C/S)方式的多进程系统,在运行过程中有且仅有一个服务器程序在运行,它的全局变量mgServer被设为TRUE,其余的MiniGUI应用程序为客户,mgServer变量被设为FALSE。

各个应用程序分别运行于各自不同的进程空间,如图2所示。

图2 Lite版本下的多进程系统

   串口通信程序要在MiniGUI-Lite下做到实时性高,吞吐量大,管理协调,可以参照MiniGUI-Threads下串口通信程序的设计,分别建立服务器程序和客户*程序。

   根据MiniGUI-Lite的特点,多串口通信程序首先初始化并启动服务器程序。

MiniGUI-Lite下服务器程序名需要命名为mginit,该程序为客户应用程序准备共享资源,并管理客户应用程序。

首先,需要初始化OnNewDelClient和OnChangeLayer这两个服务器程序特有的全局变量。

这两个变量是两个函数的指针变量,分别用来*来自客户和层的事件。

当客户连接到mginit或者断开与mginit之间的套接字连接时,如果程序设置了OnNewDelClient这个变量,将调用这个变量指向的函数。

同样,当MiniGUI-Lite的层发生变化时,比如有新的客户加入到某个层,或者层中的活动客户发生了变化,如果程序中设置了OnChangeLayer这个变量,则会调用这个变量指向的函数。

通过调用这些函数,可以得到客户标号或者层的指针、客户指针,mginit程序就可以方便地访问MiniGUI函数库中的内部数据结构,获得当前的客户以及当前层的所有信息,从而管理客户程序。

接着调用ServerStartup函数启动mginit的服务器功能,这个函数所做的工作比较简单,就是建立*客户连接的套接字(/var/tmp/minigui)并返回。

最后调用SetDesktopRect设定屏幕上由服务器独占的矩形区域,客户程序不能使用这块矩形区域。

设定之后,客户程序就只能在这个独占的区域以外进行绘制。

服务器初始化完毕后,用exec_app()函数启动客户串口*程序,完成服务器和客户程序的建立。

  为了实现客户和服务器之间的通讯,MiniGUI-Lite通过经过封装的UNIXDomainSocket处理函数在服务器和*程序之间进行数据传递。

服务器可以使用serv_listen()函数建立一个*套接字,并返回套接字文件描述符:

#defineLISTEN_SOCKET"/var/tmp/mysocket"

staticintlisten_fd;

BOOLlisten_socket(HWNDhwnd)

{

 if((listen_fd=serv_listen(LISTEN_SOCKET))<0)

returnFALSE;

eturnRegisterListenFD(fd,POLL_IN,hwnd,NULL);/*在系统中注册*文件描述符,在被*的文件描述符上发生指定事件时,向某窗口发送MSG_FDEVENT消息*/

}

   当服务器接收到来自客户的连接请求时,服务器hwnd窗口将接收到MSG_FDEVENT消息,这时,服务器可接受该连接请求:

intMyWndProc(HWNDhwnd,intmessage,WPARAMwParam,LPARAMlParam)

{

switch(message){

caseMSG_FDEVENT:

if(LOWORD(wParam)==listen_fd){/*来自*套接字*/

pid_tpid;uid_tuid;intconn_fd;

conn_fd=serv_accept(listen_fd,&pid,&uid);/*服务器调用serv_accept()函数接受来自客户的连接请求*/

if(conn_fd>=0){

RegisterListenFD(conn_fd,POLL_IN,hwnd,NULL);}

}

else{ intfd=LOWORD(wParam);/*来自已连接套接字*/

sock_read_t(fd,...);/*处理来自客户的数据*/

sock_write_t(fd,....);}

break;

 }

}

上面的代码中,服务器将连接得到的新文件描述符也注册为*描述符,因此,在MSG_FDEVENT消息的处理中,应该判断导致MSG_FDEVENT消息的文件描述符类型,并适当处理。

在客户端,当需要连接到服务器时,可通过如下代码:

intconn_fd;

if((conn_fd=cli_conn(LISTEN_SOCKET,'b'))>=0){

/*客户调用cli_conn函数连接到服务器*/

sock_write_t(fd,....);/*向服务器发送请求*/

sock_read_t(fd,....);}/*获取来自服务器的处理结果*/

4 两种模式下需要注意的一些差别

4.1 实现串口*程序的差别

串口*程序担当着实时*的任务,*预定义事件。

在MiniGUI-Threads下*线程需要给主线程发送预定义消息;在MiniGUI-Lite下,*程序要完成和服务器的数据交换和通信。

在这里,预定义事件就是多个串口中有一个串口有数据到来时,判断并锁定这个串口进行数据读取。

使用I/O多路复用(I/Omultiplexing)技术可以很好地解决这个问题。

其基本思想是:

先构造一张有关描述符的表,然后调用一个函数,它要到这些描述符中的一个已准备好的进行I/O时才返回。

在返回时,它告诉线程哪一个描述符已准备好可以进行I/O。

使用这种返回值,就可调用相应的I/O函数(一般是read或write),并且确知该函数不会阻塞。

   Linux下的系统调用select函数可以执行I/O多路复用。

Select函数原型为:

Intselect(intmaxfdp1,fd_set*readfds,fd_set*writefds,fd_set*exceptfds,Structtimeval*tvptr);

   在MiniGUI-Threads中,因为每个线程都有自己相应的消息队列,而系统消息队列是由单独运行的desktop线程管理的,所以任何一个应用程序建立的线程都可以长时间阻塞,从而可以使用select系统调用。

   在MiniGUI-Lite之上运行的应用程序只有一个消息队列。

应用程序在初始化之后,会建立一个消息循环,然后不停地从这个消息队列当中获得消息并处理,直到接收到MSG_QUIT消息为止。

应用程序的窗口过程在处理消息时,要在处理完消息之后立即返回,以便有机会获得其他的消息并处理。

现在,如果应用程序在处理某个消息时*某个文件描述符而调用select系统调用,就有可能会出现问题———因为select系统调用可能会长时间阻塞,而由MiniGUI-Lite服务器发送给客户的事件得不到及时处理。

这样,消息驱动的方式和select系统调用就难于很好地融合。

在MiniGUI-Lite当中,可以用以下几种方法解决这一问题:

①在调用select系统调用时,传递超时值,保证select系统调用不会长时间阻塞;

②设置定时器,定时器到期时,利用select系统调用查看被*的文件描述符。

如果没有相应的事件发生,则立即返回,否则进行读写操作;

③利用MiniGUI-Lite提供的RegisterListenFD函数在系统中注册*文件描述符,并在被*的文件描述符上发生指定的事件时,向某个窗口发送MSG_FDEVENT消息。

4.2 处理同步问题的差别

   在MiniGUI-Threads下,对于共享资源的互斥性同步,可以使用“互斥(mutex)”来解决,它是一种锁或者信号灯,相关宏定义和函数包含在中。

当一个线程调用pthread_mutex_lock()函数锁定某个Mutex后,其它也要锁定Mutex的线程将被阻塞,直至Mutex被释放,从而达到资源的独占。

对于线程按正确顺序执行的顺序同步,正如上面提到的,Sendmessage的消息传递机制起到了“事件同步”的作用。

当一个线程要等待另一个线程的某个事件时,会把自己挂起,直至另一个线程的相应事件发生后把自己唤醒。

而在MiniGUI-Lite中主要是应用程序间的互斥性同步,可以使用Linux下常用的“信号量机制”等方式解决多个进程的共享与互斥问题。

5 结论

   在嵌入式GUI环境下,需要结合操作系统和GUI系统的特点,充分利用两者的资源来实现多串口通信。

在IntelPXA255Sitsang板上实践证明,在MiniGUI-Threads下采用多线程技术,在MiniGUI-Lite下采用服务器程序结合*程序,实现多串口全双工通信,有效地解决了在串口通信中的实时响应问题,降低了数据的丢失率,提高了嵌入式系统的可靠性。

 

MiniGUI-Threads与MiniGUI-Lite下多串口通信的设计与实现

来源:

电子开发网作者:

章坚武许作鹏董平时间:

2008-07-08

 目前,嵌入式Linux设备已广泛应用到计算机、通信和工业控制等领域,负责各种数据的处理和存储,并进行控制决策。

MiniGUI是一种面向嵌入式系统和实时系统的图形用户界面支持系统。

在MiniGUI环境下实现多个RS-232串口通信,多串口实时协同工作,可满足许多工控和通信场合需要。

该文实现平台为扩展了5个串口的IntelPXA255Sitsang的嵌入式硬件平台以及基于嵌入式Linux2.4.19的软件平台,采用MiniGUI作为图形用户界面,在MiniGUI的两个运行模式下设计并实现了多个串口的实时双工通信。

1 MiniGUI及其两个运行模式

目前,在Linux之上进行(实时)嵌入式系统开发,一般选择如下几种GUI系统:

紧缩的XWindow系统、MiniGUI、MicroWindows、OpenGUI、QT/Embedded等。

该文采用MiniGUI1.3.0版本作为系统GUI,应用程序建立在图形界面和嵌入式Linux内核之上。

MiniGUI可以编译成两个截然不同的运行模式:

一个是MiniGUI-Threads,一个是MiniGUI-Lite。

MiniGUI-Threads具有非常高的实时性,采用了线程机制。

MiniGUI-Threads的应用程序,可以具有多个线程,每个线程有不同的功能和任务,可以在不同的线程中建立多个窗口,但所有的窗口在一个进程或者地址空间中运行。

不同的线程之间可通过MiniGUI的消息传递机制进行事件传送和同步。

但显然,这种基于线程的结构也导致了系统整体的脆弱,如果某个线程因为非法的数据访问而终止运行,则整个进程都将受到影响。

不过,这种体系结构对实时控制系统等时间关键的系统来讲,还是非常适合的。

为了改变Threads版本体系上的脆弱,MiniGUI-Lite版本使用进程机制。

和MiniGUI-Threads相反,MiniGUI-Lite上的每个程序是单独的进程,每个进程也可以建立多个窗口。

在Lite版本中,可以同时运行多个MiniGUI应用程序。

首先需要启动一个服务器程序mginit,然后启动其他作为客户端运行的MiniGUI应用程序。

如果因为某种原因客户终止,服务器不受影响,可以继续运行。

2 MiniGUI-Threads下多线程串口通信

  串口通信程序要做到实时性高,吞吐量大,程序的输出与输入是两个需要并发执行的操作,因此在MiniGUI-Threads下采用多线程技术。

在多串口的MiniGUI环境下,通信程序至少应具备如下两个线程:

主线程和串口监听线程。

主线程是串口通信程序的管理者,用来进行人机交互的操作、部分串口操作和数据处理及协调好各线程运行;串口监听线程的职责是实时监听各个串口的状态,一旦发生预定的事件,需要判断是哪个串口有数据到来,然后进行一定的数据处理,并立即向主线程发送相应消息,请求主线程对其进行相应处理。

主线程在接到串口监听线程发送来的消息后,立即调用相应的过程函数进行处理。

串口通信程序可以在MiniGUIMain()中通过CreateThreadForMainWindow函数创建了两个并发的线程,定义线程的入口函数地址并返回线程标识符。

在主线程中配置termios结构完成对串口的初始化操作,创建主窗口,建立控键并进入消息循环。

监视线程和主线程同时启动,此后串口监视线程在后台对各个串口进行实时监控,在监视到预定事件时,立即通过SendMessage向主线程发送相应的消息。

与此同时,主线程对监视线程发送来的消息作出相应的处理,读取串口数据到缓冲区。

主线程在处理完该消息后,串口监视线程继续执行后面的程序代码,对串口继续监听。

主线程还可以同时进行其他工作,比如接收或处理键盘、鼠标一类的消息,数据显示和响应控件事件等。

MiniGUI-Threads下的SendMessage的传递机制,可以用来发送“同步消息”。

如果发送消息的线程和接收消息的线程不是同一个线程,发送消息的线程将阻塞并等待另一个线程的处理结果,然后继续运行;如果发送消息的线程和接收消息的线程是同一个线程,则与MiniGUI-Lite的SendMessage一样,直接调用接收消息窗口的过程函数。

MiniGUI定义了MSG_USER宏,用户能够自定义消息,并利用自定义消息传递数据。

应用程序可如下定义自己的消息:

#defineMSG_MYMESSAGE1(MSG_USER+1);

#defineMSG_MYMESSAGE2(MSG_USER+2)。

这种方式能有效防止数据的堵塞,避免线程出现死锁等情况的出现。

MiniGUI-Threads下串口通信程序过程如图1所示。

 

                                               

 

                                                                              图1 串口通信程序框图

3 MiniGUI-Lite下多进程串口通信

  Lite版本是支持客户服务器(C/S)方式的多进程系统,在运行过程中有且仅有一个服务器程序在运行,它的全局变量mgServer被设为TRUE,其余的MiniGUI应用程序为客户,mgServer变量被设为FALSE。

各个应用程序分别运行于各自不同的进程空间,如图2所示。

           

 

                      图2 Lite版本下的多进程系统

串口通信程序要在MiniGUI-Lite下做到实时性高,吞吐量大,管理协调,可以参照MiniGUI-Threads下串口通信程序的设计,分别建立服务器程序和客户监听程序。

根据MiniGUI-Lite的特点,多串口通信程序首先初始化并启动服务器程序。

MiniGUI-Lite下服务器程序名需要命名为mginit,该程序为客户应用程序准备共享资源,并管理客户应用程序。

首先,需要初始化OnNewDelClient和OnChangeLayer这两个服务器程序特有的全局变量。

这两个变量是两个函数的指针变量,分别用来监视来自客户和层的事件。

当客户连接到mginit或者断开与mginit之间的套接字连接时,如果程序设置了OnNewDelClient这个变量,将调用这个变量指向的函数。

同样,当MiniGUI-Lite的层发生变化时,比如有新的客户加入到某个层,或者层中的活动客户发生了变化,如果程序中设置了OnChangeLayer这个变量,则会调用这个变量指向的函数。

通过调用这些函数,可以得到客户标号或者层的指针、客户指针,mginit程序就可以方便地访问MiniGUI函数库中的内部数据结构,获得当前的客户以及当前层的所有信息,从而管理客户程序。

接着调用ServerStartup函数启动mginit的服务器功能,这个函数所做的工作比较简单,就是建立监听客户连接的套接字(/var/tmp/minigui)并返回。

最后调用SetDesktopRect设定屏幕上由服务器独占的矩形区域,客户程序不能使用这块矩形区域。

设定之后,客户程序就只能在这个独占的区域以外进行绘制。

服务器初始化完毕后,用exec_app()函数启动客户串口监听程序,完成服务器和客户程序的建立。

为了实现客户和服务器之间的通讯,MiniGUI-Lite通过经过封装的UNIXDomainSocket处理函数在服务器和监听程序之间进行数据传递。

服务器可以使用serv_listen()函数建立一个监听套接字,并返回套接字文件描述符:

#defineLISTEN_SOCKET"/var/tmp/mysocket"

staticintlisten_fd;

BOOLlisten_socket(HWNDhwnd)

{

 if((listen_fd=serv_listen(LISTEN_SOCKET))<0)

returnFALSE;

eturnRegisterListenFD(fd,POLL_IN,hwnd,NULL);/*在系统中注册监听文件描述符,在被监听的文件描述符上发生指定事件时,向某窗口发送MSG_FDEVENT消息*/

}

当服务器接收到来自客户的连接请求时,服务器hwnd窗口将接收到MSG_FDEVENT消息,这时,服务器可接受该连接请求:

intMyWndProc(HWNDhwnd,intmessage,WPARAMwParam,LPARAMlParam)

{

switch(message){

caseMSG_FDEVENT:

if(LOWORD(wParam)==listen_fd){/*来自监听套接字

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 外语学习 > 其它语言学习

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1