2. RTOS任务创建与调度观察
任务定义
本案例在STM32F103开发板上,基于FreeRTOS创建两个独立任务:任务A控制LED以500ms周期闪烁,任务B控制蜂鸣器以200ms周期鸣响。通过观察两个任务互不阻塞地交替运行,验证RTOS多任务并发调度机制。
硬件连接
代码实现
// main.c
#include "stm32f1xx_hal.h"
#include "cmsis_os.h"
// 引脚定义
#define LED_PIN GPIO_PIN_1
#define LED_PORT GPIOA
#define BUZZER_PIN GPIO_PIN_2
#define BUZZER_PORT GPIOA
// 任务句柄
osThreadId_t taskAHandle;
osThreadId_t taskBHandle;
// 任务函数声明
void TaskA_LED(void *argument);
void TaskB_Buzzer(void *argument);
// 任务属性定义
const osThreadAttr_t taskA_attr = {
.name = "TaskA_LED",
.stack_size = 128 * 4,
.priority = osPriorityNormal,
};
const osThreadAttr_t taskB_attr = {
.name = "TaskB_Buzzer",
.stack_size = 128 * 4,
.priority = osPriorityNormal,
};
// 任务A:控制LED 500ms翻转
void TaskA_LED(void *argument) {
while (1) {
HAL_GPIO_TogglePin(LED_PORT, LED_PIN);
osDelay(500); // 500ms延时
}
}
// 任务B:控制蜂鸣器 200ms翻转
void TaskB_Buzzer(void *argument) {
while (1) {
HAL_GPIO_TogglePin(BUZZER_PORT, BUZZER_PIN);
osDelay(200); // 200ms延时
}
}
// GPIO初始化
static void GPIO_Init(void) {
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = LED_PIN | BUZZER_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
// 主函数
int main(void) {
HAL_Init();
GPIO_Init();
// 初始化RTOS内核
osKernelInitialize();
// 创建两个任务
taskAHandle = osThreadNew(TaskA_LED, NULL, &taskA_attr);
taskBHandle = osThreadNew(TaskB_Buzzer, NULL, &taskB_attr);
// 启动调度器
osKernelStart();
while (1) {
// 不会执行到这里
}
}
工程配置说明
本案例基于STM32CubeMX生成的FreeRTOS工程,需在CubeMX中完成以下配置:
- 启用FreeRTOS CMSIS_V1接口(或V2,代码兼容)
- 将PA1、PA2配置为GPIO输出
- 时钟配置为72MHz主频
- 堆栈大小:每个任务分配128字(512字节)
验证方法
运行与观察:
- 编译并烧录程序到STM32F103开发板
- 上电后观察LED和蜂鸣器行为
判定标准:
- LED以约500ms周期闪烁(亮250ms,灭250ms)
- 蜂鸣器以约200ms周期鸣响(响100ms,停100ms)
- 两个任务互不阻塞,LED闪烁频率不受蜂鸣器影响,反之亦然
- 若LED和蜂鸣器各自按预期频率工作且互不干扰,则判定多任务并发执行成功
预期输出:由于两个任务独立运行,LED和蜂鸣器各自按照自己的延时参数翻转GPIO,观察到的现象是LED慢速闪烁、蜂鸣器快速鸣响,两者同时进行且节奏独立。