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