STM32F1与STM32CubeIDE编程实例-CMSIS-RTOS V2-定时器管理 定时器管理 CMSIS-RTOS v2 (CMSIS-RTOS2) 为基于 Arm® Cortex® 处理器的设备提供通用 RTOS 接口。 它为需要 RTOS 功能的软件组件提供标准化 API,从而为用户和软件行业带来巨大的好处。
本文将详细介绍,在CMSIS-RTOS V2中如何使用定时器。
1、CMSIS-RTOS V2定时器介绍 除了通用延时函数 之外,CMSIS-RTOS 还支持虚拟定时器对象。 这些定时器对象可以触发函数(不是线程)的执行。 当定时器到期时,将执行回调函数以运行与定时器相关的代码。 每个定时器都可以配置为一次性或周期性定时器。 周期性定时器重复其操作,直到它被删除或停止。 所有定时器都可以启动、重新启动或停止。
1 2 3 4 注意: 1)、RTX 在线程 osRtxTimerThread 中处理定时器。 回调函数在此线程的控制下运行,并且可能使用其他 CMSIS-RTOS API 调用。 osRtxTimerThread 在 Timer Configuration 中配置。 2)、定时器管理函数不能从中断服务程序中调用。
下图显示了周期性定时器的行为。 对于一次性定时器,定时器在回调函数执行后停止。
CMSIS-RTOS V2对定时器管理提供了如下函数:
osTimerId_t osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr):
函数 osTimerNew 创建一次性或周期性定时器,并将其与带有参数的回调函数相关联。 定时器在使用 osTimerStart 启动之前处于停止状态。 该函数可以在 RTOS 启动之前安全调用(调用 osKernelStart),但不能在初始化之前调用(调用 osKernelInitialize)。
函数 osTimerNew 返回指向定时器对象标识符的指针,如果发生错误,则返回 NULL。
其参数说明如下:
+ func: 函数指向回调函数的指针。
+ osTimerOnce: 用于一次性或 osTimerPeriodic 用于周期性行为。
+ argument:定时器回调函数的参数。
+ attr: 定时器属性; NULL:默认值。`注意:不能从中断服务程序调用此函数`
简单示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include "cmsis\_os2.h" void Timer1\_Callback (void \*arg); // prototypes for timer callback function void Timer2\_Callback (void \*arg); // prototypes for timer callback function uint32\_t exec1; // argument for the timer call back function uint32\_t exec2; // argument for the timer call back function void TimerCreate\_example (void) { osTimerId\_t id1; // timer id osTimerId\_t id2; // timer id // Create one-shoot timer exec1 = 1U; id1 = osTimerNew(Timer1_Callback, osTimerOnce, &exec1, NULL); if (id1 != NULL) { // One-shoot timer created } // Create periodic timer exec2 = 2U; id2 = osTimerNew(Timer2_Callback, osTimerPeriodic, &exec2, NULL); if (id2 != NULL) { // Periodic timer created } : }
**const char * osTimerGetName (osTimerId_t timer_id)**:返回定时器名称
**osStatus_t osTimerStart (osTimerId_t timer_id, uint32_t ticks)**:启动或重新启动由参数 timer_id 指定的计时器。 参数 ticks 以时间刻度指定计时器的值。可能的 osStatus_t 返回值:
osOK :指定的定时器已经启动或重启。
osErrorISR :无法从中断服务例程调用 osTimerStart。
osErrorParameter :参数 timer_id 为 NULL 或无效或刻度不正确。
osErrorResource :定时器处于无效状态。
简单示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include "cmsis\_os2.h" void Timer\_Callback (void \*arg) { // timer callback function // arg contains &exec // called every second after osTimerStart } uint32\_t exec; // argument for the timer call back function void TimerStart\_example (void) { osTimerId\_t id; // timer id uint32\_t timerDelay; // timer value osStatus\_t status; // function return status // Create periodic timer exec = 1U; id = osTimerNew(Timer_Callback, osTimerPeriodic, &exec, NULL); if (id != NULL) { timerDelay = 1000U; status = osTimerStart(id, timerDelay); // start timer if (status != osOK) { // Timer could not be started } } ; }
简单示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include "cmsis\_os2.h" void Timer\_Callback (void \*arg); // prototype for timer callback function uint32\_t exec; // argument for the timer call back function void TimerStop\_example (void) { osTimerId\_t id; // timer id osStatus\_t status; // function return status // Create periodic timer exec = 1U; id = osTimerNew(Timer_Callback, osTimerPeriodic, &exec, NULL); osTimerStart(id, 1000U); // start timer : status = osTimerStop(id); // stop timer if (status != osOK) { // Timer could not be stopped } ; osTimerStart(id, 1000U); // start timer again ; }
**uint32_t osTimerIsRunning (osTimerId_t timer_id)**:检查参数 timer_id 指定的定时器是否正在运行。 如果计时器正在运行,则返回 1,如果计时器停止或发生错误,则返回 0。
**osStatus_t osTimerDelete (osTimerId_t timer_id)**:删除由参数 timer_id 指定的定时器。可能的 osStatus_t 返回值:
osOK :指定的定时器已被删除。
osErrorISR :无法从中断服务例程调用 osTimerDelete。
osErrorParameter :参数 timer_id 为 NULL 或无效。
osErrorResource :定时器处于无效状态。注意:不能从中断服务程序调用此函数
简单示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include "cmsis\_os2.h" void Timer\_Callback (void \*arg); // prototype for timer callback function uint32\_t exec; // argument for the timer call back function void TimerDelete\_example (void) { osTimerId\_t id; // timer id osStatus\_t status; // function return status // Create periodic timer exec = 1U; id = osTimerNew(Timer_Callback, osTimerPeriodic, &exec, NULL); osTimerStart(id, 1000U); // start timer ; status = osTimerDelete(id); // stop and delete timer if (status != osOK) { // Timer could not be deleted } ; }
2、在STM32CubeIDE中配置定时器 第一步: 新建工程
新建工程,请参考前面文章:
串口配置,请参考前面文章:
第二步: 配置时钟
配置时钟,请参考前面文章:
第三步:配置FreeRTOS
配置FreeRTOS,及FreeRTOS的堆栈,请参考:
第四步:添加定时器
可根据需求填写Timer Name 、Callback 等。
定义了两个定时器,一个是osTimerPeriodic,一处是osTimerOnce。
第五步:保存生成代码
3、定时器回调代码实现 在main.c文件的main函数中,RTOS启动调用如下:
1 2 3 4 5 6 7 /\* Init scheduler \*/ osKernelInitialize(); /\* Call init function for freertos objects (in freertos.c) \*/ MX\_FREERTOS\_Init(); /\* Start scheduler \*/ osKernelStart();
在freertos.c文件中,生成定义的定时器如下:
1 2 3 4 5 6 7 8 9 10 11 /\* Definitions for ledBlink \*/ osTimerId\_t ledBlinkHandle; const osTimerAttr\_t ledBlink_attributes = { .name = "ledBlink" }; /\* Definitions for ledOn \*/ osTimerId\_t ledOnHandle; const osTimerAttr\_t ledOn_attributes = { .name = "ledOn" };
在freertos.c文件中,生成定义的定时器回调函数如下:
1 2 3 void ledBlinkTask(void \*argument); void ledOnCallback(void \*argument);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 /\* ledBlinkTask function \*/ void ledBlinkTask(void \*argument) { /\* USER CODE BEGIN ledBlinkTask \*/ /\* USER CODE END ledBlinkTask \*/ } /\* ledOnCallback function \*/ void ledOnCallback(void \*argument) { /\* USER CODE BEGIN ledOnCallback \*/ /\* USER CODE END ledOnCallback \*/ }
在MX_FREERTOS_Init函数中启动定时器:
1 2 3 4 5 6 7 /\* Create the timer(s) \*/ /\* creation of ledBlink \*/ ledBlinkHandle = osTimerNew(ledBlinkTask, osTimerPeriodic, NULL, &ledBlink_attributes); /\* creation of ledOn \*/ ledOnHandle = osTimerNew(ledOnCallback, osTimerOnce, NULL, &ledOn_attributes);
STM32CubeIDE帮助我们生成了整个与定时器管理相关的脚手加代码,接下来,只需要在定时器回调函数中实现需要的功能即可。
比如,定义的定时器回调函数中,实现的功能如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 /\* ledBlinkTask function \*/ void ledBlinkTask(void \*argument) { /\* USER CODE BEGIN ledBlinkTask \*/ printf("led blink\r\n"); HAL\_GPIO\_TogglePin(LED2_GPIO_Port, LED2_Pin); /\* USER CODE END ledBlinkTask \*/ } /\* ledOnCallback function \*/ void ledOnCallback(void \*argument) { /\* USER CODE BEGIN ledOnCallback \*/ printf("-------------led on-----------\r\n"); HAL\_GPIO\_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET); /\* USER CODE END ledOnCallback \*/ }
在ledBlinkTask和ledOnCallback函数中,分别对LED进行点亮、关闭操作和点亮操作。关于GPIO的设置,请参考:
最后编译生成固件并下载到开发板中。
4、STM32F1与STM32CubeIDE快速入门系列文章
文章来源: https://iotsmart.blog.csdn.net/article/details/124645963
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!