一、STM32cubeMX中相关配置
( 首先我用的STM32板子是STM32F103VBT6,板子不同,配置会略有不同,仅作参考!)
打开STM32cubeMX,新建工程,选择对应板子型号:
1.配置微控制器的时钟系统
High Speed Clock (HSE): 高速时钟源,这里选择的是“Crystal/Ceramic Resonator”,意味着使用外部晶体或陶瓷谐振器作为时钟源。
2.配置SYS
在STM32CubeMX中选择“Serial Wire”作为调试模式,意味着在生成的初始化代码中,将配置微控制器以使用SW模式进行调试。
其中,Timebase Source不能为SysTick,如果配置了SysTick,生成代码时会出现警告如下:
在FreeRTOS中使用时钟基准时,通常使用SysTick定时器作为系统时钟源(也称为Tick定时器),而不是使用其他硬件定时器。所以我们需要用其它定时器作为时间基准。
这个警告的意思是,如果你的系统中使用了RTOS,那么使用Systick作为时间基准可能不是最佳选择,因为它可能会与RTOS的调度器冲突。建议使用其他的定时器作为HAL的时间基准源,以避免潜在的问题。
3.配置时钟
上面只需设置两个地方就行,其它的STm32cubeMX会自动为你配置
1.
设置为12MHz,这要看我们的STM32板子上的外部晶振是多少,由于我的STM32上外部晶振是12MHz,所以设置为12。
这里就看自己需求了,我一般设置为72。
4.配置FreeRTOS
在左边的Middleware中
选择CMSIS_V1(该选项有Disable,CMSIS_V1和CMSIS_V2)
CMSIS(Cortex Microcontroller Software Interface Standard)是由ARM公司发布的一个标准,旨在为Cortex-M微控制器提供统一的软件接口。CMSIS-RTOS是CMSIS的一部分,它定义了RTOS接口的标准化规范,使得不同的RTOS实现(如RTX、FreeRTOS等)能够通过一致的API进行操作。
下面有FreeRTOS的Configuration的配置,作为小白默认就好
不过我们根据项目需要添加Task和Queue
在STM32CubeMX中配置FreeRTOS时,Task和Queue是两个重要的概念,它们是FreeRTOS中的核心元素,分别用于任务管理和任务间的通信
我们基于FreeRTOS完成两个任务来测试一下
1.Led闪烁
2.串口通信:向电脑发送“hello!world”
所以添加两个任务:
点击Add添加任务,会弹出如下配置,默认点击ok即可:
(其中,Entry Function是任务函数的名称)
我这里已经添加了两个任务myTask02和meTask03,这个defaultTask是STM32cubeMx为你生成的一个任务。
GPIO配置:
其中,对于STM32F103VBT6,需要将PB3设置为1,才能让Led灯亮
配置USART1:选择异步通信
5.生成文件
然后对工程文件命名,选择IDE为:MDK-ARM,J_Link版本为V5等等
最后,生成代码。
二、在Keil5中编写测试代码
打开生成的keil5文件,可以看到有文件结构如下:
第一件事是:先进行编译,看看是否编译成功。
如果编译失败,那么应该是STM32cubeMX配置出现了问题;如果编译成功就接着往下看:
在freertos.c文件中可以看到创建任务的初始化函数
里面创建了在cubeMX添加的任务:
而在freertos.c文件下面还有这些任务的定义,我们可以自己编写需要执行的功能代码:
所以为了实现一下功能,只需要在我创建的两个任务里分别实现就行
每隔一秒闪烁:
void StartTask03(void const * argument)
{
/* USER CODE BEGIN StartTask03 */
/* Infinite loop */
while (1) {
// 假设A_Pin连接了LED
HAL_GPIO_WritePin(A_GPIO_Port, A_Pin, GPIO_PIN_SET); // 点亮LED
osDelay(1000); // 延时1秒
HAL_GPIO_WritePin(A_GPIO_Port, A_Pin, GPIO_PIN_RESET); // 熄灭LED
osDelay(1000); // 延时1秒
}
/* USER CODE END StartTask03 */
}
每间隔一秒向串口发送“hello!world”
char message[] = "hello! world";
void StartTask02(void const * argument)
{
/* USER CODE BEGIN StartTask02 */
/* Infinite loop */
for(;;)
{
HAL_UART_Transmit(&huart1, (uint8_t*)message, strlen(message), 1000);
osDelay(1000);
}
/* USER CODE END StartTask02 */
}
在main.c文件中可以看到,cubeMX已经自动为我们生成了FreeRTOS的初始化以及启动内核操作系统的代码:
可以看到osKernelStart()下面有一段注释.
意思是说,控制权已经交给了 FreeRTOS 调度器。在调度器开始运行后,程序应该进入任务执行状态,而不应该再返回到 main() 函数。
编译,下板进行验证即可。