物联网操作系统-软件定时器(software timer)

这篇具有很好参考价值的文章主要介绍了物联网操作系统-软件定时器(software timer)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

软件定时器就是"闹钟",你可以设置闹钟,
⚫ 在 30 分钟后让你起床工作
⚫ 每隔 1 小时让你例行检查机器运行情况
软件定时器也可以完成两类事情:
⚫ 在"未来"某个时间点,运行函数
⚫ 周期性地运行函数
日常生活中我们可以定无数个"闹钟",这无数的"闹钟"要基于一个真实的闹钟。
在FreeRTOS里,我们也可以设置无数个"软件定时器",它们都是基于系统滴答中断
(Tick Interrupt)。
本章涉及如下内容:
⚫ 软件定时器的特性
⚫ Daemon Task
⚫ 定时器命令队列
⚫ 一次性定时器、周期性定时器的差别
⚫ 怎么操作定时器:创建、启动、复位、修改周期
 

软件定时器的特性


我们在手机上添加闹钟时,需要指定时间、指定类型(一次性的,还是周期性的)、指定
做什么事;还有一些过时的、不再使用的闹钟。 如下图所示:
 

物联网操作系统-软件定时器(software timer),物联网操作系统Freertos开发,FreeRTOS组件详解,单片机,嵌入式硬件,计算机外设,stm32,物联网

使用定时器跟使用手机闹钟是类似的:
⚫ 指定时间:启动定时器和运行回调函数,两者的间隔被称为定时器的周期
(period)。
⚫ 指定类型,定时器有两种类型:
◼ 一次性(One-shot timers):
这类定时器启动后,它的回调函数只会被调用一次;
可以手工再次启动它,但是不会自动启动它。
◼ 自动加载定时器(Auto-reload timers ):
这类定时器启动后,时间到之后它会自动启动它;
这使得回调函数被周期性地调用。
⚫ 指定要做什么事,就是指定回调函数


实际的闹钟分为:有效、无效两类。软件定时器也是类似的,它由两种状态:
⚫ 运行(Running、 Active):运行态的定时器,当指定时间到达之后,它的回调
函数会被调用
⚫ 冬眠(Dormant):冬眠态的定时器还可以通过句柄来访问它,但是它不再运
行,它的回调函数不会被调用
 

定时器运行情况示例如下:
⚫ Timer1:它是一次性的定时器,在 t1 启动,周期是 6 个 Tick。经过 6 个 tick
后,在 t7 执行回调函数。它的回调函数只会被执行一次,然后该定时器进入冬眠
状态。
⚫ Timer2:它是自动加载的定时器,在 t1 启动,周期是 5 个 Tick。每经过 5 个
tick 它的回调函数都被执行,比如在 t6、 t11、 t16 都会执行
物联网操作系统-软件定时器(software timer),物联网操作系统Freertos开发,FreeRTOS组件详解,单片机,嵌入式硬件,计算机外设,stm32,物联网

软件定时器的上下文  

守护任务


要理解软件定时器 API 函数的参数,特别是里面的 xTicksToWait,需要知道定时器执
行的过程。
FreeRTOS中有一个Tick中断,软件定时器基于Tick来运行。在哪里执行定时器函数?第
一印象就是在Tick中断里执行:
⚫ 在 Tick 中断中判断定时器是否超时
⚫ 如果超时了,调用它的回调函数
FreeRTOS 是 RTOS,它不允许在内核、在中断中执行不确定的代码:如果定时器函数很
耗时,会影响整个系统。
所以, FreeRTOS中,不在Tick中断中执行定时器函数。
在哪里执行?在某个任务里执行,这个任务就是: RTOS Damemon Task, RTOS守护
任务。以前被称为"Timer server",但是这个任务要做并不仅仅是定时器相关,所以改名为:
RTOS Damemon Task。
当FreeRTOS的配置项configUSE_TIMERS被设置为1时,在启动调度器时,会自动创
建RTOS Damemon Task。
我们自己编写的任务函数要使用定时器时,是通过"定时器命令队列"(timer commandqueue)和守护任务交互,如下图所示:
物联网操作系统-软件定时器(software timer),物联网操作系统Freertos开发,FreeRTOS组件详解,单片机,嵌入式硬件,计算机外设,stm32,物联网

守护任务的优 先级为: configTIMER_TASK_PRIORITY ;定时器命令队列的长度 为
configTIMER_QUEUE_LENGTH。

守护任务的调度

守护任务的调度,跟普通的任务并无差别。当守护任务是当前优先级最高的就绪态任务
时,它就可以运行。 它的工作有两类:
⚫ 处理命令:从命令队列里取出命令、处理
⚫ 执行定时器的回调函数
能否及时处理定时器的命令、能否及时执行定时器的回调函数,严重依赖于守护任务的
优先级。下面使用 2 个例子来演示。
例子1:守护任务的优先性级较低
⚫ t1: Task1 处于运行态,守护任务处于阻塞态。
守护任务在这两种情况下会退出阻塞态切换为就绪态:命令队列中有数据、某个
定时器超时了。
至于守护任务能否马上执行,取决于它的优先级。
⚫ t2: Task1 调用 xTimerStart()
要注意的是, xTimerStart()只是把"start timer"的命令发给"定时器命令队列",使
得守护任务退出阻塞态。
在本例中, Task1 的优先级高于守护任务,所以守护任务无法抢占 Task1。
⚫ t3: Task1 执行完 xTimerStart()
但是定时器的启动工作由守护任务来实现,所以 xTimerStart()返回并不表示定时
器已经被启动了。
⚫ t4: Task1 由于某些原因进入阻塞态,现在轮到守护任务运行。
守护任务从队列中取出"start timer"命令,启动定时器。
⚫ t5:守护任务处理完队列中所有的命令,再次进入阻塞态。 Idel 任务时优先
级最高的就绪态任务,它执行。
⚫ 注意:假设定时器在后续某个时刻 tX 超时了,超时时间是"tX-t2",而非"tXt4",从 xTimerStart()函数被调用时算起。
物联网操作系统-软件定时器(software timer),物联网操作系统Freertos开发,FreeRTOS组件详解,单片机,嵌入式硬件,计算机外设,stm32,物联网

 

例子2:守护任务的优先性级较高
⚫ t1: Task1 处于运行态,守护任务处于阻塞态。
守护任务在这两种情况下会退出阻塞态切换为就绪态:命令队列中有数据、某个
定时器超时了。
至于守护任务能否马上执行,取决于它的优先级。
⚫ t2: Task1 调用 xTimerStart()
要注意的是, xTimerStart()只是把"start timer"的命令发给"定时器命令队列",使
得守护任务退出阻塞态。
在本例中,守护任务的优先级高于 Task1,所以守护任务抢占 Task1,守护任务开
始处理命令队列。
Task1 在执行 xTimerStart()的过程中被抢占,这时它无法完成此函数。
⚫ t3:守护任务处理完命令队列中所有的命令,再次进入阻塞态。
此时 Task1 是优先级最高的就绪态任务,它开始执行。
⚫ t4: Task1 之前被守护任务抢占,对 xTimerStart()的调用尚未返回。现在开
始继续运行次函数、返回。
⚫ t5: Task1 由于某些原因进入阻塞态,进入阻塞态。 Idel 任务时优先级最高的
就绪态任务,它执行。
物联网操作系统-软件定时器(software timer),物联网操作系统Freertos开发,FreeRTOS组件详解,单片机,嵌入式硬件,计算机外设,stm32,物联网注意,定时器的超时时间是基于调用xTimerStart()的时刻tX,而不是基于守护任务处理
命令的时刻tY。假设超时时间是10个Tick,超时时间是"tX+10",而非"tY+10"。
 

回调函数


定时器的回调函数的原型如下:

void ATimerCallback( TimerHandle_t xTimer );

定时器的回调函数是在守护任务中被调用的,守护任务不是专为某个定时器服务的,它
还要处理其他定时器。
所以,定时器的回调函数不要影响其他人:
⚫ 回调函数要尽快实行,不能进入阻塞状态
⚫ 不要调用会导致阻塞的 API 函数,比如 vTaskDelay()
⚫ 可以调用 xQueueReceive()之类的函数,但是超时时间要设为 0:即刻返
回,不可阻塞
 

软件定时器的函数  

根据定时器的状态转换图,就可以知道所涉及的函数:
物联网操作系统-软件定时器(software timer),物联网操作系统Freertos开发,FreeRTOS组件详解,单片机,嵌入式硬件,计算机外设,stm32,物联网

物联网操作系统-软件定时器(software timer),物联网操作系统Freertos开发,FreeRTOS组件详解,单片机,嵌入式硬件,计算机外设,stm32,物联网

创建


要使用定时器,需要先创建它,得到它的句柄。
有两种方法创建定时器:动态分配内存、静态分配内存。函数原型如下:
 

/* 使用动态分配内存的方法创建定时器
* pcTimerName:定时器名字, 用处不大, 尽在调试时用到
* xTimerPeriodInTicks: 周期, 以 Tick 为单位
* uxAutoReload: 类型, pdTRUE 表示自动加载, pdFALSE 表示一次性
* pvTimerID: 回调函数可以使用此参数, 比如分辨是哪个定时器
* pxCallbackFunction: 回调函数
* 返回值: 成功则返回 TimerHandle_t, 否则返回 NULL
*/
TimerHandle_t xTimerCreate( const char * const pcTimerName,
const TickType_t xTimerPeriodInTicks,
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction );
/* 使用静态分配内存的方法创建定时器
* pcTimerName:定时器名字, 用处不大, 尽在调试时用到
* xTimerPeriodInTicks: 周期, 以 Tick 为单位
* uxAutoReload: 类型, pdTRUE 表示自动加载, pdFALSE 表示一次性
* pvTimerID: 回调函数可以使用此参数, 比如分辨是哪个定时器
* pxCallbackFunction: 回调函数
* pxTimerBuffer: 传入一个 StaticTimer_t 结构体, 将在上面构造定时器
* 返回值: 成功则返回 TimerHandle_t, 否则返回 NULL
*/
TimerHandle_t xTimerCreateStatic(const char * const pcTimerName,
TickType_t xTimerPeriodInTicks,
UBaseType_t uxAutoReload,
void * pvTimerID,
TimerCallbackFunction_t pxCallbackFunction,
StaticTimer_t *pxTimerBuffer );

回调函数的类型是:

void ATimerCallback( TimerHandle_t xTimer );
typedef void (* TimerCallbackFunction_t)( TimerHandle_t xTimer );

删除


动态分配的定时器,不再需要时可以删除掉以回收内存。删除函数原型如下:
 

/* 删除定时器
* xTimer: 要删除哪个定时器
* xTicksToWait: 超时时间
* 返回值: pdFAIL 表示"删除命令"在 xTicksToWait 个 Tick 内无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait );

定时器的很多 API 函数,都是通过发送"命令"到命令队列,由守护任务来实现。
如果队列满了, "命令"就无法即刻写入队列。我们可以指定一个超时时间xTicksToWait,
等待一会。
 

启动/停止


启动定时器就是设置它的状态为运行态(Running、 Active)。
停止定时器就是设置它的状态为冬眠(Dormant),让它不能运行。
涉及的函数原型如下:
 

/* 启动定时器
* xTimer: 哪个定时器
* xTicksToWait: 超时时间
* 返回值: pdFAIL 表示"启动命令"在 xTicksToWait 个 Tick 内无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait );
/* 启动定时器(ISR 版本)
* xTimer: 哪个定时器
* pxHigherPriorityTaskWoken: 向队列发出命令使得守护任务被唤醒,
* 如果守护任务的优先级比当前任务的高,
* 则"*pxHigherPriorityTaskWoken = pdTRUE",
* 表示需要进行任务调度
* 返回值: pdFAIL 表示"启动命令"无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerStartFromISR( TimerHandle_t xTimer,
BaseType_t *pxHigherPriorityTaskWoken );
/* 停止定时器
* xTimer: 哪个定时器
* xTicksToWait: 超时时间
* 返回值: pdFAIL 表示"停止命令"在 xTicksToWait 个 Tick 内无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait );
/* 停止定时器(ISR 版本)
* xTimer: 哪个定时器
* pxHigherPriorityTaskWoken: 向队列发出命令使得守护任务被唤醒,
* 如果守护任务的优先级比当前任务的高,
* 则"*pxHigherPriorityTaskWoken = pdTRUE",
* 表示需要进行任务调度
* 返回值: pdFAIL 表示"停止命令"无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerStopFromISR( TimerHandle_t xTimer,
BaseType_t *pxHigherPriorityTaskWoken );

注意,这些函数的 xTicksToWait 表示的是,把命令写入命令队列的超时时间。命令队
列可能已经满了,无法马上把命令写入队列里,可以等待一会。
xTicksToWait不是定时器本身的超时时间,不是定时器本身的"周期"。
创建定时器时,设置了它的周期(period)。 xTimerStart()函数是用来启动定时器。假设
调用xTimerStart()的时刻是tX,定时器的周期是n,那么在tX+n时刻定时器的回调函数被
调用。
如果定时器已经被启动,但是它的函数尚未被执行,再次执行xTimerStart()函数相当于
执行xTimerReset(),重新设定它的启动时间。

 复位


从定时器的状态转换图可以知道,使用 xTimerReset()函数可以让定时器的状态从冬眠
态转换为运行态,相当于使用 xTimerStart()函数。
如果定时器已经处于运行态,使用xTimerReset()函数就相当于重新确定超时时间。假
设调用xTimerReset()的时刻是tX,定时器的周期是n,那么tX+n就是重新确定的超时时间。
复位函数的原型如下:
 

 

* 复位定时器
* xTimer: 哪个定时器
* xTicksToWait: 超时时间
* 返回值: pdFAIL 表示"复位命令"在 xTicksToWait 个 Tick 内无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait );
/* 复位定时器(ISR 版本)
* xTimer: 哪个定时器
* pxHigherPriorityTaskWoken: 向队列发出命令使得守护任务被唤醒,
* 如果守护任务的优先级比当前任务的高,
* 则"*pxHigherPriorityTaskWoken = pdTRUE",
* 表示需要进行任务调度
* 返回值: pdFAIL 表示"停止命令"无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerResetFromISR( TimerHandle_t xTimer,
BaseType_t *pxHigherPriorityTaskWoken );

修改周期


从定时器的状态转换图可以知道,使用 xTimerChangePeriod()函数,处理能修改它的
周期外,还可以让定时器的状态从冬眠态转换为运行态。
修 改 定 时 器 的 周 期 时 , 会 使 用 新 的 周 期 重 新 计 算 它 的 超 时 时 间 。 假 设 调 用
xTimerChangePeriod()函数的时间tX,新的周期是n,则tX+n就是新的超时时间。
相关函数的原型如下:


 

 

/* 修改定时器的周期
* xTimer: 哪个定时器
* xNewPeriod: 新周期
* xTicksToWait: 超时时间, 命令写入队列的超时时间
* 返回值: pdFAIL 表示"修改周期命令"在 xTicksToWait 个 Tick 内无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerChangePeriod( TimerHandle_t xTimer,
TickType_t xNewPeriod,
TickType_t xTicksToWait );
/* 修改定时器的周期
* xTimer: 哪个定时器
* xNewPeriod: 新周期
* pxHigherPriorityTaskWoken: 向队列发出命令使得守护任务被唤醒,
* 如果守护任务的优先级比当前任务的高,
* 则"*pxHigherPriorityTaskWoken = pdTRUE",
* 表示需要进行任务调度
* 返回值: pdFAIL 表示"修改周期命令"在 xTicksToWait 个 Tick 内无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerChangePeriodFromISR( TimerHandle_t xTimer,
TickType_t xNewPeriod,
BaseType_t *pxHigherPriorityTaskWoken );

定时器 ID


定时器的结构体如下,里面有一项 pvTimerID,它就是定时器
物联网操作系统-软件定时器(software timer),物联网操作系统Freertos开发,FreeRTOS组件详解,单片机,嵌入式硬件,计算机外设,stm32,物联网

 怎么使用定时器ID,完全由程序来决定:
⚫ 可以用来标记定时器,表示自己是什么定时器
⚫ 可以用来保存参数,给回调函数使用
它的初始值在创建定时器时由xTimerCreate()这类函数传入,后续可以使用这些函数
来操作:
⚫ 更新 ID:使用 vTimerSetTimerID()函数
⚫ 查询 ID:查询 pvTimerGetTimerID()函数
这两个函数不涉及命令队列,它们是直接操作定时器结构体。
函数原型如下:

/* 获得定时器的 ID
* xTimer: 哪个定时器
* 返回值: 定时器的 ID
*/
void *pvTimerGetTimerID( TimerHandle_t xTimer );
/* 设置定时器的 ID
* xTimer: 哪个定时器
* pvNewID: 新 ID
* 返回值: 无
*/
void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID );

示例 : 一般使用


要使用定时器,需要做些准备工作:
 

/* 1. 工程中 */
添加 timer.c
/* 2. 配置文件 FreeRTOSConfig.h 中 */
##define configUSE_TIMERS 1 /* 使能定时器 */
##define configTIMER_TASK_PRIORITY 31 /* 守护任务的优先级, 尽可能高一些 */
##define configTIMER_QUEUE_LENGTH 5 /* 命令队列长度 */
##define configTIMER_TASK_STACK_DEPTH 32 /* 守护任务的栈大小 */
/* 3. 源码中 */
##include "timers.h"

main函数中创建、启动了2个定时器:一次性的、周期
 

static volatile uint8_t flagONEShotTimerRun = 0;
static volatile uint8_t flagAutoLoadTimerRun = 0;
static void vONEShotTimerFunc( TimerHandle_t xTimer );
static void vAutoLoadTimerFunc( TimerHandle_t xTimer );
/*-----------------------------------------------------------*/
##define mainONE_SHOT_TIMER_PERIOD pdMS_TO_TICKS( 10 )
##define mainAUTO_RELOAD_TIMER_PERIOD pdMS_TO_TICKS( 20 )
int main( void )
{
TimerHandle_t xOneShotTimer;
TimerHandle_t xAutoReloadTimer;
prvSetupHardware();
xOneShotTimer = xTimerCreate(
"OneShot", /* 名字, 不重要 */
mainONE_SHOT_TIMER_PERIOD, /* 周期 */
pdFALSE, /* 一次性 */
0, /* ID */
vONEShotTimerFunc /* 回调函数 */
);
xAutoReloadTimer = xTimerCreate(
"AutoReload", /* 名字, 不重要 */
mainAUTO_RELOAD_TIMER_PERIOD, /* 周期 */
pdTRUE, /* 自动加载 */
0, /* ID */
vAutoLoadTimerFunc /* 回调函数 */
);
if (xOneShotTimer && xAutoReloadTimer)
{
/* 启动定时器 */
xTimerStart(xOneShotTimer, 0);
xTimerStart(xAutoReloadTimer, 0);
/* 启动调度器 */
vTaskStartScheduler();
}
/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
return 0;
}

 这两个定时器的回调函数比较简单:

 

static void vONEShotTimerFunc( TimerHandle_t xTimer )
{
static int cnt = 0;
flagONEShotTimerRun = !flagONEShotTimerRun;
printf("run vONEShotTimerFunc %d\r\n", cnt++);
}
static void vAutoLoadTimerFunc( TimerHandle_t xTimer )
{
static int cnt = 0;
flagAutoLoadTimerRun = !flagAutoLoadTimerRun;
printf("run vAutoLoadTimerFunc %d\r\n", cnt++);
}


物联网操作系统-软件定时器(software timer),物联网操作系统Freertos开发,FreeRTOS组件详解,单片机,嵌入式硬件,计算机外设,stm32,物联网

 示例 : 消除抖动

在嵌入式开发中,我们使用机械开关时经常碰到抖动问题:引脚电平在短时间内反复变
化。
怎么读到确定的按键状态?
⚫ 连续读很多次,知道数值稳定:浪费 CPU 资源
⚫ 使用定时器:要结合中断来使用
对于第 2 种方法,处理方法如下图所示,按下按键后:
⚫ 在 t1 产生中断,这时不马上确定按键,而是复位定时器,假设周期时
20ms,超时时间为"t1+20ms"
⚫ 由于抖动,在 t2 再次产生中断,再次复位定时器,超时时间变为"t2+20ms"
⚫ 由于抖动,在 t3 再次产生中断,再次复位定时器,超时时间变为"t3+20ms"
⚫ 在"t3+20ms"处,按键已经稳定,读取按键值
物联网操作系统-软件定时器(software timer),物联网操作系统Freertos开发,FreeRTOS组件详解,单片机,嵌入式硬件,计算机外设,stm32,物联网

main函数中创建了一个一次性的定时器,从来处理抖动;创建了一个任务,用来模拟产
生抖动。代码如下:
 

/*-----------------------------------------------------------*/
static void vKeyFilteringTimerFunc( TimerHandle_t xTimer );
void vEmulateKeyTask( void *pvParameters );
static TimerHandle_t xKeyFilteringTimer;
/*-----------------------------------------------------------*/
##define KEY_FILTERING_PERIOD pdMS_TO_TICKS( 20 )
int main( void )
{
prvSetupHardware();
xKeyFilteringTimer = xTimerCreate(
"KeyFiltering", /* 名字, 不重要 */
KEY_FILTERING_PERIOD, /* 周期 */
pdFALSE, /* 一次性 */
0, /* ID */
vKeyFilteringTimerFunc /* 回调函数 */
);
/* 在这个任务中多次调用 xTimerReset 来模拟按键抖动 */
xTaskCreate( vEmulateKeyTask, "EmulateKey", 1000, NULL, 1, NULL );
/* 启动调度器 */
vTaskStartScheduler();
/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
return 0;
}

模拟产生按键:每个循环里调用3次xTimerReset,代码如下:
 

void vEmulateKeyTask( void *pvParameters )
{
int cnt = 0;
const TickType_t xDelayTicks = pdMS_TO_TICKS( 200UL );
for( ;; )
{
/* 模拟按键抖动, 多次调用 xTimerReset */
xTimerReset(xKeyFilteringTimer, 0); cnt++;
xTimerReset(xKeyFilteringTimer, 0); cnt++;
xTimerReset(xKeyFilteringTimer, 0); cnt++;
printf("Key jitters %d\r\n", cnt);
vTaskDelay(xDelayTicks);
}
}

定时器回调函数代码如下:

static void vKeyFilteringTimerFunc( TimerHandle_t xTimer )
{
static int cnt = 0;
printf("vKeyFilteringTimerFunc %d\r\n", cnt++);
}

在用户函数中多次调用xTimerReset,只触发1次定时器回调函数,运行结果如下图所示:
物联网操作系统-软件定时器(software timer),物联网操作系统Freertos开发,FreeRTOS组件详解,单片机,嵌入式硬件,计算机外设,stm32,物联网文章来源地址https://www.toymoban.com/news/detail-831831.html

到了这里,关于物联网操作系统-软件定时器(software timer)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32物联网实战开发(4)——基本定时器

            我使用的是正点原子的阿波罗F429开发板,他有14个定时器,本次实验使用STM32F429的基本定时器6作定时,在中断中每隔1秒翻转LED电平状态。 1.CubeMX初始化定时器 先开启定时器6          再对定时器6的参数进行配置,将定时器6定时时间配置为 5ms ,在中断中再累

    2024年02月01日
    浏览(17)
  • STM32软件定时器

    目录 什么是定时器? 软件定时器优缺点 软件定时器原理 软件定时器相关配置 单次定时器和周期定时器 软件定时器相关 API 函数 1. 创建软件定时器 2. 开启软件定时器 3. 停止软件定时器 4. 复位软件定时器 5. 更改软件定时器定时时间 实操 cubeMX配置 代码实现  简单可以理解为

    2024年02月11日
    浏览(18)
  • FreeRTOS(6)----软件定时器

    软件定时器允许设置一段时间, 当设定的时间到达之后就会执行指定的功能函数 ,被定时器调用的这个函数叫做定时器的回调函数。 回调函数的两次执行间隔 叫做定时器的定时周期。 回调函数是在定时器服务任务中执行的,因为定时器服务任务是由内核产生,无法由用户

    2024年02月05日
    浏览(17)
  • FreeRTOS教程9 软件定时器

    正点原子stm32f407探索者开发板V2.4 STM32CubeMX软件(Version 6.10.0) Keil µVision5 IDE(MDK-Arm) 野火DAP仿真器 XCOM V2.6串口助手 本文主要学习 FreeRTOS 软件定时器的相关知识, 包括软件定时器回调函数、属性、状态、运行原理和常见 API 函数等知识 软件定时器的回调函数 是一个返回值

    2024年03月21日
    浏览(25)
  • 【STM32】FreeRTOS软件定时器学习

      软件定时器 FreeRTOS提供了现成的软件定时器功能,可以一定程度上替代硬件定时器,但精度不高。 实验:创建一个任务,两个定时器,按键开启定时器,一个500ms打印一次,一个1000ms打印一次。 实现:在【STM32】FreeRTOS事件组学习基础上修改。 上面的代码是CubeMX封装好的。

    2024年02月12日
    浏览(15)
  • FreeRTOS软件定时器 基于STM32

    文章目录 一·、软件定时器的基本概念 二、软件定时器应用场景 三、软件定时器的精度 四、软件定时器的运作机制 五、软件定时器函数接口讲解 1.软件定时器创建函数 xTimerCreate() 2.软件定时器启动函数 xTimerStart()  3.软件定时器停止函数  xTimerStop()  4.软件定时器任务 5.软件

    2024年02月11日
    浏览(24)
  • 【杰理AC696X】软件定时器介绍

    测试SDK版本:《ac696n_soundbox_sdk_v1.6.0》 SDK给出了软件定时器的相关接口,主要有 sys_hi_timer_add、sys_s_hi_timer_add、sys_timer_add等。 列出AC696X系列软件定时器的相关知识点,再结合代码调试和工具测试,总结出使用案例。 上面的低功耗指的是 power down,不是soft poweroff。 usr_timer的强

    2024年02月10日
    浏览(19)
  • 鸿蒙Hi3861学习六-Huawei LiteOS(软件定时器)

            软件定时器,是 基于系统Tick时钟中断 且由 软件来模拟的定时器 。当经过设定的Tick时钟计数值后,会 触发用户定义的回调函数 。定时精度与系统Tick时钟周期有关。         硬件定时器受硬件的限制,数量上不足以满足用户的实际需求。因此,为了满足用户需求,

    2024年02月03日
    浏览(17)
  • 鸿蒙Hi3861学习六-Huawei LiteOS-M(软件定时器)

            软件定时器,是 基于系统Tick时钟中断 且由 软件来模拟的定时器 。当经过设定的Tick时钟计数值后,会 触发用户定义的回调函数 。定时精度与系统Tick时钟周期有关。         硬件定时器受硬件的限制,数量上不足以满足用户的实际需求。因此,为了满足用户需求,

    2024年02月05日
    浏览(21)
  • 自定义循环队列、软件定时器、事件集,实用嵌入式代码库

    本篇博文分享一个很实用的嵌入式代码库。 它可灵活应用到有无RTOS的程序中,采用C语言面向对象的思路实现各个功能,尽可能最大化的复用代码,目前为止工具包包含: 循环队列、软件定时器、事件集 。 网址:https://download.csdn.net/download/m0_38106923/87765476?spm=1001.2014.3001.550

    2024年02月03日
    浏览(21)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包