软件定时器是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浏览量
6730 -
FreeRTOS
+关注
关注
12文章
483浏览量
61997
发布评论请先 登录
相关推荐
评论