艾 紅
(北京信息科技大學 自動化學院,北京 100192)
嵌入式系統在生活的各個方面都有其身影,比如人們平時廣泛使用的手機、PDA、MP3、機頂盒都屬于嵌入式系統設備。uClinux是Linux2.0的一個分支,被應用于微控制領域。uClinux最大的特征是沒有MMU即內存管理單元模塊,很適合那些沒有MMU的處理器,例如ARM7-TDMI等。這種沒有MMU的處理器在嵌入式領域中應用得相當普遍。同標準的Linux相比,由于uClinux上運行的絕大多數用戶程序并不需要多任務。uClinux有完整的TCP/IP協議,同時對其他網絡協議都提供支持,這些網絡協議都在uClinux上得到了很好實現?;贏RM7和uClinux操作系統構建嵌入式系統硬件平臺實現網頁顯示實時溫度、數據采集、存儲和人機交互功能。計算機圖形界面是計算機與使用者之間的對話接口。隨著嵌入式系統性能的不斷提高,圖形化的接口己經成為嵌入式設備應用領域中的一個熱點。圖形用戶界面使人們能夠更加方便地與機器進行互動操作,其中以MiniGUI為代表的嵌入式GUI較為突出,可以設計人機交互界面[1-2]。
采用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。
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℃的精度。
使用 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)讀取數值。
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地址。會出現界面顯示實時溫度值。
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()函數計算出變量占用的位數。計算出要讀取的字節數。
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中剛寫入的數據。根據時序圖,先寫入器件的子地址,再讀出相應個數的數據。

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為止。
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的含義是一樣的,分別為命令行參數個數和參數字符串數組指針。
使用 hMainWnd=CreateMainWindow(&window_info);創建主窗口。每個MiniGUI應用程序的初始界面一般都是一個主窗口,可以通過調用CreateMainWindow函數創建一個主窗口,參數是一個指向MAINWINCREATE結構的指針,本例中就是window_info,返回值為所創建主窗口的句柄。MAINWINCREATE結構描述一個主窗口的屬性,在使用window_info創建主窗口之前,需要設置它的各項屬性。 使用 ShowWindow(hMainWnd,SW_SHOWNORMAL);顯示主窗口。創建完主窗口之后,還需要調用ShowWindow函數才能把所創建的窗口顯示在屏幕上。ShowWindow的第一個參數為所要顯示的窗口句柄,第二個參數指明顯示窗口的方式即顯示還是隱藏,SW_SHOWNORMAL說明要顯示主窗口,并把它置為頂層窗口。
在調用ShowWindow函數之后,主窗口就會顯示在屏幕上。MiniGUI為每一個MiniGUI程序維護一個消息隊列。在發生事件之后,MiniGUI將事件轉換為一個消息,并將消息放入目標程序的消息隊列之中。應用程序現在的任務就是執行如下的消息循環代碼,不斷地從消息隊列中取出消息進行處理。
窗口過程函數是MiniGUI程序的主體部分,應用程序實際所做的工作大部分都發生在窗口過程函數中,因為MiniGUI程序的主要任務是接收和處理窗口收到的各種消息。窗口過程函數可以由程序員任意命名,CreateMainWindow函數根據MAINWINCREATE結構類型的參數中指定的窗口過程創建主窗口。
MiniGUI通過鍵盤設備驅動程序從鍵盤接收原始的輸入事件或數據,將它轉換為MiniGUI抽象的鍵盤事件和數據。相關的底層事件處理例程把這些鍵盤事件轉換為上層的擊鍵消息,放到相應的消息隊列中。應用程序通過消息循環獲取這些消息,交由窗口過程處理。
當一個鍵被按下時,應用程序將收到一個MSG_KEYDOWN消息或MGS_SYSKEYDOWN消息。釋放一個鍵會產生一個MSG_KEYUP消息或MGS_SYSKEYUP消息。按鍵和釋放鍵消息通常是成對出現的。如果用戶按住某個鍵不放手,一段時間以后就會啟動鍵盤的自動重復特性,系統將會產生一系列的MSG_KEYDOWN或MSG_SYSKEYDOWN消息。在用戶釋放該鍵時,才會產生一條MSG_KEYUP或MSG_SYSKEYUP消息。
ARM7硬件平臺上有一個4×4的矩陣鍵盤,MiniGUI通過鍵盤設備驅動已經將鍵盤中的每個按鍵都賦予了相應的鍵值。基于ARM硬件平臺采用MiniGUI設計的智能終端屏幕上有六個圖標,每個圖標都有各自的功能,屏幕下方有相應圖標功能的說明。對界面的操作主要以鍵盤為主,鍵盤可以移動桌面上圖標中的光標對圖標進行選擇。利用光標的移動改變將要實現功能的選擇,使用上下左右鍵可以切換圖標的選擇,按確定鍵就可以進入相應圖標的功能。進入圖標后,桌面顯示界面將會被清除,取而代之的是相應功能界面。此時根據不同功能的需要,鍵盤也有相應的操作。按退出鍵返回桌面主題,可以繼續對其它功能進行操作。應用程序由7個應用程序共同組成,分別是桌面顯示、虛擬示波器、LED控制、蜂鳴器控制、電子相框、幫助文件等所組成。每一個程序都需要一個顯示界面,MiniGUI中建立了一個主窗口,這幾個應用程序都用這一個主窗口來顯示。程序中需要設置一個非常關鍵的變量,對應用程序進行標志性的記錄,利用這個標志變量選擇輸出窗口的顯示內容。桌面上共有六個圖標,這六個圖標就代表六個分支語句,選擇任意一個圖標,就代表進入了這個分支,同時改變標志變量的值。當從這六個應用程序退出時,標志變量的值都將改變為桌面主題的標志,這樣每次退出都能夠返回桌面主題的顯示。
在桌面主題中選擇第一個圖標,按確定鍵后即可進入虛擬示波器功能。主要實現對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]。
基于ARM7利用I2C總線對E2PROM存儲器進行讀寫操作。利用I2C總線對LM75溫度傳感器進行溫度采集。利用I2C總線對ZLG7290鍵盤管理芯片實現按鍵處理。利用A/D對多路電壓進行采集。利用MiniGUI編制綜合應用程序,效果類似于個人數字助理,能夠實現多種應用程序的管理。如利用通用I/O接口實現LED小燈與蜂鳴器的控制,利用A/D對多路電壓進行采集并畫出相應的曲線圖,實現虛擬示波器功能。利用液晶屏顯示圖片實現數碼相框功能。編制了網絡服務器程序,通過網頁瀏覽器的訪問可以顯示實時溫度值?;贏RM7和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. ■