嵌入式C编程:IF语句功能异常问题排查
Arduino Mega按键控制LED功能修复
问题说明
需求如下:
- 按住PORTK PK1(Switch1)后,每按一次PORTK PK0(Switch2),Port F的0-3号LED依次点亮
- 先按两次Switch2,再按住Switch1时,每按一次Switch2,Port F的4-7号LED依次点亮
当前仅第一种功能正常,第二种逻辑完全无法触发。
原代码问题分析
- 状态记录缺失:代码完全没有记录“先按两次Switch2”这个前置操作的状态,根本无法触发第二种逻辑
- 无效判断逻辑:
j变量仅在按住Switch1时被设为1,j/2结果为0(整数除法),导致第一个if块永远不会执行;j%2结果为1,重复处理第一种情况,完全没涉及第二种功能 - 阻塞式消抖:用
for循环延时做消抖,会阻塞程序运行,导致按键状态检测不及时,甚至错过按键事件 - 逻辑结构混乱:重复的LED控制代码,没有区分不同触发条件的分支
修正后的代码
void setup() { DDRF = 0xFF; // Port F设为输出(控制LED) DDRK = 0x00; // Port K设为输入(读取按键) PORTK = 0x03; // 给PK0、PK1引脚配置内部上拉电阻,按键接地时触发 // 状态变量定义 static uint8_t switch2_count = 0; // 记录Switch2的独立按下次数 static uint8_t led_state_low = 0; // F0-F3的LED循环状态 static uint8_t led_state_high = 0; // F4-F7的LED循环状态 static bool switch1_prev = HIGH; // Switch1上一次状态 static bool switch2_prev = HIGH; // Switch2上一次状态 const unsigned long debounce_time = 50;// 消抖延时50ms unsigned long last_switch1_time = 0; // Switch1最后触发时间 unsigned long last_switch2_time = 0; // Switch2最后触发时间 while (1) { unsigned long current_time = millis(); // 读取当前按键状态(低电平表示按下) bool switch1_curr = (PINK & 0x02) == 0x00; bool switch2_curr = (PINK & 0x01) == 0x00; // 处理Switch1未按住时的Switch2计数 if (!switch1_curr) { if (switch2_curr != switch2_prev && current_time - last_switch2_time > debounce_time) { last_switch2_time = current_time; switch2_prev = switch2_curr; if (switch2_curr) { // 按键按下时计数,超过2次重置 switch2_count++; switch2_count = switch2_count > 2 ? 0 : switch2_count; } } } // 处理Switch1的消抖 if (switch1_curr != switch1_prev && current_time - last_switch1_time > debounce_time) { last_switch1_time = current_time; switch1_prev = switch1_curr; } // 处理按住Switch1时的LED控制 if (switch1_curr) { if (switch2_curr != switch2_prev && current_time - last_switch2_time > debounce_time) { last_switch2_time = current_time; switch2_prev = switch2_curr; if (switch2_curr) { if (switch2_count == 2) { // 前置按过两次Switch2,控制F4-F7 led_state_high++; led_state_high = led_state_high > 4 ? 1 : led_state_high; PORTF = (1 << (led_state_high + 3)); // 映射到F4-F7引脚 } else { // 控制F0-F3 led_state_low++; led_state_low = led_state_low > 4 ? 1 : led_state_low; PORTF = (1 << (led_state_low - 1)); // 映射到F0-F3引脚 } } } } } } void loop() { // 空loop,逻辑已在setup的while循环中实现 }
修正要点
- 增加状态记录:用
switch2_count记录Switch2的独立按下次数,作为第二种LED逻辑的触发条件 - 非阻塞消抖:用
millis()实现消抖,避免阻塞程序,保证按键检测的灵敏性 - 清晰分支逻辑:拆分“Switch1未按住时的计数”和“Switch1按住时的LED控制”两个独立逻辑分支
- 硬件适配:配置引脚内部上拉电阻,简化按键接线(按键一端接引脚,另一端接地)
- 状态循环重置:LED状态计数超过上限时自动重置,保证LED循环点亮
内容的提问来源于stack exchange,提问作者Iyyappan Chithambarathanu
相关产品推荐
相关产品推荐

