基于uClinux的GPSOne/GPS双定位信息汲取
发布日期:2011-05-19
叙述uClinux串口编程的底子要领;扼要先容利用体系的几种I/O模型,分外对基于select的I/O复用模型在监听多个配置时的实用性举行较过细的阐发;比较多个串口下利用轮询要领和利用select机制处理惩罚处罚的差别;连合GPSOne与GPS双定位导航体系的实例,给出双串口定位信息汲取的软件实现要领。
GPS是当前在导航体系中应用最广泛的定位技能之一,但GPS也有其自身的不敷。比喻,当GPS终端在修筑麋集的地方或在高架桥底劣等恶劣的地理位置时,定位信号比较容易丢失,通常难以获取有效的定位信息。由美国高通公司开辟的GPSOne定位模块,提供的定位信号是基于网络与蜂窝的定位技能。纵然在卫星信号不好的环境下,只要存在联通的网络信号,利用蜂窝定位技能,就可以较容易地得到定位信号。此信号可作为GPS信号丢失环境下的一种补偿信号。
GPSOne是传统GPS定位技能与CDMA网络技能奥妙连合的殽杂型定位技能,即GPSOne=AGPS+AFLT+CellID。它是第一种可以在室内稳固变乱的基于GPS技能的办理方案,是唯一商用的GPS定位办理方案,同时也是如本日下上最经济有效的集成型无线GPS办理方案。利用GPSOne可以大概补充GPS自身不敷的这一特点,本导航体系的定位信息获取模块采取GPS和GPSOne双定位方案,以实现改精确、可靠的定位。该定位信息获取模块的硬件架构是ARM+GPS+GPSOne;CPU采取Philips公司LP系列的LPC2210的ARM7芯片,利用体系采取uClinux。本体系获取定位信息的关键,在于编写好串口通讯步调,从而更好地及时汲取和处理惩罚处罚当前的位置信息。由于体系结果较为巨大,须要实现GUI界面交互、定位、报警、数据库查问、语音提示等多项结果,故对串口数据的汲取,利用I/O复用机制举行处理惩罚处罚更利于体系实现和办理。
1 uClinux串口编程利用要领
在Linux中,配置分为3类:字符配置、块配置和网络配置。uClinux用配置文件表现大部分I/O配置。文件体系提供了同一的接口来访问一样通常意义上的文件和配置文件。
体系串口COM1与COM2,分别映射uClinux体系的/dev/ttyS0、/dev/ttyS1两个串口配置文件。串口属于字符型配置,对串口的编程也便是对相应文件举行读/写、控制等利用。串口编程的底子步调是:先打开串口,设置串口属性,然失队行收发数据,着末封闭串口。
(1) 打开串口
通过利用标准的文件打开函数open,到达访问串口配置驱动的目标。比喻,以读写的要领打开串口1,可用下面的要领实现:
fd = open("/dev/ttyS0", O_RDWR);
(2) 设置串口属性
紧张是设置布局体termios各成员的值。底子设置包括:波特率、数据位、校验位、克制位、输入和输出模式等。一样通常在设置时,先获取体系已有的串口属性,并在它的底子上举行修改。别的,设置时要用到体系预定义的宏。
(连合实例的阐发略。——编者注)
(3) 收发数据
uClinux下串口发送和汲取数据,通过利用文件利用中的read和write的要领来实现。比喻:
write(fd, buffer ,Length);
read(fd, buffer ,Length);
(4) 封闭串口
封闭串口只须封闭已打开的串口文件形貌符,如close(fd) ;
2 常用的几种I/O模型
通常在利用I/O时,会用到下面几种模型之一:壅闭型I/O、非壅闭型I/O和复用型I/O。下面以读取串口数据为例,扼要阐发它们的底子领变原理和特点。
2.1 壅闭型I/O
顾名思义,它以壅闭要领利用I/O,如图1所示。若一个进程以壅闭要领调用read函数读取串口数据,则该进程会不绝就寝在read体系调用上。此时体系内核会不绝等待数据,直到串口有数据到达为止。当串口数据准备好后,内核就把数据从内核拷贝至用户空间;而当数据拷贝完成后,才唤醒串口读取进程,关照它读取数据报。
图1 壅闭I/O模型
2.2 非壅闭I/O
图2中,在非壅闭I/O模型下,I/O利用是及时完成的。当进程调用read函数时,设置了O_NONBLOCK标记,那么纵然串口没有数据可读,read函数也会立即返回。此时其返回值为EAGAIN,表明串口数据未就绪。要是串口有数据可读,则read函数会读取该数据,并返回所读数据的长度。通常轮询I/O的要领便是采取这种模型来读取串口数据的,此时进程必须通过重复调用来检测是否有数据可读。要是轮询频率过低,则容易丢失数据;轮询频率过高,则占用太多处理惩罚处罚器的处理惩罚处罚周期。
图2 非壅闭I/O模型
2.3 I/O复用
上述两种I/O模型,是最常用的两种利用I/O的要领;但在面向较巨大、须要处理惩罚处罚多个I/O的体系时,这两种模型存在着不敷之处。比喻:在应用进程中须要对多个I/O配置举行监听,当某个配置可读或可写时,进程能顿时得知,并举行干系处理惩罚处罚。这时若采取壅闭要领利用I/O,则进程会壅闭在某个配置的I/O读写利用上而不克不及实用于这种环境;若采取非壅闭要领,则通常须要定时或循环地探测全部配置,才作相应处理惩罚处罚,这种作法相称淹灭体系中间处理惩罚处罚器的实行周期。可见,上述的两个I/O模型都不克不及餍足这类应用,故此须要引入一种分外的I/O处理惩罚处罚机制,即I/O复用。
所谓I/O复用,是指当一个或多个I/O条件(可读、能写或出现非常)餍足时,进程能立即知道,从而正确并高效地对它们举行处理惩罚处罚。
在uClinux下,体系提供select函数和poll函数,用来支持I/O复用的实现。如图3所示,若利用select的体系调用来查问是否有数据可读时,进程是在等待多个I/O形貌接口的任一个变为可读,但此时期并不壅闭进程。当有数据报已准备好时,返回可读条件,并关照进程再次举行体系调用准备读取相应的I/O数据。此时内核就开始拷贝准备好的数据至用户空间,并返回指示进程处理惩罚处罚数据报。
图3 I/O复用模型
与上面提及的两种I/O模型差别的是:在这个处理惩罚处罚进程中,利用了两次体系调用来到达读取数据的目标。固然两次体系调用的开销宛如更大,但它的最大好处在于能同时等待多个形貌符准备好。因此select调用结果更多地是借助了内核来监听I/O配置形貌符的。下面细致先容select函数的结果及应用。
3 uClinux中基于select的I/O复用机制和变乱原理
在体系存在多个输入或输出流但不渴望此中任一个流被壅闭的场合,通常利用复用I/O的要领办理。uClinux中,用户步调多利用select机制实现I/O复用控制,select函数容许进程对一个或多个配置文件举行非壅闭的读或写利用。
select的函数定义于<unistd.h>中,原型如下:
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
该函数容许进程指示内核等待多个变乱中的任一个孕育产生,并仅在一个或多个变乱孕育产生或颠末某指定的时间后才唤醒进程。该函数的第1个参数n表现文件形貌符聚会合最大值再加1;第2个参数readfds,表现可读的文件形貌符聚集,用于查察是否有可读取数据;第3个参数writefds表现可写的文件形貌符聚集,用于查察是否能写入数据;第4个参数exceptfds用于非常控制;着末一个参数timeout决定了select将会壅闭多久才把控制权移交给调用它的进程。调用select之前,必须对此参数举行初始化。若timeout值为0,则select直接返回0。此时I/O利用没有等待就立即返回,相称于一种非壅闭I/O的调用。
在应用中,通常先调用select查察哪个I/O配置可读/写。要是没有可读/写的配置,并且没有设置超时返回结果,那么进程将壅闭在select调用上;要是有,则select函数返回,紧接着可通过测试参数readfds和writefds来确定哪个I/O配置可读或能写,而后以非壅闭要领利用该I/O配置,从而实现渴望结果。
在实现select应用的进程中,还会利用到这些select干系接口:
void FD_ZERO(fd_set *fdset);
void FD_SET(int fd, fd_set *fdset);
void FD_CLR(int fd, fd_set *fdset);
int FD_ISSET(int fd, fd_set *fdset);
此中,fd_set表现配置文件形貌符聚集,fd表现配置文件形貌符。FD_ZERO函数用于打扫配置文件形貌符聚集全部元素;FD_SET函数用于把某个文件形貌符添加至文件形貌符聚集;FD_CLR函数用于从文件形貌符聚会合删除某个文件形貌符;而FD_ISSET用于检测配置文件形貌符聚集的某个文件形貌符是否有效,有效则表现该位映射的配置有数据可读或可写。
4 轮询检测要领与select要领的比较
4.1 轮询检测要领
轮询检测要领是指对串口举行非壅闭的读写利用。当利用未告成时,让进程或线程挂起一段时间,然后再利用非壅闭调用来重新查问串口是否有可读/写数据。用此要领,相称于体系不绝地对汲取大概发送利用的实行结果举行探测,直到把数据发出去大概汲取完成定量的数据,才退出此轮询循环。而敷衍汲取与发送不确定哪个时间会到达的环境,即随机性比较高的读/写利用,采取轮询要相识导致CPU资源浪费。要是轮询频率过低,则会使体系少汲取一部分数据或汲取过慢;反之,则汲取方会由于等待太久而不克不及汲取更多新的数据。轮询频率过高的环境,会让CPU太过频繁地查问串口状态,导致过多的耗用CPU实行周期,低沉其利用率。
4.2 select机制能充分利用体系时间的缘故因由
与频繁调用非壅闭读写函数来轮询监听I/O的要领相比, select调用容许用户把进程本身挂起来,同时使体系内核监听所恳求的一组文件形貌符的恣意活动。只要确认在恣意被监控的文件形貌符上出现活动,select调用将返回指示该配置文件已经准备好的信息。如许就使进程能相对及时地监测到I/O配置上随机的变革,而不必由进程本身去探测输入数据是否准备好。
5 利用select I/O的机制实现GPS与GPSOne数据的汲取
本文提出的基于GPS与GPSOne信号的双定位的办理方案,即对体系两个串口定位信号的监听与处理惩罚处罚,充分利用uClinux下基于Select的I/O复用机制,更利于较巨大概系的控制和办理。
方案实现的步调流程如图4所示。
图4 双定位信息获取的步调流程
以下代码为利用Select I/O机制汲取GPS信息和GPSOne信息的软件实现:
int Maxfd = fd_gps>fd_gpsOne? fd_gps: fd_gpsOne;//得到串口形貌符中较大的一个
struct timeval tv;//定义超时控制布局
fd_set fds; //文件形貌符聚集变量
tv.tv_sec = 5;//设置超时价 5 s
tv.tv_usec = 0;
while(1){//通过GPSOne串口,发送GPSOne定位恳求
Rt = send_port (fd_gpsone, "AT+GPSSTRT\r", strlen("AT+GPSSTRT\r");
if (Rt) == -1)
printf("Error happened!");
FD_ZERO (&fds);//初始化文件形貌符聚集
FD_SET(*fd_gps, &fds);//设置文件形貌符聚集的相应位
FD_SET(fd_gpsOne, &fds);//利用select,让内核开始监听GPSOne和GPS串口配置
fd_sel = select((Maxfd)+1, &fds_gps, NULL, NULL, &tv);
if (fd_sel < 0){
printf("Error happened while receiving gps data.\n");}
else if (FD_ISSET(*fd_gps, &fds)){//若GPS串口配置有数据可读
recv_len = recv_port(fd_gps, buf, 254);
if (recv_len > 0){
memcpy (gps_info, buf, recv_len);//信息生存到
gps_info数组中gps_info_process(gps_info);//阐发定位信息处理惩罚处罚
}
}
else if (FD_ISSET(*fd_gpsOne, &fds)){//若GPSOne串口配置有数据可读
recv_len = recv_port(*fd_gpsOne, buf, 254);
if (recv_len > 0){memcpy (gpsOne_info, buf, recv_len); //信息生存到gpsOne_info数组中
gpsOne_info_process(gpsOne_info);//阐发定位信息处理惩罚处罚
}
}
sleep(1);
}
6 筹划总结
本文过细阐发白串口编程的底子要领和步调,并提出一种基于select的I/O复用机制处理惩罚处罚多个串口信息的方案,同时给出这种方案的细致实现。此方案具有较高的可靠性,包管了多个串口的信息可以很好地被汲取和处理惩罚处罚,并且不相互滋扰,利于体系更好地办理多个文件配置。分外是在数据征求和数据传输范畴中,select利用内核同时监听多个配置形貌符机制,可以被广泛地应用于嵌入式体系多路I/O征求的筹划中。编者注:本文为期刊缩略版,全文见本刊网站www.mesnet.com.cn。
参考文献
[1] Kurt Wall. GNU/Linux编程指南[M].张辉,译. 北京:清华大学出版社,2005.
[2] Richard Stevens W. UNIX网络编程[M]. 第2版. 第1卷·套接口API和X/Open传输接口API.北京:清华大学出版社,1998:121131.
[3] 马忠梅,李善平,康慨,等. ARM&Linux嵌入式体系教程[M].北京:北京航空航天大学出版社,2005:255261.
[4] 周建功.ARM嵌入式体系实行教程(2).广州:广州周建功单片机生长有限公司,2005:213219.
[5] 邓滔,徐勇. GPS与嵌入式Linux平台串行通讯研究[J]. 财产控制谋略机,2005,18(1).