You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Nucleo开发板的RGB混色:party_sequence函数按键控制异常问题

问题分析

你遇到的核心问题是party_sequence函数里的while(1)死循环会独占CPU,一旦进入这个函数,主循环的按键检测代码就完全无法执行。所以松开按键时,case BUTTON_PRESSED里的关闭LED、重置模式逻辑永远不会被触发,导致party模式停不下来。

解决方案

1. 添加全局控制变量

在color_sequence定义下方新增静态变量,用来控制party模式的运行状态和当前步骤:

static enum button_state_e button_state = BUTTON_NOT_PRESSED;
static uint8_t color_sequence = 0;
static uint8_t run_party = 0;  // 控制party序列是否运行
static int party_step = 0;     // 记录party序列的当前执行步骤

2. 重构party序列函数(改为非阻塞)

把原来的死循环函数拆成单次执行一步的函数,避免占用CPU:

void party_step_run(void) {
    // 设置当前步骤的RGB颜色
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, sins[party_step]); // Red
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, sins[(party_step + 120) % 360]); // Green
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, sins[(party_step + 240) % 360]); // Blue

    // 更新步骤,循环回到起点
    party_step = (party_step + 1) % 360;
}

3. 修改按键处理逻辑

调整case9的触发逻辑

当切换到case9时,只设置运行标志位,不再调用死循环函数:

case 9:
    run_party = 1;
    party_step = 0;  // 重置序列到起始步骤
    break;

调整松开按键的处理逻辑

松开按键时,关闭LED、停止party模式,并重置color_sequence到0:

case BUTTON_PRESSED:
    if (!pressed)
    {
        button_state = BUTTON_NOT_PRESSED;
        switch_off_all_leds();
        run_party = 0;       // 停止party序列运行
        color_sequence = 0;  // 重置到case0模式
    }
    break;

4. 在主循环中执行party序列

在按键处理代码之后,添加逻辑检测run_party标志,开启时执行party步骤:

while (1)
{
    bool pressed = (HAL_GPIO_ReadPin(Toggle_Switch_GPIO_Port, Toggle_Switch_Pin) == GPIO_PIN_SET);

    // 原按键状态处理代码(保留不动)
    switch (button_state)
    {
        // ... 原代码全部保留
    }

    // 新增:执行party序列(如果开启)
    if (run_party) {
        party_step_run();
        HAL_Delay(2);  // 和原party序列的延时保持一致
    }

    HAL_Delay(10);
}

关键修改后的完整代码片段

// 变量定义
static enum button_state_e button_state = BUTTON_NOT_PRESSED;
static uint8_t color_sequence = 0;
static uint8_t run_party = 0;
static int party_step = 0;

// 非阻塞party步骤函数
void party_step_run(void) {
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, sins[party_step]);
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, sins[(party_step + 120) % 360]);
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, sins[(party_step + 240) % 360]);
    party_step = (party_step + 1) % 360;
}

// 主循环中的case9处理
case 9:
    run_party = 1;
    party_step = 0;
    break;

// 松开按键的处理
case BUTTON_PRESSED:
    if (!pressed)
    {
        button_state = BUTTON_NOT_PRESSED;
        switch_off_all_leds();
        run_party = 0;
        color_sequence = 0;
    }
    break;

// 主循环末尾的party执行逻辑
if (run_party) {
    party_step_run();
    HAL_Delay(2);
}

逻辑说明

  • 拆分party序列为单次步骤执行,让主循环能持续检测按键状态,避免CPU被独占。
  • 通过run_party标志位控制序列启停,松开按键时直接清除标志即可停止。
  • 重置color_sequence到0,确保下次按下按键从case0的红色模式开始。

内容的提问来源于stack exchange,提问作者Mendi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 19:12:02