基于ARM7与uClinux嵌入式智能终端系统
2014-03-12艾红
艾 红
(北京信息科技大学 自动化学院,北京 100192)
嵌入式系统在生活的各个方面都有其身影,比如人们平时广泛使用的手机、PDA、MP3、机顶盒都属于嵌入式系统设备。uClinux是Linux2.0的一个分支,被应用于微控制领域。uClinux最大的特征是没有MMU即内存管理单元模块,很适合那些没有MMU的处理器,例如ARM7-TDMI等。这种没有MMU的处理器在嵌入式领域中应用得相当普遍。同标准的Linux相比,由于uClinux上运行的绝大多数用户程序并不需要多任务。uClinux有完整的TCP/IP协议,同时对其他网络协议都提供支持,这些网络协议都在uClinux上得到了很好实现。基于ARM7和uClinux操作系统构建嵌入式系统硬件平台实现网页显示实时温度、数据采集、存储和人机交互功能。计算机图形界面是计算机与使用者之间的对话接口。随着嵌入式系统性能的不断提高,图形化的接口己经成为嵌入式设备应用领域中的一个热点。图形用户界面使人们能够更加方便地与机器进行互动操作,其中以MiniGUI为代表的嵌入式GUI较为突出,可以设计人机交互界面[1-2]。
1 嵌入式智能终端硬件平台
采用PHILIPS公司的ARM7微处理器LPC2210,其片内具有16KB静态RAM,8路10位A/D转换器。ARM7处理器硬件平台的外部资源如图1所示,包括2MB的NOR FLASH,16MB的NAND FLASH,8MB的RAM,两个9针D型串行接口,一个RJ45以太网接口,3个符合I2C总线协议的设备分别是LM75温度传感器、CAT1025E2PROM存储器和ZLG7290键盘接口芯片,还有一个TFT液晶屏。
图1 ARM7处理器硬件平台Fig.1 ARM7 processor hardware platform
I2C总线只需由两根信号线组成:一根是串行数据线SDA;另一根是串行时钟线SCL。SDA和SCL引脚是漏极开路输出结构。使用时SDA和SCL信号线要加上拉电阻。ARM7硬件平台中有3个设备是通过I2C协议来进行数据通信的,分别是LM75温度传感器、CAT1025数据存储器和ZLG7290键盘管理芯片。它们具有不同的地址,I2C存储器CAT1025的地址为0xA0,键盘管理芯片ZLG7290的地址为0x70,温度传感器芯片LM75的地址为0x90。
2 温度测量
2.1 温度测量硬件电路
LM75芯片温度测量范围是-55~125℃,LM75将温度直接转换为数字值,再通过ARM7处理器直接读取,硬件电路连接如图2所示。
图2 LM75电路连接图Fig.2 LM75 circuit connection diagram
LM75的工作电压为3.0~5.5 V,采用3.3 V直接供电。使用一片LM75时将芯片的A0~A2引脚接地,使其I2C地址为0x90。LM75是一个使用了内置带隙温度传感器和Σ-Δ模数转换技术的温度-数字转换器。LM75也是一个温度检测器,可提供一个过热检测输出。温度寄存器通常存放着一个11位的二进制数补码,用来实现0.125℃的精度。
2.2 温度测量软件设计
使用 fd=open("/dev/lm75",O_RDWR)打开 I2C设备,对I2C进行初始化,写入温度寄存器地址,使用 read (fd,tmp,2) 读取温度寄存器中的数值,tmp为两个数据的数组,高位数据读在前,低位数据读在后。数据有效位处理使用value=tmp[0]*256+tmp[1]合并为一个16位数据。value=value>>7忽略7位数据,得到有效数据。判断温度正负值。负值处理过程是数据为补码格式,先要把数据转换成原码,补码是原码取反再加上 1。 value=~value;val=((value& 0xff)+1)*0.5。 正数的处理过程 val=value*0.5;当有按键按下后,利用LM75芯片对温度进行采集,通过I2C总线读取数值并显示温度值。读取温度值对应的温度寄存器为00H。根据LM75的时序图,使用suba=0x00;write(fd,&suba,1)先将地址写入,再使用 read(fd,tmp,2)读取数值。
3 网络程序设计
Socket接口是 TCP/IP网络的 API,Socket接口定义了许多函数,可以开发TCP/IP网络的应用程序。网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过Socket实现的。常用的Socket类型有两种:流式 Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用。数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。
建立Webserver,对ARM7硬件平台上的LM75温度芯片进行温度采集,在客户机上通过网页浏览器进行访问,显示温度值。建立Webserver,只需要建立服务端程序,客户端用网页浏览器进行打开。在服务端程序中需要用到HTML语言,HTML语句是以字符串的形式编写的,当服务器将以字符串形式的HTML语言发送到客户端后,客户端的浏览器会根据字符串的内容来识别HTML语言。例如以下语句的作用是设置浏览器的标题栏内容以及浏览器背景的颜色。WebServer流程图如图3所示。
图3 WebServer流程图Fig.3 Flow chart of WebServer
调用Socket函数创建一个socket,调用Bind函数将其与本机地址以及一个本地端口号绑定,调用Listen在相应的socket上监听,当accpet接收到一个连接服务请求时,将生成一个新的socket。服务器显示该客户机的IP地址,并通过新的socket向客户端的服务器发送温度采集到的数值,最后关闭该socket。Socket创建套接字 sockfd=socket(AF_INET,SOCK_STREAM,0),Bind()与本地 IP 和端口与套接字相连,等待客户的连接,发送温度值。通过I2C总线采集LM75芯片的温度值,利用sprintf函数将要发送的内容转化成字符格式存入缓存区后,将数值发送到网页中。基本程序设计是读取温度值,进行格式转换,计算字符串的个数,发送温度数值。其中html关键字含义是<br>换行,<center>格式居中,<font color=#000000>设置文字颜色为黑色,<font size=7>设置字体大小,<u>加入下划线。关闭连接close(nsockfd);将程序下载到ARM7处理器目标板后,启动uClinux,运行程序。在宿主机上运行IE浏览器,输入目标机的IP地址。会出现界面显示实时温度值。
4 数据采集与存储
4.1 数据采集
LPC2210处理器提供了A/D转换功能,有10位逐次逼近式A/D转换器,有8个引脚复用为A/D输入脚,A/D参考电压为3.3 V,测量范围为0~3.3 V。AIN7~AIN0是模拟输入,A/D转换器单元可测量8个输入信号的电压。使用ioctl(fd,ADC_SET_CLKDIV,(Fpclk+Fadc-1)/Fadc-1)设置 A/D 转换速率。Fpclk为总线时钟频率,Fadc为ADC转换时钟频率,A/D转换时钟不能大于4.5 MHz。设置A/D转换精度使用 ioctl (fd,ADC_SET_BITS,N),N 为要设置的转换精度,取值范围为3~10位。A/D转换结果有10位,占 2 个字节。 read(fd,&ad_data,sizeof(ad_data))设置ad_data为16位的存储变量,运用sizeof()函数计算出变量占用的位数。计算出要读取的字节数。
4.2 CAT1025 E2PROM存储器
LPC2210具有支持400 kb/s高速模式的硬件I2C接口,使用一片I2C接口的E2PROM存储器CAT1025与ARM7处理器相连接,实现I2C的读/写操作。E2PROM存储器读写流程图如图4所示。
图4 存储器读写流程图Fig.4 Flow chart of memory read and write
使用 fd=open("/dev/cat1025",O_RDWR)打开设备文件,初始化I2C设备。系统时钟为11.0592 MHz,I2C速率为10 kHz。设置高电平时间采用ioctl(fd,I2C_SET_CLH, ((11059200/100000) +1)/2), 设置低电平时间采用 ioctl(fd,I2C_SET_CLL,(11059200/100000)/2),将内容写入E2PROM。第一个字节为器件的子地址,子地址为00H。将snd存储区内的12个字节发存储到E2PROM中。读出E2PROM中刚写入的数据。根据时序图,先写入器件的子地址,再读出相应个数的数据。
5 人机接口
ARM7硬件平台具有16个按键,使用I2C接口的键盘驱动芯片ZLG7290进行键盘管理。ZLG7290可以扫描管理多达64个按键,访问这些寄存器需要通过I2C总线接口来实现。ZLG7290的I2C总线器件写操作地址是70H,读操作地址是71H。访问内部寄存器要通过“子地址”来实现。当有按键按下后,ZLG7290会将相应的键值保存在键值寄存器中,如果没有键值按下,键值寄存器中的数值为0,键值寄存器的值在被读走后会自动变成0。芯片具有防抖动功能。ZLG7290采用3.3 V电源,复位引脚与系统复位信号nRST相连,当系统上电复位或手动复位时会同时复位ZLG7290。ZLG7290的键盘中断输出信号与LPC2210的中断引脚P0.30相连,当有按键按下时,有中断信号输出通知ZLG7290。使用fd=open("/dev/zlg7290",O_RDWR)打开设备文件,初始化I2C速率,设置 I2C 速率为 100kHz。 ioctl(fd,I2C_SET_CLH,((11059200/100000) +1)/2);ioctl(fd,I2C_SET_CLL,(11059200/100000)/2);读取 ZLG7290 键值寄存器,子地址为 01H,使用 suba=0x01;write(fd,&suba,1)发送将要读取的子地址。 使用 read(fd,&tmp,1)读取键值寄存器中的键值,放入tmp变量。判断键盘是否按下,如果没有键值按下,键值寄存器中的数值为0。判断键值寄存器中的数值,当为0时,继续读取键值寄存器,当读到的数值不为0为止。
6 MiniGUI体系结构
MiniGUI采用分层结构设计,可分为三层。在系统硬件之上的是图形抽象层GAL和输入抽象层IAL,这部分与系统的硬件驱动程序紧密相关。中间核心层是MiniGUI的最重要部分,一般采用客户机/服务器(Client/Server,C/S)模式运行,配合相应的功能模块。最上面的API层是GUI提供给用户的编程接口。一个C程序的入口点为main函数,而一个MiniGUI程序的入口点为MiniGUIMain,该函数原型为 int MiniGUIMain(int argc,const char*argv[])main函数已经在MiniGUI的函数库中定义了,该函数在进行一些MiniGUI的初始化工作之后调用MiniGUIMain函数。每个MiniGUI应用程序的入口点均为MiniGUIMain函数。参数argc和argv与C程序main函数的参数argc和argv的含义是一样的,分别为命令行参数个数和参数字符串数组指针。
6.1 创建主窗口和显示主窗口
使用 hMainWnd=CreateMainWindow(&window_info);创建主窗口。每个MiniGUI应用程序的初始界面一般都是一个主窗口,可以通过调用CreateMainWindow函数创建一个主窗口,参数是一个指向MAINWINCREATE结构的指针,本例中就是window_info,返回值为所创建主窗口的句柄。MAINWINCREATE结构描述一个主窗口的属性,在使用window_info创建主窗口之前,需要设置它的各项属性。 使用 ShowWindow(hMainWnd,SW_SHOWNORMAL);显示主窗口。创建完主窗口之后,还需要调用ShowWindow函数才能把所创建的窗口显示在屏幕上。ShowWindow的第一个参数为所要显示的窗口句柄,第二个参数指明显示窗口的方式即显示还是隐藏,SW_SHOWNORMAL说明要显示主窗口,并把它置为顶层窗口。
6.2 进入消息循环
在调用ShowWindow函数之后,主窗口就会显示在屏幕上。MiniGUI为每一个MiniGUI程序维护一个消息队列。在发生事件之后,MiniGUI将事件转换为一个消息,并将消息放入目标程序的消息队列之中。应用程序现在的任务就是执行如下的消息循环代码,不断地从消息队列中取出消息进行处理。
6.3 窗口过程函数
窗口过程函数是MiniGUI程序的主体部分,应用程序实际所做的工作大部分都发生在窗口过程函数中,因为MiniGUI程序的主要任务是接收和处理窗口收到的各种消息。窗口过程函数可以由程序员任意命名,CreateMainWindow函数根据MAINWINCREATE结构类型的参数中指定的窗口过程创建主窗口。
6.4 键盘消息MSG_CHAR
MiniGUI通过键盘设备驱动程序从键盘接收原始的输入事件或数据,将它转换为MiniGUI抽象的键盘事件和数据。相关的底层事件处理例程把这些键盘事件转换为上层的击键消息,放到相应的消息队列中。应用程序通过消息循环获取这些消息,交由窗口过程处理。
6.5 击键消息
当一个键被按下时,应用程序将收到一个MSG_KEYDOWN消息或MGS_SYSKEYDOWN消息。释放一个键会产生一个MSG_KEYUP消息或MGS_SYSKEYUP消息。按键和释放键消息通常是成对出现的。如果用户按住某个键不放手,一段时间以后就会启动键盘的自动重复特性,系统将会产生一系列的MSG_KEYDOWN或MSG_SYSKEYDOWN消息。在用户释放该键时,才会产生一条MSG_KEYUP或MSG_SYSKEYUP消息。
6.6 桌面主题设计
ARM7硬件平台上有一个4×4的矩阵键盘,MiniGUI通过键盘设备驱动已经将键盘中的每个按键都赋予了相应的键值。基于ARM硬件平台采用MiniGUI设计的智能终端屏幕上有六个图标,每个图标都有各自的功能,屏幕下方有相应图标功能的说明。对界面的操作主要以键盘为主,键盘可以移动桌面上图标中的光标对图标进行选择。利用光标的移动改变将要实现功能的选择,使用上下左右键可以切换图标的选择,按确定键就可以进入相应图标的功能。进入图标后,桌面显示界面将会被清除,取而代之的是相应功能界面。此时根据不同功能的需要,键盘也有相应的操作。按退出键返回桌面主题,可以继续对其它功能进行操作。应用程序由7个应用程序共同组成,分别是桌面显示、虚拟示波器、LED控制、蜂鸣器控制、电子相框、帮助文件等所组成。每一个程序都需要一个显示界面,MiniGUI中建立了一个主窗口,这几个应用程序都用这一个主窗口来显示。程序中需要设置一个非常关键的变量,对应用程序进行标志性的记录,利用这个标志变量选择输出窗口的显示内容。桌面上共有六个图标,这六个图标就代表六个分支语句,选择任意一个图标,就代表进入了这个分支,同时改变标志变量的值。当从这六个应用程序退出时,标志变量的值都将改变为桌面主题的标志,这样每次退出都能够返回桌面主题的显示。
7 虚拟示波器功能
在桌面主题中选择第一个图标,按确定键后即可进入虚拟示波器功能。主要实现对ARM7硬件电路板上的两路电压进行采集,在液晶屏上实时显示电压数值,并且画出相应的变化曲线如图5所示。使用退出键可以返回桌面主题。
当进入虚拟示波器功能后,程序对A/D进行初始化,调用SetTimer函数进行定时器的设置。A/D转换时钟频率为4.5 MHz,打开通道1设备,打开通道2设备,设置通道1和通道2的A/D转换速率,设置通道1和通道2的A/D转换精度。当定时时间到达后,系统会产生MSG_TIMER消息,在此消息中进行电压的采集以及数值输出和波形绘制。波形绘制主要用到了MoveTo和LineTo函数,前一个为线段的起点坐标,后一个是线段的终点坐标,当波形画满整个屏幕后,程序将调用刷新命令InitMainWindow函数,将波形清除,重新开始绘制。流程图如图6所示。由于电压采集的范围为0~3.3 V,以液晶屏纵坐标280的像素点为0 V,以纵坐标115的像素点为3.3 V,0 V与3.3 V的电压坐标相差165个像素,将电压值进行转换可以得到屏幕绘制的精度为20 mV。
图5 虚拟示波器显示采集电压值Fig.5 Virtual oscilloscopedisplay voltage acquisition value
图6 示波器定时器消息Fig.6 Oscilloscope timer message
程序设计实现定时消息产生,采集第一路电压,输出格式处理,获取上下文设备,输出当前值,得到纵坐标值,得到横坐标值,设置颜色,绘制起始坐标和终点坐标,保存坐标值,绘制下次坐标的起点。判断横坐标是否大于240,如果大于,刷新屏幕,从起始点重新绘制。释放上下文设备。当有按键产生后,按键消息首先判断是否为退出键,退出键响应后,程序会改变标志变量的值为桌面主题,关闭A/D采集设备文件,更新屏幕显示,使液晶屏重新输出桌面主题。如果不是退出键,则程序继续进行A/D采集。当有按键按下进行处理,释放A/D转换第一路,释放A/D转换第二路,释放定时器,建立并显示主窗口,界面切换到主菜单,波形起始坐标归位[3]。
8 结语
基于ARM7利用I2C总线对E2PROM存储器进行读写操作。利用I2C总线对LM75温度传感器进行温度采集。利用I2C总线对ZLG7290键盘管理芯片实现按键处理。利用A/D对多路电压进行采集。利用MiniGUI编制综合应用程序,效果类似于个人数字助理,能够实现多种应用程序的管理。如利用通用I/O接口实现LED小灯与蜂鸣器的控制,利用A/D对多路电压进行采集并画出相应的曲线图,实现虚拟示波器功能。利用液晶屏显示图片实现数码相框功能。编制了网络服务器程序,通过网页浏览器的访问可以显示实时温度值。基于ARM7和uClinux较好地实现了嵌入式终端系统的管理。
[1] 周立功.ARM嵌入式系统基础教程[M].北京:北京航空航天大学出版社,2005:245-258.
[2] 刘玥.ARM嵌入式系统GUI开发研究[J].微计算机信息,2007,23(5-2):153-154,160.
[3] 张杰.基于ARM-uClinux的嵌入式产品平台构建[J].自动化与仪器仪表,2007,22(3):68-70. ■