許多長時間無人值守的監控系統中,數據到來的時刻是不可預知的,數據及其出現時的時間信息要一并記錄下來,以便后期的處理和查閱。在智能交通系統中,以交叉路口的闖紅燈自動抓拍系統為例,系統抓拍的闖紅燈車輛的圖片中就要包含抓拍的時間信息,以作為日后交警進行違規處罰的有力證據。以往的自動抓拍系統都是用工控機搭建的,在其工控主板上有時鐘芯片和板載電池,即使斷電也不會丟失實時時間信息。但是,作為硬件資源豐富的通用型工業控制計算機,在具體的控制系統中,往往會有許多硬件資源被閑置,使得成本偏高。隨著嵌入式技術的發展和逐步成熟,為了節約成本和提高系統的可靠性,大有用嵌入式取代通用型工控機的趨勢。這就提出了一個問題:在嵌入式系統中,實時時間從何獲得。 本文將給出兩種在嵌入式系統中獲取實時時間的設計方法:使用時鐘芯片方法和使用GPS接收機方法。 1 使用時鐘芯片獲取實時時間 在這種方案中,實時時鐘芯片以美國DALLAS公司推出的DSl302芯片為例,嵌入式平臺選用ATMEL的基于ARM920T內核的AT9lRM9200微處理器配以Linux一2.6.13嵌入式操作系統。 1.1 時鐘芯片概述 DIP封裝的DSl302共有8個引腳,Vccl和Vcc2分別是主電源引腳和備用電源引腳,當Vcc2>Vccl+0.2V時,由備用電源向時鐘芯片供電。X1、X2是晶振連接引腳。GND接地。剩下的三個引腳用于與微控制器通信,它們是RST、SCLK、I/O。 DSl302內部有31字節的靜態RAM可用于記錄重要數據、共有12個寄存器其中有7個用于存儲時間和日期。更為詳細的資料,可以參考DSl302的芯片手冊。下面就DSl302讀寫操作中應注意的幾點列舉如下: 1、所有的數據傳送均是以發送8位的指令字節開始。指令字節的最高有效位(位7)必須是邏輯l,如果它為O,則不能把數據寫入到DSl302中。 2、RST輸入引腳的兩種功能:(1)接通控制邏輯,允許地址/命令序列送入移位寄存器:(2)提供了終止單字節或多字節數據傳送的手段。當RST為高電平時,所有的數據傳送使能,允許對DSl302進行操作。如果在傳送過程中RST被置為低電平,則會立即終止此次數據傳送,并且I/0引腳變為高組態。 3、當把RST驅動至邏輯l時,SCLK必須為邏輯0。 1.2 硬件電路設計 DSl302采用雙電源方式,系統正常工作時由板載電源統一供電,當系統斷電或復位時由板載電池供電,以保證時鐘芯片始終處于運行狀態。 微控制器AT9lRM9200的PBO、PBl0、PBll三個引腳用于與時鐘芯片進行同步串行通信,因為這三個引腳在AT9lRM9200內部都是多功能復用的,所以在DSl302設備驅動程序的初始化代碼中首先要把它們配置成通用I/O口。關于晶體振蕩器,DS1302的芯片資料指出:32.768KHz的晶振可以直接連接到X1、X2引腳,同時外接晶振電路要有6PF的負載電容與內部震蕩器配合運行。所以,在電路設計時X1、X2兩引腳分別連接一個15pF的電容至地。硬件連接,如圖1所示: 1.3 Linux 下OSl302驅動程序設計 Linux系統中有三種類型的設備:字符設備、塊設備和網絡設備。字符設備是指發送和接收數據以字符的形式進行,無需緩沖直接存取,在對字符設備發出讀寫請求后,實際的硬件I/0隨即發生;而塊設備則是對數據緩沖區進行讀寫并可以隨機訪問,操作是以塊為單位。而網絡設備與字符設備、塊設備有很大的不同,用于對網絡設備的控制和管理。DSl302顯然屬于字符設備。 2.6版本的Linux內核和2.4版本存在很大的不同,在模塊的開發和設計上也是如此。在這里使用的內核版本是Linux一2.6.13。首先,驅動程序作為一個模塊可以動態加載進內核也可以動態的從內核中卸載掉,在加載和卸載的過程中實際伴隨的是驅動程序向內核的注冊與注銷。在驅動程序的代碼中會有兩個函數分別在模塊加載和卸載過程中調用DSl302_init()、DSl302_exit(),在其中再調用register_chrdev()、unregister_chrdev()用以向內核注冊和注銷一個設備驅動程序。在2.6內核版本中,用如下方法聲明這兩個函數給內核: Module_init(DS1302_init): Module_exit(DSl302_exit): 在DSl302_init()函數中除調用字符設備的注冊函數外,還有一個重要任務,就是配置需要用到的三條I/0口線:PBO、PBl0、PBll。配置過程包括:B端口控制器時鐘使能、通用I/O口使能、輸出使能、上拉電阻使能、三個口線上的同步數據輸出使能,另外通過置PIOB_CODR寄存器使三個引腳輸出低電平。代碼如下: 其中va_sys是一個結構體,包含了AT9lRM9200處理器內的全部寄存器,通過一條語句:AT91PS_SYS va_sys=(AT91PS SYS)AT91C_VA_BASE_SYS,把所有寄存器的最低地址賦給va_sys,這樣結構體中的寄存器名稱就和實際的地址對應起來了。注意:這里用到的地址都是經過映射過的虛擬地址,在實際運行中會通過處理器內部的MMU單元轉換為實際的物理地址發往地址總線。上述代碼中的AT91C_PI0_PBO等等是一些常數的宏定義用于寄存器賦值,比如:#define AT9lC_PIO_PBO(1<<0),它們定義在AT91RM9200.h頭文件中。 在驅動程序中,file_operations是一個重要的結構體,通過它把針對設備的具體操作注冊給內核的統一接口。結構體中全是函數指針,DSl302驅動程序中用到的函數有:open、release、ioctl,用于設備的打開與釋放、設備的讀寫以及設備的控制。對DSl302的讀寫都是在dsl302_ioctl()中調用相應的讀寫函數實現的。 下面具體分析一下驅動程序中向DSl302發送單個字 代碼中用到的at91_set_gpi0_value()函數定義在內核的Gpio.c文件中,最終是對10控制器的PIO_SODR(置位輸出數據寄存器)或PIO_CODR(清零輸出數據寄存器)賦值以使相應引腳輸出需要的電平。 經過測試,短時間內誤差不明顯,但時鐘芯片存在積累誤差并且易受環境影響,連續幾天運行下來,誤差有數秒之多。所以,嵌入式系統需要通過某種方法定期使用標準時間向時鐘芯片對時,以消除誤差。下面要介紹的GPS接收機方案就可以做到這點。 2 從GPS接收機獲取實時時間 GPS是美國開發研制的最初主要作為軍用的一種全球定位系統,有三個部分組成:空間部分、地面監控部分和用戶部分。一般來說,在地面上的GPS接收機能接收5~12個衛星信號,而為了獲得地面上的定位坐標,至少需要4顆衛星的信號,三個用來確定GPS接收機的緯度、經度和海拔高度,第四個則提供同步校正時間。 GPS接收機只要處于工作狀態就會源源不斷地把計算出的GPS導航定位信息通過串口傳送到計算機中。GPS接收機送出的數據都是格式化的,NMEA一0183協議是GPS接收機應當遵循的標準協議,大多數常見的GPS接收機、GPS數據處理軟件、導航軟件都遵守或者至少兼容這個協議。下面介紹下如何從符合NMEA—0183協議的接收機接收數據中提取時間信息。 接收機通過串口發送到計算機的數據主要由幀頭、幀尾和幀內數據組成,根據數據幀的不同,幀頭也不相同,主要有“$GPGGA”、“$GPGSA”、“$GPGSV”以及“$GPRMC”等。這些幀頭標識了后續幀內數據的組成結構,各幀均以回車符和換行符作為幀尾標識一幀的結束。對于通常的情況,我們所關心的定位數據如經緯度、速度、時間等均可以從“$GPRMC”幀中獲取得到,該幀的結構及各字段釋義如下: $GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>*hh<CR><LF> <1>當前位置的格林尼治時間,格式為hhmmss <2>狀態,A為有效,V為接收警告,即當前天線視野上方的衛星個數少于3顆。 <3>緯度,格式為ddmm.mmmm <4>標明南北半球,N為北半球、S為南半球 <5>徑度,格式為dddmm.mmmm <6>標明東西半球,E為東半球、W為西半球 <7>地面上的速度,范圍為0.ON999.9 <8>方位角,范圍為000.O到359.9度 <9>日期,格式為ddmmyy <lO>地磁變化,從000.0到180.O度 <ll>地磁變化方向,為E或W 在Linux操作系統中,從$GPRMC數據幀中提取時間信息的代碼如下: 程序首先打開串口,然后對串口參數進行配置,隨后進入無限循環主體。這段代碼是作為主進程的一個線程實現串口數據的接收,當串口接收緩沖區中無數據時,read函數阻塞。程序中只提取了時間信息,若需導航數據可以類似方法提取。 3 結束語 本文分別介紹了兩種嵌入式系統中獲取實時時間的方法:時鐘芯片方法和GPS接收機方法。時鐘芯片方法的優點是硬件連接簡單、成本低;缺點是存在積累誤差、易受環境影響、可靠性差。GPS接收機的優點:由于GPS衛星使用的是可以精確到十億分之一秒的原子鐘,所以不存在時間誤差問題。同時也應該看到,目前GPS核心技術在國外,國內GPS市場主要還是做代理或是在購買國外GPS模塊的基礎上做產品開發,這就使得開發成本偏高。GPS方法中還有一個問題就是在某些情況下接收不到GPS信號,如在高樓林立的環境下或是在地下室之類的地方。此時就應該讓GPS接收機方法與處理器內部的實時時鐘(RTC)配合工作,這樣在短時接收不到GPS信號的情況,仍可以從RTC讀取時間。 |