文章目录[隐藏]
德斯资源网7月5日消息,软件定时器与硬件定时器的区别。
FreeRTOS 从入门到精通,作者介绍了队列管理的相关知识,本章将讨论FreeRTOS提供的另一个功能——软件定时器(Software Timer)概念与应用。
软件定时器是什么?
为了实现定时或延迟控制,需要设置定时器。定时器分为硬件定时器和软件定时器。硬件定时器是单片机内部的特殊功能模块,可以通过中断硬件定时器准确控制任务的运行时间。然而,单片机的硬件资源通常是有限的,不同类型的单片机定期中断的代码是不同的,这使得程序代码的兼容性和易用性非常困难。相对而言,软件定时器是基于系统时钟中断和软件模拟的定时器 用户定义的回调函数将在时钟计数值后触发。软件定时器不占用单片机宝贵的硬件资源和CPU资源。Freertos为软件定时器提供了完美的支持。为了使用软件定时器,Freertosconfig需要在头文件中使用.configUSE_TIMERS在h中设置为1.
需要定时或延时控制的软件定时器函数称为回调函数。函数的原型如下:
void ATimerCallback( TimerHandle_t xTimer );
函数的返回值是空的,xtimer的参数是软件定时器的具柄。回调函数的注意事项是,代码应尽可能简短紧凑,并避免调用FreeRTOSAPI函数以防止进入阻塞状态。
软件定时器的类型
FreeRTOS中的软件定时器分为两类
一次性定时器(One-shot timer)
定时器自动重载(Auto-reload timer)
一次性定时器启动后只会执行一次回掉函数;定时器自动重载会周期性地执行回调函数。
软件定时器有以下两种状态
静止装态(Dormant)
运行状态(Running)
静态定时器不执行回调函数,可通过调用定时器的手柄启用;在设定的时间间隔(相对于定时器进入运行状态)到达后,运行状态的定时器将调用回调函数。一次性定时器在执行回调函数后会进入静态状态,而自动重载定时器在执行回调函数后会重新进入运行状态。通过调用与软件定时器相关的系统API函数,可以在两种状态之间切换,其中两种定时器的状态转换图如下:
自动重载定时器状态转换图
一次性定时器状态转换图
软件定时器的本质
软件定时器由系统内核调度器自动生成的时间服务任务管理。FreRTOSConfigggg,这个时间服务任务的优先级和堆栈大小的主要文件.h中configTIMER_TASKPRIORIORITY和configTIMER_TASK_STACK_DEPTH属性相应设置。如果定时器的回调函数调用FreeRTOS的API函数,则需要避免时间服务任务管理进入阻塞状态。
启动定时器、停止定时器、重置定时器等软件定时器命令将通过命令队列发送到时间服务任务。Freertosconfig队列长度.h中configTIMER_QUEUE_LENGTH 值设定。
界面的图形配置
在STM32CubeIDEFreeRTOS配置选项中,Timers and Semaphores负责维护软件定时器和信号量(文章将介绍信号量的内容)。点击Add按钮添加一个新的定时器,其中Calback选项是用户实现的回调函数,Type选项可以选择一次性定时器或自动重载定时器。配置完成后,IDE会自动生成相应软件定时器的初始代码,然后通过该界面配置删除或修改,大大降低用户的开发和维护时间成本。
API函数定时器相关API
TimerHandle_t xTimerCreate( const char * const pcTimerName,
TickType_t xTimerPeriodInTicks,
UBaseType_t uxAutoReload,
void * pvTimerID,
TimerCallbackFunction_t pxCallbackFunction )
xTimerCreate()用于创建定时器的函数
函数参数的含义如下
pcTimerName 定时器的名称用于调试
xTimerPeriodInTicks 定时器的周期,dMS_TO_TICKS() 可以把时间变成节拍数
uxAutoReload PDTRUE设置为自动重载定时器,PDFALSE设置为一次性定时器
pvTimerID 定时器的ID可用于各种目的
pxCallbackFunction 定时器执行的回调函数
返回值 NULL表示返回值创建失败,非NULL表示成功创建
BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait )
xTimerStart()启动定时器的函数
函数参数的含义如下
xTimer 要执行定时器的工具手柄
xTicksToWait 如果命令队列是满时函数,则进入阻塞状态,等待命令队列有空时间。
返回值 返回值为pdpass,表示启动定时器成功;返回值为pdfalse,表示失败
void vTimerSetTimerID( const TimerHandle_t xTimer, void *pvNewID )
vTimerSetTimerID()pvtimerID用于设置定时器 属性
函数参数的含义如下
xTimer 执行定时器的具柄
pvNewID pvtimerID设置的值
void *pvTimerGetTimerID( TimerHandle_t xTimer );
pvTimerGetTimerID()pvtimerID用于获取定时器的函数 属性
函数参数的含义如下
xTimer 执行定时器的具柄
返回值 pvtimerID值
BaseType_t xTimerChangePeriod( TimerHandle_t xTimer,
TickType_t xNewTimerPeriodInTicks,
TickType_t xTicksToWait );
用于改变定时器的运行周期的xtimerchangePeriod函数
函数参数的含义如下
xTimer 执行定时器的具柄
xNewTimerPeriodInTicks 新的定时器周期,dMS_TO_TICKS() 时间可以转化为节拍数
xTicksToWait 如果命令队列为满时函数进入阻塞状态,等待命令队列有空时间
返回值 pdpass的返回值表示成功;pdfalse的返回值表示失败
BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait );
xTimerReset()重置定时器使用函数,定时器将重新运行并计算新的时间间隔
函数参数的含义如下
xTimer 要执行定时器的工具手柄
xTicksToWait 如果命令队列是满时函数,则进入阻塞状态,等待命令队列有空时间。
返回值 返回值为PDPASS表示成功;返回值为PDFALSE表示失败;
软件定时器的案例
在此,笔者将举一个使用软件定时器的例子,本案例是通过定时器实现LED闪烁的效果
首先,在t配置界面中建立一个定时器,设置如下
定时器的配置
然后我们可以在mainin中看到IDE.以下代码在c中自动生成
/* Definitions for LedBlink */
osTimerId_t LedBlinkHandle;
const osTimerAttr_t LedBlink_attributes = {
.name = "LedBlink"
};
void CallbackBlink(void *argument);
int main(void)
{
...
/* Create the timer(s) */
/* creation of LedBlink */
LedBlinkHandle = osTimerNew(CallbackBlink, osTimerPeriodic, NULL, &LedBlink_attributes);
/* Start scheduler */
osKernelStart();
...
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
};
/* CallbackBlink function */
void CallbackBlink(void *argument)
{
/* USER CODE BEGIN CallbackBlink */
/* USER CODE END CallbackBlink */
}
从上面的代码中可以看出,IDE已经为我们构建了定时器的初始代码骨架,我们只需要实现回调函数CalbackBlink()
我在这里贴上完整的实现代码,LED灯与PG13输入输出口相连
/* Definitions for LedBlink */
osTimerId_t LedBlinkHandle;
const osTimerAttr_t LedBlink_attributes = {
.name = "LedBlink"
};
void CallbackBlink(void *argument);
int main(void)
{
...
/* Create the timer(s) */
/* creation of LedBlink */
LedBlinkHandle = osTimerNew(CallbackBlink, osTimerPeriodic, NULL, &LedBlink_attributes);
/* start timers, add new ones, ... */
///配置PG13口输出口
TM_GPIO_Init(GPIOG,GPIO_Pin_13,TM_GPIO_Mode_OUT,TM_GPIO_OType_PP,TM_GPIO_PuPd_UP,TM_GPIO_Speed_High);
osTimerStart(LedBlinkHandle, 1000);
/* USER CODE END RTOS_TIMERS */
...
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
};
/* CallbackBlink function */
void CallbackBlink(void *argument)
{
/* USER CODE BEGIN CallbackBlink */
///将PG13口的输出口反转,实现LED灯闪烁的效果
TM_GPIO_TogglePinValue(GPIOG,GPIO_Pin_13);
/* USER CODE END CallbackBlink */
}
在上述代码中, osTimerStart(LedB
总结
今天就分享到这里吧,下期给大家分享更多软件小知识,德斯资源网每天都会更新一些日常软件小知识,包括有微信,微客优品,千喜惠,淘汇购,集市易选,泡泡易选,聊讯,优乐购,淘卷淘,花惜,逗鱼时刻,易凡,坤米,有趣超市,达信酷,思语,惊喜淘,钉钉,支付宝,百盛,陌陌,QQ,微信红包辅助,苹果微信多开,微信分身,安卓微信多开等社交软件下载,软件自带功能有秒抢,避雷,秒,埋雷软件,扫尾,单透软件等一些红包强项外挂功能软件免费下载使用。