当前位置: 代码迷 >> 综合 >> stm32cube+freerots基础案例一:点灯
  详细解决方案

stm32cube+freerots基础案例一:点灯

热度:10   发布时间:2023-12-12 15:10:13.0

背景:

最近项目要在STM32L152上移植FreeRTOS轻量级系统,本文将从FreeRTOS的入门知识讲起,记录FreeRTOS的一些基本知识点和学习心得。

硬件平台:STM32F103C8T6

软件平台:keil v5和 cubeMx。

本文部分转载于一下博客,为了防止原博主文章后边找不到,所有特意自己也重新过了一边流程。
STM32+cubeMX+FreeRTOS学习(1)

内容:

1.FreeRTOS简介
在这里插入图片描述

FreeRTOS是一种轻量级实时操作系统。RTOS:Real Time OperatingSystem实时操作系统。FreeRTOS可拆分为Free + RTOS,前面Free代表一种操作系统类型的名称,后面RTOS代表实时操作系统。
近几年,FreeRTOS的排名在嵌入式操作系统的排名中还是比较高的,且有不断上升趋势。

2, cubeMX中FreeRTOS的生成及任务创建
首先,打开CUBEMX软件,点击NEW Project,选择芯片STM32F103C8。

在这里插入图片描述

2,配置RCC时钟
在这里插入图片描述
3,设置PB5和P6为GPIO_OUTPUT;
在这里插入图片描述
4,使能FREERTOS;
在这里插入图片描述

5,设置时钟树,本例外部晶振8M,8倍频,2分频,得到32M;
在这里插入图片描述

6,配置FREERTOS,创建两个任务;

在这里插入图片描述
在这里插入图片描述

7,生成基于Keil V5的代码。
在这里插入图片描述

8,添加LED点亮和熄灭程序;
在这里插入图片描述


void Func_LED1(void const * argument)
{
    /* USER CODE BEGIN Func_LED1 *//* Infinite loop */for(;;){
    osDelay(1000);HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5);}/* USER CODE END Func_LED1 */
}
void Func_LED2(void const * argument)
{
    /* USER CODE BEGIN Func_LED2 *//* Infinite loop */for(;;){
    osDelay(2000);HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_6);osDelay(1);}/* USER CODE END Func_LED2 */
}

编译运行,可以看到LED1和LED2 分别以不同的频率闪烁。

在这里插入图片描述

下面重点分析生成的代码:

下面分析MX_FREERTOS_Init()函数;

void MX_FREERTOS_Init(void)

{

osThreadDef(Task_LED1, Func_LED1, osPriorityNormal, 0, 128);//宏定义,定义了一个名为os_thread_def_Task_LED1的osThreadDef_t类型结构体,并赋值给各个成员变量。

Task_LED0Handle = osThreadCreate(osThread(Task_LED1), NULL);//创建了LED1任务

osThreadDef(Task_LED2, Func_LED2, osPriorityNormal, 0, 128);//宏定义,定义了一个名为os_thread_def_Task_LED2的osThreadDef_t类型结构体,并赋值给各个成员变量。
Task_LED1Handle = osThreadCreate(osThread(Task_LED2), NULL);//创建了LED2任务

}

go to definition of osThreadDef,该宏定义如下

#define osThreadDef(name, thread, priority, instances, stacksz)
const osThreadDef_t os_thread_def_##name =
{ #name, (thread), (priority), (instances), (stacksz)}
#endif

上诉宏定义中出现了##和# 符号,其中

##是一个连接符号,用于把参数连在一起;

#是“字符串化”的意思。出现在宏定义中的#是把跟在后面的参数转换成一个字符串。

例如:

#define paster( n ) printf( “token” #n" = %d\n ", token##n )

所以paster(9);就是相当于 printf(“token 9 = %d\n”,token9);

那么osThreadDef(Task_LED1, Func_LED1, osPriorityNormal, 0, 128);等价于下面的定义

#defineosThreadDef(Task_LED1, Func_LED1, osPriorityNormal, 0, 128)
const osThreadDef_t os_thread_def_Task_LED1 = { Task_LED1,Func_LED1,osPriorityNormal, 0, 128}
#endif

总结:

本例中的两个任务函数Func_LED1和Func_LED2,他们实际占用CPU的时间很少,在调用osDelay()函数之后,它们就进入阻塞状态了,它们在等待“定时时间到”事件。在用户任务都进入阻塞状态时,运行的是空闲任务。空闲任务是启动调度器时自动创建的。

在调试过程中,尝试把两个任务函数的osDelay都改成500后,观察现象是LED1和LED2同时同频率的闪烁,但这和FreeRTOS中的某一任意时刻,只会有一个任务在运行,不会有同时两个任务在运行的理论相悖。之后分析发现,在调用osDelay()函数之后,它们就进入阻塞状态了,当500ms到时,LED1先切换至运行态,之后LED2切换至运行态,然后进入组态等待下一个500ms。LED1运行和切换到LED2这个时间非常短,以至于表面上看lED1和LED2同时运行,实际上依然是2个任务在不停的切换。