鸿蒙Hi3861学习六-Huawei LiteOS-M(软件定时器)
一、簡介
? ? ? ? 軟件定時器,是基于系統Tick時鐘中斷且由軟件來模擬的定時器。當經過設定的Tick時鐘計數值后,會觸發用戶定義的回調函數。定時精度與系統Tick時鐘周期有關。
? ? ? ? 硬件定時器受硬件的限制,數量上不足以滿足用戶的實際需求。因此,為了滿足用戶需求,提供更多的定時器,LiteOS提供軟件定時器功能。
? ? ? ? 軟件定時器擴展了定時器的數量,允許創建更多的定時業務。
? ? ? ? 軟件定時器功能上支持:
- 靜態裁剪:能通過宏關閉軟件定時器功能。
- 軟件定時器創建。
- 軟件定時器啟動。
- 軟件定時器停止。
- 軟件定時器刪除。
- 軟件定時器剩余Tick數獲取。
? ? ? ? 更多概念可以參考:FreeRTOS學習六(軟件定時器)_freertos 執行定時器回調函數的內存消耗將是在定時器任務堆棧上動態分配_t_guest的博客-CSDN博客
????????Timer Management
二、運作機制
? ? ? ? 軟件定時器使用了系統的一個隊列和一個任務資源,軟件定時器的觸發遵循隊列規則,先進先出。定時時間短的定時器總是比定時時間長的靠近隊列頭,滿足優先被觸發的準則。
? ? ? ? 軟件定時器以Tick為基本計時單位,當用戶創建并啟動一個軟件定時器時,LiteOS會根據當前系統Tick時間寄用戶設置的定時間隔確定該定時器的到期Tick時間,并將該定時器控制結構掛入計時全局鏈表。
? ? ? ? 當Tick中斷到來時,在Tick中斷處理函數中掃描軟件定時器的計時全局鏈表,看是否有定時器超時,若有則將超時的定時器記錄下來。
? ? ? ? Tick中斷處理函數結束后,軟件定時器任務(優先級最高)被喚醒,在該任務中調傭之前記錄下來的定時器的超時回調函數。
三、API介紹
??????osTimerNew
????????函數功能:
? ? ? ? 創建一個軟件定時器
? ? ? ??函數原型:
osTimerId_t osTimerNew(osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr)? ? ? ??參數:
? ? ? ? func:超時回調函數
? ? ? ? type:運行模式
| osTimerOnce | 0,單次 |
| osTimerPeriodic | 1,周期 |
? ? ? ? argument:傳給定時器的參數。沒有填NULL
? ? ? ? attr:定時器相關屬性。自定義地址的時候會用到。大部分情況用不到,填NULL。
? ? ? ??返回值:
? ? ? ? NULL:失敗
? ? ? ? 其他值:osTimerId_t類型的定時器ID。該ID給其他函數使用
? ? ? ??實例:
osTimerPeriodic char timer1_param[] = "timer1 param"; g_timer1_id = osTimerNew(Timer1_Callback, osTimerPeriodic, timer1_param, NULL);??????osTimerStart
????????函數功能:
? ? ? ? 軟件定時器啟動
? ? ? ??函數原型:
osStatus_t osTimerStart(osTimerId_t timer_id, uint32_t ticks)? ? ? ??參數:
? ? ? ? timer_id:軟件定時器ID,創建時osTimerNew獲得。
? ? ? ? ticks:軟件定時器的定時周期。對于Hi3861,定時器單位為10ms。
? ? ? ??返回值:
? ? ? ? osOK:成功
? ? ? ? 其他值:失敗
typedef enum {/** Operation completed successfully */osOK = 0,/** Unspecified error */osError = -1,/** Timeout */osErrorTimeout = -2,/** Resource error */osErrorResource = -3,/** Incorrect parameter */osErrorParameter = -4,/** Insufficient memory */osErrorNoMemory = -5,/** Service interruption */osErrorISR = -6,/** Reserved. It is used to prevent the compiler from optimizing enumerations. */osStatusReserved = 0x7FFFFFFF } osStatus_t;? ? ? ??實例:
osTimerId_t g_timer1_id; timerDelay = 100U; status = osTimerStart(g_timer1_id, timerDelay);??????osTimerStop
????????函數功能:
? ? ? ? 軟件定時器停止
? ? ? ??函數原型:
osStatus_t osTimerStop(osTimerId_t timer_id)? ? ? ??參數:
? ? ? ? timer_id 定時器ID
? ? ? ??返回值
????????osOK:成功
? ? ? ? 其他值:失敗
? ? ? ??實例:
osTimerId_t g_timer1_id; osTimerStop(g_timer1_id);??????osTimerDelete
????????函數功能:
? ? ? ? 軟件定時器刪除
? ? ? ??函數原型:
osStatus_t osTimerDelete(osTimerId_t timer_id)? ? ? ??參數:
????????timer_id 定時器ID
? ? ? ??返回值:
????????osOK:成功
? ? ? ? 其他值:失敗
? ? ? ??實例:
osTimerId_t g_timer1_id; osTimerDelete(g_timer1_id);四、代碼實例
? ? ? ? 此代碼創建兩個軟件定時器,定時器1為循環定時器,定時器2為單次定時器。
#define LOG_I(fmt, args...) printf("<%8ld> - [TIMER]:"fmt"\r\n",osKernelGetTickCount(),##args); #define LOG_E(fmt, args...) printf("<%8ld>-[TIMER_ERR]>>>>>>>>>>>>:"fmt"\r\n",osKernelGetTickCount(), ##args);osTimerId_t g_timer1_id; osTimerId_t g_timer2_id;/***** 定時器1 回調函數 *****/ void Timer1_Callback(void *arg) {static uint8_t cnt = 0;LOG_I("timer1 callback,cnt:%d,param:%s",cnt,arg);if(cnt++ > 10){osTimerDelete(g_timer1_id);LOG_I("timer1 delete");}else if(cnt == 3){osTimerStop(g_timer1_id);LOG_I("timer1 stop and restart timer2");osTimerStart(g_timer2_id, 500);} }/***** 定時器2 回調函數 *****/ void Timer2_Callback(void *arg) {LOG_I("timer2 callback,param:%d",*(uint32_t *)arg);osTimerStart(g_timer1_id, 100);LOG_I("start timer1"); }char timer1_param[] = "timer1 param"; uint32_t timer2_param = 1024;void Hello_World(void) {LOG_I("Test software Timer");uint32_t timerDelay;osStatus_t status;/*timer 1*/g_timer1_id = osTimerNew(Timer1_Callback, osTimerPeriodic, timer1_param, NULL);if (g_timer1_id != NULL){// Hi3861 1U=10ms,100U=1StimerDelay = 100U;status = osTimerStart(g_timer1_id, timerDelay);if (status != osOK){LOG_E("timer1 start error"); }else{LOG_I("timer1 start success,cycle:%dms",timerDelay * 10);}}else{LOG_E("timer1 create fail!!!");}/*timer 2*/g_timer2_id = osTimerNew(Timer2_Callback, osTimerOnce, (void *)&timer2_param, NULL);if (g_timer2_id != NULL){// Hi3861 1U=10ms,100U=1StimerDelay = 500U;status = osTimerStart(g_timer2_id, timerDelay);if (status != osOK){LOG_E("timer2 start error");}else{LOG_I("timer2 start success,cycle:%dms",timerDelay * 10);}}else{LOG_E("timer2 create fail!!!");} }? ? ? ? 定時器1為循環定時器,循環周期為1秒,定時器2為單次定時器,超時時間為5秒。兩個定時器同時啟動。在定時器1第三秒的時候,會停止自己,并且重新啟動定時器2。定時器2超時后會重新啟動定時器1。定時器1在第10次時會刪除自己。
? ? ? ? 看運行結果:
? ? ? ? ?可以看到,雖然定時器2在運行,但是如果此時再次調用osTimerStart來啟動定時器2,會刷新定時器的超時時間。
? ? ? ? 這里我們用軟件打印當前的時間戳,來看一下1秒的定時周期是否準確。
? ? ? ? ?可以看到1秒的定時還是很準的。
總結
以上是生活随笔為你收集整理的鸿蒙Hi3861学习六-Huawei LiteOS-M(软件定时器)的全部內容,希望文章能夠幫你解決所遇到的問題。