weixin_61846385 2024-03-12 10:48 采纳率: 83.3%
浏览 3
已结题

关于freertos和stm32

#freertos/stm32

if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0)
{
    vTaskDelay(20);
    if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0)
    {
        vTaskDelay(20);
     while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0);
        key_num=2;            
    }
}

任务中调用了,这样按键有时候能触发,有时候不能触发,有时候触发一次直接卡死

  • 写回答

3条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-03-12 10:48
    关注

    引自免费微信小程序:皆我百晓生

    在FreeRTOS环境下,STM32的GPIO按键处理需要考虑中断与任务同步的问题。上述代码片段通过轮询方式检测PB1引脚上的按键状态,这种实现方式可能导致按键响应不灵敏或系统卡死,原因有以下几点:

    1. 任务调度延迟vTaskDelay(20)设置了20个系统ticks的延时,但在实时操作系统中,其他更高优先级的任务可能抢占当前任务,导致按键事件未被及时捕获。

    2. 按键抖动:物理按键按下和释放时会有电气信号的抖动,直接在主循环中连续读取两次可能会错过有效电平变化,建议使用硬件滤波或者软件去抖动方法。

    3. 卡死问题while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == 0);这句代码会导致任务在按键一直按下的情况下阻塞,无法执行其他任何任务,从而导致系统“卡死”。

    为解决这些问题,推荐采用中断的方式来处理按键事件,同时配合信号量、事件组等机制进行任务间同步。以下是改进后的示例代码:

    #include "stm32fxxx_hal.h"
    #include "FreeRTOS.h"
    #include "task.h"
    #include "semphr.h"
    
    SemaphoreHandle_t xKeySemphr = NULL;
    
    void EXTI1_IRQHandler(void)
    {
        HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
        if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == 0)
        {
            BaseType_t xHigherPriorityTaskWoken = pdFALSE;
            xSemaphoreGiveFromISR(xKeySemphr, &xHigherPriorityTaskWoken);
            portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
        }
    }
    
    void vButtonTask(void *pvParameters)
    {
        for (;;)
        {
            xSemaphoreTake(xKeySemphr, portMAX_DELAY);
    
            // 按键按下后的工作
            key_num = 2;
    
            // 延迟或其他操作...
        }
    }
    
    int main(void)
    {
        // 初始化HAL库、FreeRTOS及GPIO
        HAL_Init();
        SystemClock_Config();
        MX_GPIO_Init();
    
        // 创建信号量
        xKeySemphr = xSemaphoreCreateBinary();
    
        // 设置EXTI中断线,关联到GPIO_PIN_1
        HAL_NVIC_SetPriority(EXTI1_IRQn, 5, 0);
        HAL_NVIC_EnableIRQ(EXTI1_IRQn);
        HAL_GPIO_EXTI_Callback(GPIO_PIN_1, EXTI1_IRQHandler);
    
        // 创建并启动按键处理任务
        xTaskCreate(vButtonTask, "ButtonTask", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
    
        vTaskStartScheduler();
    
        while (1);
    }
    

    这段代码首先创建了一个二值信号量(Semaphore)用于按键事件通知,然后在EXTI中断服务程序中,当检测到PB1引脚按键按下时,给予信号量,并触发任务切换。在按键处理任务中,通过等待信号量来获取按键事件,这样即使按键长时间按下也不会导致任务阻塞和系统卡死。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 3月20日
  • 已采纳回答 3月12日
  • 创建了问题 3月12日

悬赏问题

  • ¥15 comsol仿真压阻传感器
  • ¥15 Python线性规划函数optimize.linprog求解为整数
  • ¥15 llama3中文版微调
  • ¥15 时间序列预测算法 预测结果出现负值
  • ¥15 在win系统Django虚拟环境下载mysqlclient报错
  • ¥15 pg数据库导入数据序列重复
  • ¥15 三分类机器学习模型可视化分析
  • ¥15 本地测试网站127.0.0.1 已拒绝连接,如何解决?(标签-ubuntu)
  • ¥50 Qt在release捕获异常并跟踪堆栈(有Demo,跑一下环境再回答)
  • ¥30 python,LLM 文本提炼