實際應用中,時間管理往往是必不可少的。例如:定時完成某件事情、周期性地觸發某一動作、測量評估程序運行時間等。AWorks提供了一系列時間相關的服務,包括標準時間和定時器等,用戶可以據此實現靈活的時間相關應用。
本文為《面向AWorks框架和接口的編程(上)》第三部分軟件篇——第8章時間管理——第1~5小節:時間的表示形式、RTC通用接口、系統時間、系統節拍和軟件定時器。8.1 時間的表示形式
在AWorks中,時間有3種表示形式:細分時間、日歷時間和精確日歷時間。
8.1.1 細分時間
細分時間包含年、月、日、時、分、秒等信息。在AWorks中,細分時間使用aw_tm_t類型表示,該類型的具體定義詳見程序清單8.1。
程序清單8.1 細分時間類型定義(aw_time.h)
其中,tm_sec表示秒,有效值為 0 ~ 59;tm_min表示分,有效值為0 ~ 59;tm_hour表示小時,有效值為 0 ~ 23;tm_mday表示日期,有效值為1 ~ 31;tm_mon表示月份,有效值為0 ~ 11,分別對應1 ~ 12月,即實際月份為該值加上1;tm_year表示1900年至今的年數,實際年為該值加上1900; tm_wday表示星期,0 ~ 6分別對應星期日 ~ 星期六;tm_yday表示該年1月1日至今的天數(0 ~ 365),0對應1月1日;tm_isdst表示是否使用夏令時,若tm_isdst為正,則夏令時有效,系統會在夏季將時間調快一小時,若tm_isdst為0或負數,表示不使用夏令時。現在一般不使用夏令時,tm_isdst設置為-1即可。
夏令時(Daylight Saving Time:DST)是一種為節約能源而人為規定地方時間的制度,在這一制度實行期間所采用的統一時間稱為“夏令時間”。一般在天亮早的夏季人為將時間提前一小時,可以使人早起早睡,從而節約照明用電。各個采納夏時制的國家具體規定不同。目前全世界有近110個國家每年要實行夏令時。我國在1986年至1991年實行了六年的夏令時,每年從4月中旬的第一個星期日2時整(北京時間)到9月中旬第一個星期日的凌晨2時整(北京夏令時)。在夏令時實施期間將時間調快一小時。1992年4月5日后不再實行。
例如,當前時間是2016年8月26日09:32:30,則可以定義如下細分時間:
一般地,星期(tm_wday)和一年中的天數(tm_yday)兩個成員的值無需用戶手動設置,這些值是在獲取細分時間時,反饋給用戶的信息。
8.1.2 日歷時間
日歷時間表示從1970年1月1日00:00:00開始至當前時刻經歷的秒數。在AWorks中,日歷時間使用aw_time_t類型表示,該類型定義如下(aw_time.h):
例如,當前時間是2016年8月26日09:32:30,至1970年1月1日00:00:00以來的秒數為1472203950。則可以定義如下日歷時間:
實際中,用戶往往并不需要直接計算秒數,而是通過AWorks提供的相關接口,將細分時間轉換為日歷時間,以得到某一細分時間對應的日歷時間。
8.1.3 精確日歷時間
日歷時間精度為秒,精確日歷時間的精度可以達到納秒,精確日歷時間在日歷時間的基礎上,增加了一個納秒計數器。在AWorks中,精確日歷時間使用aw_timespec_t類型表示,該類型定義如下(aw_time.h):
其中,tv_sec是秒值;tv_nsec是納秒計數值。納秒計數值從0開始計數,當納秒計數值達到1000000000時,秒值加1,同時,納秒計數值復位為0,重新開始計數。
8.1.4 細分時間與日歷時間的相互轉換
為了便于用戶使用,AWorks提供了兩個接口函數,用于細分時間和日歷時間的相互轉換。相關函數的原型詳見表8.1。
表8.1 時間轉換接口函數(aw_time.h)
1. 細分時間轉換為日歷時間
該函數用于將細分時間轉換為日歷時間,其函數原型為:
其中,p_tm作為輸入參數,指向待轉換的細分時間;p_time為輸出參數,用以輸出轉換的結果(日歷時間)。函數返回值為標準的錯誤號,返回AW_OK時表示轉換成功,其它值表示轉換失敗。
例如,需要獲取2016年8月26日09:32:30對應的日歷時間,則范例程序詳見程序清單8.2。
程序清單8.2 細分時間轉換為日歷時間范例程序
運行程序,可以得到轉換的結果為:1472203950。
2. 日歷時間轉換為細分時間
該函數用于將日歷時間轉換為細分時間,其函數原型為:
其中,p_time作為輸入參數,指向待轉換的日歷時間;p_tm為輸出參數,用以輸出轉換的結果(細分時間)。函數返回值為標準的錯誤號,返回AW_OK時表示轉換成功,其它值表示轉換失敗。
例如,需要將日歷時間1472203950轉換為細分時間,則范例程序詳見程序清單8.3。
程序清單8.3 日歷時間轉換為細分時間范例程序
運行程序,可以得到轉換的結果為:2016-08-26 09:32:30。
8.2 RTC通用接口
RTC(Real-Time Clock)設備是能夠提供基本時鐘服務的設備。一個系統中若存在RTC設備,則可以使用RTC通用接口從RTC設備中獲取到年、月、日、時、分、秒等基本的時間信息,一般地,為了修正時間值,往往還可以設置RTC設備當前的時間值。
通常情況下,在硬件設計上,都會為RTC設備分配一個獨立的后備電源(如電池),當系統主電源掉電后,RTC設備仍然能夠繼續正確運行,使得時間信息一直保持有效。
RTC通用接口包含獲取時間和設置時間的接口,其函數原型詳見表8.2。
表8.2 RTC通用接口函數(aw_rtc.h)
1. 獲取時間
該函數用于獲取RTC器件當前的時間值,其函數原型為:
其中,rtc_id表示RTC設備的編號,系統為每個RTC設備都分配了一個唯一ID,通常都是從0開始順序為各個RTC設備編號。例如,i.MX28x片內具有RTC外設,其可以作為一個RTC設備使用,若還使用I2C總線外接了PCF85063器件,則系統中將新增一個RTC設備,此時,系統中共計將有2個RTC設備,它們的編號分別為0、1。p_tm為指向細分時間的指針,其為輸出參數,用以返回獲取到的時間值,返回值為標準的錯誤號,返回AW_OK時表示獲取成功,否則表示獲取失敗,失敗的原因可能是該rtc_id對應的設備不存在。
例如,獲取ID為0的RTC設備時間,其范例程序詳見程序清單8.4。
程序清單8.4 獲取RTC設備時間的范例程序
2. 設置時間
該函數用于設置RTC器件當前的時間值,其函數原型為:
其中,rtc_id表示RTC設備的編號,p_tm為指向細分時間的指針,返回值為標準的錯誤號,返回AW_OK時表示設置成功,否則表示設置失敗。
例如,修改ID為0的RTC設備時間,設置其時間為2016-08-26 09:32:30的范例程序詳見程序清單8.5。
程序清單8.5 設置RTC設備時間的范例程序
8.3系統時間
在使用RTC通用接口獲取或設置時間時,必須通過rtc_id指定一個RTC器件,略顯繁瑣,并且在絕大多數應用中,在獲取時間值時,可能并不關心時間是從哪個RTC設備中獲取到的。為了使應用程序在使用時間服務時更加便捷,AWorks提供了一個統一的系統時間,用戶可以實時獲取系統時間,必要時,也可以修改系統時間。
8.3.1 獲取系統時間
根據系統時間表示形式的不同,可以有3種獲取系統時間的方式:細分時間、日歷時間和精確日歷時間。相關函數的原型詳見表8.3。
表8.3 獲取系統時間接口函數(aw_time.h)
1.獲取細分時間
該函數以細分時間的形式獲取當前的系統時間,其函數原型為:
其中,p_tv為指向細分時間的指針,用于獲取細分時間。函數返回值為標準的錯誤號,返回AW_OK時表示獲取成功,其它值表示獲取失敗。范例程序詳見程序清單8.6。
程序清單8.6 獲取細分時間范例程序
程序中,每隔1s打印一次當前的時間值。初始時,若未對時間作任何設置,則系統時間默認為:1970-01-01 00:00:00。
2. 獲取日歷時間
該函數以日歷時間的形式獲取當前的系統時間,其函數原型為:
其中,p_time為指向日歷時間的指針,用于獲取日歷時間,不需要通過參數獲取日歷時間時,該值可以為NULL。返回值同樣為日歷時間,特別地,若返回值為-1,表明獲取失敗。由此可見,既可以通過參數獲得日歷時間,也可以通過返回值獲得日歷時間。
通過參數獲得日歷時間的范例程序詳見程序清單8.7。
程序清單8.7 通過參數獲得日歷時間范例程序
程序中,每隔1s打印一次當前的日歷時間值。初始時,若未對時間作任何設置,則系統的日歷時間默認為0(即起始時間為:1970-01-01 00:00:00)。
也可以直接通過返回值獲取日歷時間,范例程序詳見程序清單8.8。
程序清單8.8 通過返回值獲取日歷時間范例程序
3. 獲取精確日歷時間
該函數以精確日歷時間的形式獲取當前的系統時間,其函數原型為:
其中,p_tv為指向精確日歷時間的指針,用于獲取精確日歷時間。函數返回值為標準的錯誤號,返回AW_OK時表示獲取成功,其它值表示獲取失敗。范例程序詳見程序清單8.9。
程序清單8.9 獲取精確日歷時間范例程序
實際中,由于硬件性能的限制,往往并不能每納秒更新一次納秒計數值。不同平臺實際納秒計數值更新的快慢是不同的。例如,可能每隔2ms才更新一次納秒計數值,使納秒計數值每次增加2000000。
基于精確日歷時間,可以完成一些需要精度高于秒的應用,例如,在用于運動員計時的秒表中,精度往往需要達到0.1 ~ 0.01秒。
8.3.2 設置系統時間
系統時間不準確時,或需要對系統時間進行初始設置時,可以通過接口函數重新設置系統時間的值,以便系統時間準確運行。根據不同的時間表示形式,有2種設置系統時間方式:使用細分時間,使用精確日歷時間。相關函數的原型詳見表8.4。
表8.4 設置系統時間接口函數(aw_time.h)
1. 使用細分時間設置系統時間
該函數用于使用細分時間的形式設置系統時間,其函數原型為:
其中,p_tm為指向細分時間(待設置的時間值)的指針。函數返回值為標準的錯誤號,返回AW_OK時表示設置成功,其它值表示設置失敗。
當使用細分時間設置時間值時,細分時間的成員tm_wday, tm_yday無需用戶設置,將在調用設置函數后自動更新。設置當前時間為2016-08-26 09:32:30的范例程序詳見程序清單8.10。
程序清單8.10 使用細分時間設置系統時間范例程序
程序中,將時間設置為2016年8月26日09:32:30。并在while(1)主循環中,每隔1s打印一次當前的系統時間。
2. 使用精確日歷時間設置系統時間
該函數用于使用精確日歷時間的形式設置系統時間,其函數原型為:
其中,p_tv為指向精確日歷時間(待設置的時間值)的指針。函數返回值為標準的錯誤號,返回AW_OK時表示設置成功,其它值表示設置失敗。范例程序詳見程序清單8.11。
程序清單8.11 使用精確日歷時間設置系統時間范例程序
程序中,將精確日歷時間的秒值設置為了1472203950,該值是從1970年1月1日0時0分0秒至2016年8月26日09時32分30秒的秒數。即將時間設置為2016年8月26日09時32分30秒。在while(1)主循環中,每隔1s按照細分時間的格式打印一次當前的系統時間,用以驗證設置的結果。
通常情況下,不會這樣設置時間值,均是采用細分時間的方式設置時間值,因為細分時間更加容易閱讀和理解。但是,在一些應用場合,使用日歷時間將是一種更優的選擇,例如,需要通過遠程傳輸時間值來更新本地的時間值,顯然,日歷時間的長度要遠遠小于細分時間的長度,這種情況下,通信過程中,傳輸日歷時間比傳輸細分時間更節省通信數據量,可以節省一定的帶寬。
8.4 系統節拍
系統節拍相當于系統的“心臟”,系統節拍的頻率即為“心臟”跳動的頻率,每次“跳動”,系統節拍計數器加1,并處理系統相關的事務。例如,在系統中,可以存在多個軟件定時器(下節將詳細介紹),則在每個系統節拍產生時,系統將自動檢查所有的軟件定時器,將它們的定時節拍數減1,當減至0時,表明定時器的定時時間到。在AWorks中,很多事物的處理都是基于系統節拍的,因而往往將系統節拍看作系統的“心臟”。
系統節拍相關的函數原型詳見表8.5
表8.5 系統節拍接口(aw_system.h)
1. 獲取系統節拍頻率
一個系統節拍對應的實際時間與系統節拍的頻率相關。系統節拍頻率越高,系統相關的事務處理越頻繁,實時性越好,但單位時間內,系統本身占用CPU的時間越長,對應的,用戶能夠使用CPU的時間也就越短。反之,系統節拍頻率越低,系統相關的事物處理越緩慢,實時性越差,但單位時間內,系統本身占用CPU的時間越短,對應的,用戶能夠使用CPU的時間也就越長。因此,系統節拍的頻率不能太高,也不能太低,需要設置為一個合理的值,通常在幾Hz到幾KHz 之間。
系統實際使用的節拍頻率可以通過該函數獲得,其函數原型為:
函數返回值即為系統節拍頻率,例如,返回值為1000,表示節拍頻率為1KHz,則每個節拍對應的時間為1ms。獲取并打印當前系統節拍頻率的范例程序詳見程序清單8.12。
程序清單8.12 獲取系統節拍頻率的范例程序
2. 獲取系統當前的節拍計數值
系統中存在一個系統節拍計數器,初始值為0,系統啟動后,其值會在每個系統節拍加1。可以通過該函數在任意時刻獲取當前系統節拍的計數值,其函數原型為:
函數返回值即為當前系統節拍計數器的值。aw_tick_t為一個無符號整數類型。其位數與具體平臺相關,在32位系統中,其往往定義為32位。
系統節拍計數值往往可以用來計算一段程序運行的時間,如在程序運行前,使用該函數獲取一個系統節拍計數值,在程序運行結束后,再使用該函數獲取一個系統節拍計數值。它們的差值即為程序運行所消耗的系統節拍個數,再由系統節拍頻率可以知道每個節拍對應的時間,從而得到程序運行所耗費的時間。范例程序詳見程序清單8.13。
程序清單8.13 獲取系統節拍計數值的范例程序
程序中,作為演示,測量的是一個執行1000000次空語句的for循環程序段的時間。t1與t0的差值即為for循環程序段耗費的系統節拍數,同時,系統節拍頻率的倒數為每個節拍對應的時間(秒),程序中,將時間值擴大了1000倍,即將時間值的單位轉換為了毫秒。
程序中,節拍差值和對應的時間都通過手動計算,實際中,為了方便用戶使用,AWorks提供了相關操作對應的接口函數。
3. 計算兩個時刻的節拍計數值的差值
該函數用于計算兩個時刻的節拍計數值的差值,以計算某一程序段所耗費的時間節拍數,其函數原型為:
t0為某一程序段開始時刻的系統節拍計數值,t1為對應程序段結束時的系統節拍計數值。如優化程序清單8.13中計算節拍差值的語句,改由通過接口實現,范例程序詳見程序清單8.14。
程序清單8.14 計算節拍差值的范例程序
4. 系統節拍個數轉換為時間
在上面的例子中,將系統節拍個數轉換為時間較為繁瑣,需要獲取系統節拍的頻率,然后經過相關的換算。為了便于用戶使用,提供了直接將系統節拍值轉換為時間(單位:毫秒)的接口,其函數原型為:
其中,ticks為系統節拍個數,返回值為轉換的時間結果(單位:毫秒)。如優化程序清單8.14中計算時間的語句,改由通過接口實現,范例程序詳見程序清單8.15。
程序清單8.15 計算節拍值對應時間的范例程序
5. 時間轉換為系統節拍個數
與將系統節拍個數轉換為時間對應,AWorks提供了用于將時間(單位:毫秒)轉換為系統節拍個數的接口,其函數原型為:
其中,ms是待轉換的時間(單位:毫秒),返回值為轉換的結果(系統節拍個數),即ms參數指定時間所對應的節拍數。例如,要獲取500ms時間對應的節拍個數,范例程序詳見程序清單8.16。
程序清單8.16 計算時間對應節拍個數的范例程序
8.5 軟件定時器
當需要定時完成某件事情時,可以使用軟件定時器,其可以提供毫秒級別的定時。當定時時間到時,自動通知用戶,以便用戶處理相關的事務。軟件定時器相關的接口函數原型詳見表8.6。
表8.6 軟件定時器相關接口(aw_timer.h)
1. 定義軟件定時器實例
每個軟件定時器對應了一個事務處理,當定時時間到時,需要通知用戶,在AWorks中,“通知”是通過回調機制實現的。即初始時,用戶將一個函數與定時器綁定,后續當該定時器定時時間到時,將自動回調用戶綁定的函數,即可達到將“定時時間到”的這一事件通知到用戶。
在使用軟件定時器前,必須定義一個軟件定時器實例,軟件定時器的類型為aw_timer_t,其在aw_timer.h文件中定義,具體類型的定義用戶無需關心,僅需使用該類型定義軟件定時器實例即可,即:
其地址即可作為軟件定時器相關接口中p_timer參數的實參傳遞。
此外,系統中可以有多個軟件定時器,每個定時器可以有不同的定時時間,對應不同的事務處理,例如:
2. 初始化軟件定時器
該函數用于將指定的函數與軟件定時器綁定(注冊),保存在定時器實例中,當定時時間到,則通過函數指針p_func調用指定的函數,即注冊回調函數機制。初始化函數的原型為:
其中,p_timer為指向使用aw_timer_t類型定義的軟件定時器實例的指針,p_func指向本次注冊的回調函數,當定時時間到時,系統將自動調用p_func指向的函數(注冊回調函數),回調函數的類型為aw_pfuncvoid_t,該類型是AWorks中定義的函數指針類型,其具體定義(aw_types.h)如下:
由此可見,p_func指向的函數類型是無返回值,具有一個void*型參數的函數。
初始化函數的p_arg形參即為用戶自定義的參數,在定時時間到調用回調函數時,會將此處設置的p_arg作為參數傳遞給回調函數,如果不使用此參數,則設置為NULL。
初始化函數的使用范例詳見程序清單8.17。
程序清單8.17 初始化軟件定時器范例程序
3. 啟動軟件定時器
完成定時器的初始化后,即可設置定時時間(單位:ms)并啟動定時器,定時器開始工作,定時器定時的單位為系統節拍,啟動定時器后,在每個系統節拍將軟件定時器的節拍值減1,當減到0時,表明定時時間到,則自動調用初始化時注冊的回調函數。啟動軟件定時器的函數原型為:
其中,p_timer指向軟件定時器實例,ticks為定時的節拍數。如啟動定時器,并定時500ms,則范例程序詳見程序清單8.18
程序清單8.18 啟動軟件定時器范例程序
注意,默認情況下,啟動軟件定時器后,僅定時一次,即定時時間到后,調用用戶注冊的回調函數,整個定時過程結束。因此,上述程序僅能觀察到500ms后LED點亮,后續不會再有其它任何現象。
如需再次定時,則必須再次啟動軟件定時器。特別地,若需要周期性的定時,則可以在回調函數執行結束時,再次啟動軟件定時器。例如,需要每隔500ms翻轉一次LED,實現LED閃爍,則范例程序詳見程序清單8.19。
程序清單8.19 軟件定時器周期性定時范例程序
4. 關閉軟件定時器
當不再需要定時服務時,可以關閉軟件定時器,其函數原型為:
其中,p_timer指向軟件定時器實例,用于指定需要關閉的軟件定時器。例如,在程序清單8.19的基礎上,若需要LED閃爍10s后自動停止閃爍,則可以在啟動軟件定時器10s后關閉軟件定時器,范例程序詳見程序清單8.20。
程序清單8.20 關閉軟件定時器范例程序
-
致遠電子
+關注
關注
13文章
405瀏覽量
31278
原文標題:AWorks軟件篇 — 時間管理
文章出處:【微信號:ZLG_zhiyuan,微信公眾號:ZLG致遠電子】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論