周立功教授新書《面向AMetal框架與接口的編程(上)》,對AMetal框架進行了詳細介紹,通過閱讀這本書,你可以學到高度復用的軟件設計原則和面向接口編程的開發思想,聚焦自己的“核心域”,改變自己的編程思維,實現企業和個人的共同進步。
第六章為重用外設驅動代碼,本文內容包含6.3 RTC 實時時鐘前四個小節:
6.3.1 PCF85063
6.3.2 RTC 通用接口
6.3.3 鬧鐘通用接口
6.3.4 系統時間
6.3.5 特殊功能控制接口
6.3 RTC 實時時鐘
本節將以PCF85063 為例,詳細介紹RTC 通用接口,鬧鐘通用接口等。在本節的最后兩小節,將介紹另外兩款RTC 芯片:RX8025T 和DS1302,雖然它們與PCF85063 存在差異,但卻可以使用同樣的通用接口對其進行操作,實現了RTC 應用的跨平臺復用。
>>>6.3.1 PCF85063
1. 器件簡介
PCF85063 是一款低功耗實時時鐘/日歷芯片,它提供了實時時間的設置與獲取、鬧鐘、可編程時鐘輸出、定時器/報警/半分鐘/分鐘中斷輸出等功能。
NXP 半導體公司的PCF85063 引腳封裝詳見圖6.4,其中的SCL 和SDA 為I2C接口引腳,VDD 和VSS 分別為電源和地;OSCI 和OSCO 為32.768KHz 的晶振連接引腳,作為PCF85063 的時鐘源;CLKOUT 為時鐘信號輸出,供其它外部電路使用;INT 為中斷引腳,主要用于鬧鐘等功能。
圖6.4 PCF85063 引腳定義
PCF85063 的7 位I2C從機地址為0x51,MicroPort-RTC 模塊通過MicroPort 接口與AM824-Core 相連,SCL 和SDA 分別與PIO0_16 和PIO0_18 連接,詳見圖6.5。若焊接R1,則INT 與PIO0_1 相連;若焊接R3,則INT 與PIO0_8 相連;若焊接R2,則CLKOUT 與PIO0_24 相連。
圖6.5 PCF85063 電路原理圖
2. 器件初始化
在使用PCF85063 前,必須完成PCF85063 的初始化操作,以獲取對應的操作句柄,進而才能使用PCF85063 的各種功能,初始化函數原型(am_pcf85063.h)為:
該函數意在獲取PCF85063 器件的實例句柄,其中,p_dev 為指向am_pcf85063_dev_t類型實例的指針,int_pin 作為實例信息,指定PCF85063 的INT 與MCU 的連接引腳號。
(1)實例
定義am_pcf85063_dev_t 類型(am_pcf85063.h)實例如下:
其中,g_pcf85063_dev 為用戶自定義的實例,其地址作為p_dev 的實參傳遞。
(2)實例信息
實例信息僅一個中斷引腳信息,用于指定PCF85063 的INT 與MCU 的引腳號相連,便于使用鬧鐘等功能。假設使用PIO0_1,則PIO0_1 作為int_pin 的實參傳遞。
(3)I2C句柄i2c_handle
以I2C1 為例,其實例初始化函數am_lpc82x_i2c1_inst_init ()的返回值將作為實參傳遞給i2c_handle。即:
(4)實例句柄
PCF85063 初始化函數am_pcf85063_init ()的返回值,作為實參傳遞給其它功能接口函數的第一個參數(handle)。am_pcf85063_handle_t 類型的定義(am_pcf85063.h)如下:
若返回值為NULL,說明初始化失敗;若返回值不為NULL,說明返回值handle 有效。
基于模塊化編程思想,將初始化相關的實例、實例信息等的定義存放到對應的配置文件中,通過頭文件引出實例初始化函數接口,源文件和頭文件的程序范例分別詳見程序清單6.39 和程序清單6.40。
程序清單6.39 實例初始化函數實現(am_hwconf_pcf85063.c)
程序清單6.40 實例初始化函數聲明(am_hwconf_pcf85063.h)
后續只需要使用無參數的實例初始化函數,即可獲取到PCF85063 的實例句柄。即:
>>>6.3.2 RTC 通用接口
PCF85063 作為一種典型的RTC 器件,可以使用RTC(Real-Time Clock)通用接口設置和獲取時間,其函數原型詳見表6.10。
表6.10 RTC 通用接口函數(am_rtc.h)
可見,這些接口函數的第一個參數均為am_rtc_handle_t 類型的RTC 句柄,顯然,其并非前文通過PCF85063 實例初始化函數獲取的am_pcf85063_handle_t 類型的句柄。
RTC 時間設置和獲取只是PCF85063 提供的一個主要功能,PCF85063 還能提供鬧鐘等功能。PCF85063 的驅動提供了相應的接口用于獲取PCF85063 的RTC 句柄,以便用戶通過RTC 通用接口操作PCF85063,其函數原型為:
該函數意在獲取RTC 句柄,其中,PCF85063 實例的句柄(pcf85063_handle)作為實參傳遞給handle,p_rtc 為指向am_rtc_serv_t 類型實例的指針,無實例信息。定義am_rtc_serv_t類型(am_rtc.h)實例如下:
其中,g_pcf85063_rtc 為用戶自定義的實例,其地址作為p_rtc 的實參傳遞。
基于模塊化編程思想,將初始化相關的實例定義存放到對應的配置文件中,通過頭文件引出實例初始化函數接口,源文件和頭文件分別詳見程序清單6.41 和程序清單6.42。
程序清單6.41 新增PCF85063 的RTC 實例初始化函數(am_hwconf_pcf85063.c)
程序清單6.42 am_hwconf_pcf85063.h 文件內容更新(1)
后續只需要使用無參數的RTC 實例初始化函數,即可獲取RTC 實例句柄。即:
1. 設置時間
該函數用于設置RTC 器件的當前時間值,其函數原型為:
其中,handle 為RTC 實例句柄,p_tm 為指向細分時間(待設置的時間值)的指針。返回AM_OK,表示設置成功,反之失敗。其類型am_tm_t 是在am_time.h 中定義的細分時間結構體類型,用于表示年/月/日/時/分/秒等信息。即:
其中,tm_mon 表示月份,分別對應1~12 月。tm_year 表示年,1900 年至今的年數,其實際年為該值加上1900。tm_wday;表示星期,0~6 分別對應星期日~星期六。tm_yday 表示1 月1 日以來的的天數(0~365),0 對應1 月1 日。tm_isdst 表示夏令時,夏季將調快1 小時。如果不用,則設置為-1。設置年/月/日/時/分/秒的值詳見程序清單6.43,星期等附加的一些信息無需用戶設置,主要便于在獲取時間時得到更多的信息。
程序清單6.43 設置時間范例程序
2. 獲取時間
該函數用于獲取當前時間值,其函數原型為:
其中,handle 為RTC 實例句柄,p_tm 為指向細分時間的指針,用于獲取細分時間。返回AM_OK,表示獲取成功,反之失敗,范例程序詳見程序清單6.44。
程序清單6.44 獲取細分時間范例程序
基于RTC 通用接口,可以編寫一個通用的時間顯示應用程序:每隔1s 通過調試串口打印當前的時間值。應用程序的實現和接口聲明分別詳見程序清單6.45 和程序清單6.46。
程序清單6.45 RTC 時間顯示應用程序(app_rtc_time_show.c)
程序清單6.46 RTC 時間顯示接口聲明(app_rtc_time_show.h)
為了啟動該應用程序,必須提供一個RTC 實例句柄以指定設置時間和獲取時間的RTC對象,若使用PCF85063,則RTC 實例句柄可通過實例初始化函數am_pcf85063_rtc_inst_init()獲得,范例程序詳見程序清單6.47。
程序清單6.47 啟動RTC 應用程序(基于PCF85063)
>>>6.3.3 鬧鐘通用接口
PCF85063 除提供基本的RTC 功能外,還可以提供鬧鐘功能,可以使用鬧鐘通用接口設置使用鬧鐘,其函數原型詳見表6.11。
表6.11 鬧鐘通用接口函數(am_alarm_clk.h)
由此可見,這些接口函數的第一個參數均為am_alarm_clk_handle_t 類型的鬧鐘句柄,PCF85063 的驅動提供了相應的接口用于獲取PCF85063 的鬧鐘句柄,以便用戶通過鬧鐘通用接口操作PCF85063,其函數原型為:
該函數意在獲取鬧鐘句柄,其中,PCF85063 實例的句柄(pcf85063_handle)作為實參傳遞給handle,p_alarm_clk 為指向am_alarm_clk_serv_t 類型實例的指針,無實例信息。定義am_alarm_clk_serv_t 類型(am_alarm_clk.h)實例如下:
其中,g_pcf85063_alarm_clk 為用戶自定義的實例,其地址作為p_alarm_clk 的實參傳遞。
基于模塊化編程思想,將初始化相關的實例定義存放到對應的配置文件中,通過頭文件引出實例初始化函數接口,源文件和頭文件分別詳見程序清單6.48 和程序清單6.49。
程序清單6.48 新增PCF85063 的鬧鐘實例初始化函數(am_hwconf_pcf85063.c)
程序清單6.49 am_hwconf_pcf85063.h 文件內容更新(2)
后續只需要使用無參數的鬧鐘實例初始化函數,即可獲取鬧鐘實例句柄。即:
1. 設置鬧鐘時間
該函數用于設置鬧鐘時間,其函數原型為:
其中,handle 為鬧鐘實例句柄,p_tm 為指向鬧鐘時間(待設置的時間值)的指針。返回AM_OK,表示設置成功,反之失敗。類型am_alarm_clk_tm_t 是在am_alarm_clk.h 中定義的鬧鐘時間結構體類型,用于表示鬧鐘時間信息。即:
其中,min 表示鬧鐘時間的分,hour 鬧鐘時間的小時,wdays 用于指定鬧鐘在周幾有效,可以是周一至周日的任意一天或幾天。其可用的值已經使用宏進行了定義,比如,AM_ALARM_CLK_SUNDAY 位星期日有效,AM_ALARM_CLK_MONDAY 為星期一有效,AM_ALARM_CLK_TUESDAY 為星期二有效,AM_ALARM_CLK_WEDNESDAY 為星期三有效,AM_ALARM_CLK_THURSDAY 為星期四有效,M_ALARM_CLK_FRIDAY 為星期五有效,AM_ALARM_CLK_SATURDAY 為星期六有效,AM_ALARM_CLK_WORKDAY為工作日有效,AM_ALARM_CLK_EVERYDAY 為每天均有效。
若需鬧鐘在多天同時有效,則可以將多個宏值使用“|”連接起來,比如,要使鬧鐘在星期一和星期二有效,則其值為:
AM_ALARM_CLK_MONDAY | AM_ALARM_CLK_TUESDAY。
若需鬧鐘在星期一至星期五有效(工作日有效),則其值為:
AM_ALARM_CLK_WORKDAY。
若需鬧鐘在每一天均有效,這其值為AM_ALARM_CLK_EVERYDAY,設置鬧鐘的范例程序詳見程序清單6.50。
程序清單6.50 設置鬧鐘時間的范例程序
2. 設置鬧鐘回調函數
PCF85063 可以在指定的時間產生鬧鐘事件,當事件發生時,由于需要通知應用程序,因此需要由應用程序設置一個回調函數,在鬧鐘事件發生時自動調用應用程序設置的回調函數。設置鬧鐘回調函數原型為:
其中,handle 為鬧鐘實例句柄,pfn_callback 為指向實際回調函數的指針,p_arg 為回調函數的參數。若返回AM_OK,表示設置成功,反之失敗。
函數指針的類型am_pfnvoid_t 在am_types.h 中定義,即:
當鬧鐘事件發生時,將自動調用pfn_callback 指向的回調函數,傳遞給該回調函數的void*類型的參數就是p_arg 設定值,范例程序詳見程序清單6.51。
程序清單6.51 設置鬧鐘回調函數范例程序
3. 打開鬧鐘
該函數用于打開鬧鐘,以便當鬧鐘時間到時,自動調用用戶設定的回調函數,其函數原型為:
其中,handle 為鬧鐘實例句柄。返回AM_OK,表示打開成功,反之失敗,范例程序詳見程序清單6.52。
程序清單6.52 打開鬧鐘范例程序
4. 關閉鬧鐘
該函數用于關閉鬧鐘,其函數原型為:
其中,handle 為鬧鐘實例句柄。返回AM_OK,表示關閉成功,反之失敗,范例程序詳見程序清單6.53。
程序清單6.53 關閉鬧鐘范例程序
基于鬧鐘通用接口,可以編寫一個通用的鬧鐘測試應用程序:設定當前時間為09:32:30,鬧鐘時間為09:34,一分半后,達到鬧鐘時間,蜂鳴器鳴叫1 分鐘。鬧鐘測試應用程序的實現和接口聲明分別詳見程序清單6.54 和程序清單6.55。
程序清單6.54 鬧鐘測試應用程序(app_alarm_clk_test.c)
程序清單6.55 鬧鐘測試應用程序接口聲明(app_alarm_clk_test.h)
為了啟動該應用程序,必須提供一個RTC 實例句柄以設置當前時間與一個鬧鐘實例句柄用于設置鬧鐘,若使用PCF85063,則RTC 實例句柄可通過am_pcf85063_rtc_inst_init()獲得,鬧鐘實例句柄可通過am_pcf85063_alarm_clk_inst_init()獲得,范例程序詳見程序清單6.56。
程序清單6.56 啟動鬧鐘測試應用程序(基于PCF85063)
>>>6.3.4 系統時間
AMetal 平臺提供了一個系統時間,進行設置和獲取系統時間的函數原型詳見表6.12。
表6.12 系統時間接口函數(am_time.h)
1. 系統時間
系統時間的3 種表示形式分別為日歷時間、精確日歷時間、細分時間,細分時間前文已有介紹,這里僅介紹日歷時間和精確日歷時間。
-
日歷時間
與標準C 的定義相同,日歷時間表示從1970 年1 月1 日1 時0 分0 秒開始的秒數。其類型am_time_t 定義如下:
-
精確日歷時間
日歷時間精度為秒,精確日歷時間的精度可以達到納秒,精確日歷時間只是在日歷時間的基礎上,增加了一個納秒計數器,其類型am_timespec_t(am_time.h)定義如下:
當納秒值達到1000000000 時,則秒值加1;當該值復位為0 時,則重新計數。
2. 初始化
使用系統時間前,必須初始化系統時間,其函數原型為:
其中,rtc_handle 用于指定系統時間使用的RTC,系統時間將使用該RTC 保存時間和獲取時間。update_sysclk_ns 和 update_rtc_s 用以指定更新系統時間相關的參數。
-
RTC 句柄rtc_handle
獲取RTC 句柄可通過RTC 實例初始化函數獲取,以作為rtc_handle 的實參傳遞。即:
-
與系統時間更新相關的參數(update_sysclk_ns 和 update_rtc_s)
每個MCU 都有一個系統時鐘,比如,LPC824,其系統時鐘的頻率為30MHz,常常稱之為主頻,在短時間內,該時鐘的誤差是很小的。由于直接讀取MCU 中的數據要比通過I2C讀取RTC 器件上的數據快得多,因此根據系統時鐘獲取時間值比直接從RTC 器件中獲取時間值要快得多,完全可以在短時間內使用該時鐘更新系統時間,比如,每隔1ms 將精確日歷時間的納秒值增加1000000。但長時間使用該時鐘來更新系統時間,勢必產生較大的誤差,這就需要每隔一定的時間重新從RTC 器件中,讀取精確的時間值來更新系統時間,以確保系統時間的精度。
update_sysclk_ns 為指定使用系統時鐘更新系統時間的時間間隔,其單位為ns,通常設置為1~100ms,即1000000~100000000。update_rtc_s 為指定使用RTC 器件更新系統時間的時間間隔,若對精度要求特別高,將該值設置為1,即每秒都使用RTC 更新一次系統時間,通常設置為10~ 60 較為合理。
基于此,將初始化函數調用在添加到配置文件中,通過頭文件引出系統時間的實例初始化函數接口,詳見程序清單6.57 和程序清單6.58。
程序清單6.57 PCF85063 用作系統時間的實例初始化(am_hwconf_pcf85063.c)
程序清單6.58 am_hwconf_pcf85063.h 文件內容更新(2)
后續只需要簡單的調用該無參函數,即可完成系統時間的初始化。即:
3. 設置系統時間
根據不同的時間表示形式,有2 種設置系統時間方式。
-
精確日歷時間設置的函數原型為:
其中,p_tv 為指向精確日歷時間(待設置的時間值)的指針。若返回AM_OK,表示設置成功,反之失敗,范例程序詳見程序清單6.59。
程序清單6.59 使用精確日歷時間設置系統時間范例程序
將精確日歷時間的秒值設置為了1472175150,該值是從1970 年1 月1 日0 時0 分0 秒至2016 年8 月26 日09 時32 分30 秒的秒數。即將時間設置為2016 年8 月26 日09 時32分30 秒。通常不會這樣設置時間值,均是采用細分時間方式設置時間值。
-
細分時間設置的函數原型為:
其中,p_tm 為指向細分時間(待設置的時間值)的指針。若返回AM_OK,表示設置成功,反之失敗,范例程序詳見程序清單6.60。
程序清單6.60 使用細分時間設置系統時間范例程序
將時間設置為2016 年8 月26 日09:32:30,當使用細分時間設置時間值時,則細分時間的成員tm_wday, tm_yday 在調用后被更新。如果不使用夏令時,則設置為-1。
4. 獲取系統時間
根據不同的時間表示形式,有3 種獲取系統時間的方式。
-
獲取日歷時間的函數原型為:
其中,p_time 為指向日歷時間的指針,用于獲取日歷時間。返回值同樣為日歷時間,若返回值為-1,表明獲取失敗,通過返回值獲取日歷時間的范例程序詳見程序清單6.61。
程序清單6.61 通過返回值獲取日歷時間范例程序
也可以通過參數獲得日歷時間,范例程序詳見程序清單6.62。
程序清單6.62 通過參數獲取日歷時間范例程序
-
獲取精確日歷時間的函數原型為:
其中,p_tv 為指向精確日歷時間的指針,用于獲取精確日歷時間。若返回AM_OK,獲取成功,反之失敗,范例程序詳見程序清單6.63。
程序清單6.63 讀取精確日歷時間范例程序
-
獲取細分時間的函數原型為:
其中,p_tm 為指向細分時間的指針,用于獲取細分時間。若返回AM_OK,表示獲取成功,反之失敗,范例程序詳見程序清單6.64。
程序清單6.64 獲取細分時間范例程序
基于系統時間相關接口,可以編寫一個通用的系統時間測試應用程序:每隔1s 通過調試串口打印當前的系統時間值。應用程序的實現和接口聲明分別詳見程序清單6.65 和程序清單6.66。
程序清單6.65 系統時間測試應用程序(app_sys_time_show.c)
程序清單6.66 系統時間測試應用程序接口聲明(app_sys_time_show.h)
由此可見,在應用程序中,不再使用到任何實例句柄,使得應用程序不與任何具體器件直接關聯,系統時間的定義使得應用程序在使用時間時更加便捷。在啟動應用程序前,必須完成系統時間的初始化,若使用PCF85063 為系統時間提供RTC 服務,則系統時間的初始化可以通過am_pcf85063_time_inst_init ()完成,范例程序詳見程序清單6.67。
程序清單6.67 啟動系統時間測試應用程序(基于PCF85063)
>>>6.3.5 特殊功能控制接口
對于PCF85063,除典型的時鐘和鬧鐘功能外,還具有一些特殊功能,如定時器、時鐘輸出、1 字節RAM 等。這些功能由于不是通用功能,只能使用PCF85063 相應的接口進行操作。以讀寫1 字節RAM 為例,其相應的接口函數詳見表6.13。
表6.13 讀寫RAM 接口函數(am_pcf85063.h)
1. 寫入RAM
該函數用于寫入1 字節數據到PCF85063 的RAM 中,其函數原型為:
其中,handle 為PCF85063 實例句柄,data 為寫入的單字節數據。若返回AM_OK,表示數據寫入成功,反之失敗,寫入0x55 至RAM 中的范例程序詳見程序清單6.68。
程序清單6.68 寫入RAM 范例程序
2. 讀取RAM
該函數讀取存于PCF85063 的單字節RAM 中的數據,其函數原型為:
其中,handle 為PCF85063 實例句柄,p_data 為輸出參數,用于返回讀取到的單字節數據。返回AM_OK,表示讀取成功,反之失敗,范例程序詳見程序清單6.69。
程序清單6.69 讀取范例程序
可以使用讀寫RAM 接口簡單驗證PCF85063 是否正常,詳見程序清單6.70。
程序清單6.70 讀寫RAM 數據范例程序
-
RTC
+關注
關注
2文章
538瀏覽量
66647
原文標題:周立功:重用外設驅動代碼—— RTC 實時時鐘(1)
文章出處:【微信號:Zlgmcu7890,微信公眾號:周立功單片機】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論