軟件定時器是FreeRTOS中的一個重要模塊,使用軟件定時器可以方便的實現一些與超時或周期性相關的功能。
硬件定時器
芯片本身提供的定時功能。一般是由外部晶振提供給芯片輸入時鐘,芯片向軟件模塊提供一組配置寄存器,接受控制輸入,到達設定時間值后芯片中斷控制器產生時鐘中斷。硬件定時器的精度一般很高,可以達到納秒級別,并且是中斷觸發方式。
軟件定時器
軟件定時器是由操作系統提供的一類系統接口,它構建在硬件定時器基礎之上,使系統能夠提供不受硬件定時器資源限制的定時器服務,它實現的功能與硬件定時器也是類似的。
FreeRTOS 軟件定時器功能
裁剪:能通過宏關閉軟件定時器功能。
軟件定時器創建。
軟件定時器啟動。
軟件定時器停止。
軟件定時器復位。
軟件定時器刪除。
軟件定時器模式
單次模式:當用戶創建了定時器并啟動了定時器后,定時時間到了,只執行一次回調函數之后就將該定時器刪除,不再重新執行。
周期模式:這個定時器會按照設置的定時時間循環執行回調函數,直到用戶將定時器刪除
FreeRTOS 通過一個 prvTimerTask 任務(也叫守護任務 Daemon)管理軟定時器,它是在啟動調度器時自動創建的,為了滿足用戶定時需求。prvTimerTask 任務會在其執行期間檢查用戶啟動的時間周期溢出的定時器,并調用其回調函數。只有設置 FreeRTOSConfig.h中的宏定義 configUSE_TIMERS 設置為 1 ,將相關代碼編譯進來,才能正常使用軟件定時器相關功能。
配置定時器
//啟用軟件定時器
#define configUSE_TIMERS 1
//軟件定時器優先級
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-1)
//軟件定時器隊列長度
#define configTIMER_QUEUE_LENGTH 10
//軟件定時器任務堆棧大小
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE*2)
創建定時器
TimerHandle_t xTimerCreate( const char *pcTimerName,
const TickType_t xTimerPeriod,
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction );
參數:
pcTimerName:定時器名稱
xTimerPeriod :定時周期
uxAutoReload : 如果將uxAutoReload設置為pdTRUE,則計時器將以xTimerPeriod參數設置的頻率重復終止。如果將uxAutoReload設置為pdFALSE,則計時器將是一次觸發,并在其到期后進入休眠狀態。
pvTimerID:分配給正在創建的計時器的標識符。
pxCallbackFunction:計時器到期時要調用的函數。
返回值:
如果成功創建了計時器,則返回新創建的計時器的句柄。如果由于剩余的FreeRTOS堆不足而無法分配計時器結構而無法創建計時器,則返回NULL
啟動定時器
BaseType_t xTimerStart( TimerHandle_t xTimer,
TickType_t xTicksToWait );
參數:
xTimer:計時器的句柄
xTicksToWait:指定在計時器命令隊列已經滿的情況下,任務應保持阻塞狀態以等待空間可用的最大時間。
返回值:
如果即使經過xBlockTime刻度后仍無法將啟動命令發送到計時器命令隊列,則將返回pdFAIL。如果命令已成功發送到計時器命令隊列,則將返回pdPASS。
停止定時器
BaseType_t xTimerStop( TimerHandle_t xTimer,
TickType_t xTicksToWait );
參數:同上
返回值:同上
復位定時器
BaseType_t xTimerReset( TimerHandle_t xTimer,
TickType_t xTicksToWait );
參數:同上
返回值:同上
刪除定時器
BaseType_t xTimerDelete( TimerHandle_t xTimer,
TickType_t xTicksToWait );
參數:同上類似
返回值:同上類似
改變定時器周期
BaseType_t xTimerChangePeriod( TimerHandle_t xTimer,
TickType_txNewPeriod,
TickType_t xTicksToWait );
參數:
xTimer:定時器的句柄
xNewPeriod:新的周期參數
xTicksToWait:指定在計時器命令隊列已經滿的情況下,任務應保持阻塞狀態以等待空間可用的最大時間。
返回值:
如果即使經過xBlockTime滴答聲后仍無法將更改周期命令發送到計時器命令隊列,則將返回pdFAIL。如果命令已成功發送到計時器命令隊列,則將返回pdPASS。
還有中斷啟動定時器、停止、復位、改變周期的API函數,請查閱官方文檔!
附上小例程
#include "stm32f10x.h"
#include
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "timers.h"
//毫秒級的延時
void Delay_Ms(u16 time)
{
u16 i=0;
while(time--)
{
i=12000; //自己定義
while(i--) ;
}
}
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //定義結構體變量
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //開啟時鐘
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0; //選擇你要設置的IO口
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //設置推挽輸出模式
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //設置傳輸速率
GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化GPIO
GPIO_SetBits(GPIOC,GPIO_Pin_0); //將LED端口拉高,熄滅LED
}
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //定義結構體變量
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0; //選擇你要設置的IO口
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;//下拉輸入
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //設置傳輸速率
GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化GPIO */
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_2|GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; //上拉輸入
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_InitStructure);
}
void USART_init(uint32_t bound)
{
GPIO_InitTypeDef GPIO_InitStruct; //定義GPIO結構體變量
USART_InitTypeDef USART_InitStruct; //定義串口結構體變量
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE); //使能GPIOC的時鐘
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9; //配置TX引腳
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP; //配置PA9為復用推挽輸出
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; //配置PA9速率
GPIO_Init(GPIOA,&GPIO_InitStruct); //GPIO初始化函數
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10; //配置RX引腳
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING; //配置PA10為浮空輸入
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; //配置PA10速率
GPIO_Init(GPIOA,&GPIO_InitStruct); //GPIO初始化函數
USART_InitStruct.USART_Mode=USART_Mode_Tx|USART_Mode_Rx; //發送接收模式
USART_InitStruct.USART_Parity=USART_Parity_No; //無奇偶校驗
USART_InitStruct.USART_BaudRate=bound; //波特率
USART_InitStruct.USART_StopBits=USART_StopBits_1; //停止位1位
USART_InitStruct.USART_WordLength=USART_WordLength_8b; //字長8位
USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None; //無硬件數據流控制
USART_Init(USART1,&USART_InitStruct); //串口初始化函數
USART_Cmd(USART1,ENABLE); //使能USART1
}
int fputc(int ch,FILE *f) //printf重定向函數
{
USART_SendData(USART1,(uint8_t)ch); //發送一字節數據
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); //等待發送完成
return ch;
}
#define START_TASK_PRIO 5 //任務優先級
#define START_STK_SIZE 128 //任務堆棧大小
TaskHandle_t StartTask_Handler; //任務句柄
void Start_Task(void *pvParameters);//任務函數
#define Low_TASK_PRIO 2 //任務優先級
#define Low_STK_SIZE 50 //任務堆棧大小
TaskHandle_t LowTask_Handler; //任務句柄
void Low_Task(void *p_arg); //任務函數
#define Med_TASK_PRIO 3 //任務優先級
#define Med_STK_SIZE 50 //任務堆棧大小
TaskHandle_t MedTask_Handler; //任務句柄
void Med_Task(void *p_arg); //任務函數
TimerHandle_t Time0Handler = NULL; //軟件定時器句柄
void Time0Callback( TimerHandle_t pxTimer );//回調函數
int main( void )
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//設置系統中斷優先級分組 4
LED_Init(); //初始化 LED
KEY_Init();
USART_init(9600);
//創建開始任務
xTaskCreate(
(TaskFunction_t )Start_Task, //任務函數
(const char* )"Start_Task", //任務名稱
(uint16_t )START_STK_SIZE, //任務堆棧大小
(void* )NULL, //傳遞給任務函數的參數
(UBaseType_t )START_TASK_PRIO, //任務優先級
(TaskHandle_t* )&StartTask_Handler //任務句柄
);
vTaskStartScheduler(); //開啟調度
}
//開始任務函數
void Start_Task(void *pvParameters)
{
taskENTER_CRITICAL(); //進入臨界區
//創建軟件定時器
Time0Handler = xTimerCreate( ( char * ) "Time0", //定時器的名稱
( TickType_t ) 1000, //定時周期
( UBaseType_t ) pdTRUE, //是否重裝載 (pdTRUE or pdFAIL)
( void * ) 0, //ID號
( TimerCallbackFunction_t ) Time0Callback ); //回調函數
//開啟定時器
xTimerStart( Time0Handler, portMAX_DELAY );
//創建 Low 任務
xTaskCreate(
(TaskFunction_t )Low_Task,
(const char* )"Low_Task",
(uint16_t )Low_STK_SIZE,
(void* )NULL,
(UBaseType_t )Low_TASK_PRIO,
(TaskHandle_t* )&LowTask_Handler
);
//創建 Med 任務
xTaskCreate(
(TaskFunction_t )Med_Task,
(const char* )"Med_Task",
(uint16_t )Med_STK_SIZE,
(void* )NULL,
(UBaseType_t )Med_TASK_PRIO,
(TaskHandle_t* )&MedTask_Handler
);
vTaskDelete(StartTask_Handler); //刪除開始任務
taskEXIT_CRITICAL(); //退出臨界區
}
void Low_Task(void *pvParameters)
{
while(1)
{
vTaskDelay(1000);
}
}
void Med_Task(void *pvParameters)
{
//BaseType_t xReturn = NULL;
while(1)
{
printf("正在運行n");
vTaskDelay(1000);
}
}
void Time0Callback( TimerHandle_t pxTimer )
{
static int count = 0;
printf("%dn",++count);
}
實驗現象
--END--
-
軟件定時器
+關注
關注
0文章
18瀏覽量
6749 -
FreeRTOS
+關注
關注
12文章
484瀏覽量
62178
發布評論請先 登錄
相關推薦
評論