STM32之freeRTOS的使用基本方法
freeRTOS打开方法middleware and software, interface:CMSIS V2. 打开以后修改HAL时基避免HAL与freeRTOS抢sysTick随便选一个不用的就可以。可以看到TIM10已经变成不可用状态配置都是灰色的TASK建立打开Tasks and Queues点击add参数含义你该怎么填Task Name任务名字自己起名比如motor_xm_ol、oledTask、adcTask。建议用英文、数字、下划线Priority任务优先级决定谁先运行。优先级高的任务会抢占优先级低的任务Stack Size (Words)任务栈大小单位是wordSTM32 是 32 位 MCU1 word 4 字节所以 128 words 512 字节Entry Function任务入口函数名这个任务真正执行的函数比如StartTask02Code Generation Option代码生成方式一般保持Default就行Parameter传给任务函数的参数不需要传参就填NULLAllocation任务内存分配方式Dynamic动态分配简单方便Static静态分配更可控Buffer Name静态分配时用的栈缓冲区名只有Allocation Static时才需要Control Block Name静态分配时用的任务控制块名只有Allocation Static时才需要在Core/Src/目录下的freertos.c文件里面可以看到我在cubeMX里面添加的几个任务条件触发TASK的编写在当前项目中我计划是一些按键对应一个task另一些按键对应另一个task。也就是需要flag来标记单个任务中的不同程序。其中一个task是通过按键触发电机的手动移动思路是按键按下对应移动方向的按键以后在中断回调函数里面修改标志位任务监测到标志位变化后执行task内相对应的代码。目前的移动方向有四个在freertos.c这里添加代码/* USER CODE END Header_move_manualT */ void move_manualT(void *argument) { /* USER CODE BEGIN move_manualT */ uint32_t flags; /* Infinite loop */ for(;;) { flags osThreadFlagsWait( FLAG_XM | FLAG_XP | FLAG_YM | FLAG_YP, osFlagsWaitAny, osWaitForever ); if (flags FLAG_XM) { motor_move_XM_OL(1000); } if (flags FLAG_XP) { motor_move_XP_OL(1000); } if (flags FLAG_YM) { motor_move_YM_OL(1000); } if (flags FLAG_YP) { motor_move_YP_OL(1000); } } /* USER CODE END move_manualT */ }然后在main.c里面写按键的中断回调函数/* USER CODE BEGIN 4 */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { static uint32_t last_tick 0; uint32_t now HAL_GetTick(); if (now - last_tick 20) return; last_tick now; if (GPIO_Pin GPIO_PIN_15) { //X- osThreadFlagsSet(move_manualHandle, FLAG_XM); } else if (GPIO_Pin GPIO_PIN_10) { //X osThreadFlagsSet(move_manualHandle, FLAG_XP); } else if (GPIO_Pin GPIO_PIN_11) { //Y- osThreadFlagsSet(move_manualHandle, FLAG_YM); } else if (GPIO_Pin GPIO_PIN_12) { //Y osThreadFlagsSet(move_manualHandle, FLAG_YP); } else if (GPIO_Pin GPIO_PIN_13) { //Z } else if (GPIO_Pin GPIO_PIN_13) { //Z- } };另外标志位是两个c文件都要读取的我们另开一个flags.h文件并在main.c和freertos.c里面都include它#ifndef _FLAGS_H_ #define _FLAGS_H_ #define FLAG_XM (1U 0) #define FLAG_XP (1U 1) #define FLAG_YM (1U 2) #define FLAG_YP (1U 3) #endifmain.c里面的osThreadFlagsSet函数中的的第一个参数 是freertos.c里面task的句柄同样需要另外建立一个user_freertos.h文件来重新声明一下这些句柄加上extern。#ifndef __APP_FREERTOS_H #define __APP_FREERTOS_H #include cmsis_os.h extern osThreadId_t oled_dispHandle; extern osThreadId_t move_manualHandle; extern osThreadId_t move_autoHandle; extern osThreadId_t ESPtransferHandle; extern osThreadId_t USBtransferHandle; #endif互斥任务的设置在当前的应用场景中手动控制电机移动的任务和自动控制电机按程序移动的任务是分开的。另外USB和ESP8266读写SPI flash的程序也是分开的。因此需要对这几个task做互斥。首先在cubeMX里面的freertos-mutexes 点击add参数先选dynamic。生成代码以后进入freertos.c文件可以看到生成了一个新的句柄/* Definitions for motor_mutex */ osMutexId_t motor_mutexHandle; const osMutexAttr_t motor_mutex_attributes { .name motor_mutex };函数结构如下void StartTask1(void *argument) { for (;;) { osThreadFlagsWait(FLAG_TASK1, osFlagsWaitAny, osWaitForever); osMutexAcquire(allMotorMutexHandle, osWaitForever); Task1_Function(); osMutexRelease(allMotorMutexHandle); } }可以看到增加了两个函数这俩函数就是互斥锁第一个函数是用来上锁第二个函数用来解锁。

相关新闻