基于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
相关产品推荐
相关产品推荐

