公司动态

freertos学习记录(7)

📅 2026/8/20 12:12:16
freertos学习记录(7)
6.1 二进制信号量补充一下上次学习中对TCB的理解TCB Task Control Block任务控制块它就是 FreeRTOS 里用来描述、管理一个任务的数据结构体。核心作用内核靠 TCB 保存一个任务的全部信息任务切换时就是在操作 TCB任务栈地址 / 栈顶pxTopOfStack最关键上下文保存到这里任务状态就绪 / 阻塞 / 挂起 / 运行任务优先级任务句柄、任务名称阻塞延时时间、事件等待标记栈溢出检测相关信息编写上述代码完成实验首先对引脚进行初始化配置完毕后先写出代码里需要的print方法。// //通过串口打印字符串 // static void print(const char* str) { vTaskSuspendALL();//暂停调度器 HAL_UART_Transmit(huart1,(const uint8_t*)str,strlen(str),HAL_MAX_DELAY); vTaskResumeALL();//恢复调度器 }还需要写按钮检测代码static void vButtonTask(void *pvParameters) { GPIO_PinState current,previousGPIO_PIN_SET; for(;;) { currentHAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin); if(currentGPIO_PIN_SET previousGPIO_PIN_RESET) { xSemaphoreGive(xFireSemphr); } previous current; vTaskDelay(pdMS_TO_TICKS(10)); } }把等待时间用上这个程序里改成5s没按下就发射失败了。2.1 按钮音效编程实现按下按钮蜂鸣器鸣叫的效果。首先来看不使用信号量的情况。蜂鸣器鸣叫期间会让按钮失效分成两个任务不会让鸣叫任务影响按钮操作。如图是蜂鸣器的电路图需要把引脚设置成推挽输出。创建两个文件buzzer_task.h#ifndef TASK_BUZZER_TASK_H_ #define TASK_BUZZER_TASK_H_ void Buzzer_Init(); void vBuzzerTask(void *pvParameters); void Buzzer_Beep(); #endif /* TASK_BUZZER_TASK_H_ */buzzer_task.c#include FreeRTOS.h #include buzzer_task.h #include semphr.h #include main.h static SemaphoreHandle_t xBuzzerSemphr; void Buzzer_Init() { xBuzzerSemphrxSemaphoreCreateBinary(); } void vBuzzerTask(void *pvParameters) { for(;;) { xSemaphoreTake(xBuzzerSemphr,portMAX_DELAY); HAL_GPIO_WritePin(BUZZER_GPIO_Port,BUZZER_Pin,GPIO_PIN_SET);//开始鸣叫 vTaskDelay(pdMS_TO_TICKS(100)); HAL_GPIO_WritePin(BUZZER_GPIO_Port,BUZZER_Pin,GPIO_PIN_RESET);//停止鸣叫 } } void Buzzer_Beep() { xSemaphoreGive(xBuzzerSemphr); }并且把给信号的函数放在key1的回调函数里面static void KEY1_ClickedCallback(void) { Buzzer_Beep(); }在main.c里面调用相关函数和创建相关函数Buzzer_Init(); xTaskCreate(KeyTask,key1Task,128,NULL,3,NULL); xTaskCreate(vBuzzerTask,BuzzerTask,32,NULL,1,NULL); vTaskStartScheduler();这样就实现了按下6个按钮蜂鸣器都会鸣叫的现象了。6.2 在中断里使用二进制信号量用中断方式需要进行校抖操作具体代码如上。注图上的判断条件应该是GPIO_PIN_9。编写完代码后烧录实验现象是当按下按钮后蜂鸣器确实会鸣叫5下但是在鸣叫的过程中LED1停止闪烁和我们预期的实验现象是不一样的。中断任务会打断非中断任务所以我们需要让中断任务执行尽可能短。除了上面的代码还需要写下面的代码#include semphr.h SemaphoreHandle_t xBuzzerSemphr NULL;我自己写的时候经常漏掉导致报错。实验结果仍旧是在按下按钮后小灯的闪烁暂停了进入调试模式查找原因。void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { uint32_t nowHAL_GetTick(); BaseType_t xHigherPriorityTaskWoken pdFALSE; if((GPIO_PinGPIO_PIN_9) (now-key1DebounceTime10)) { // xSemaphoreGive(xBuzzerSemphr); xSemaphoreGiveFromISR(xBuzzerSemphr,xHigherPriorityTaskWoken); } key1DebounceTimenow; portYIELD_FROM_ISR(xHigherPriorityTaskWoken); }改造之后还是卡死了。我们当前使用的EXTI9_5默认优先级是0当然会报错。把中断优先级配置成5处于临界位置。之后实验正常蜂鸣器鸣叫期间不打断小灯闪烁。