你所遇到的問題的確可能是因為在執行 display_sos() 函數時,按鍵掃描沒有被及時處理,導致按第三下按鍵時,LED沒有熄滅。這個問題的根本原因是按鍵處理函數在 display_sos() 運行時沒有機會執行,因為你的代碼是單線程順序執行的。display_sos() 函數中包含了長時間的延時操作,導致在這段時間內程序不能響應按鍵的變化。
要解決這個問題,可以采用中斷處理或者使用一個狀態機來管理LED的狀態,而不是在 display_sos() 函數中使用阻塞延時。以下是使用狀態機的方法的簡化思路:
1. 移除阻塞的延時將阻塞延時改為非阻塞計數器方式,這樣主循環可以繼續檢查按鍵狀態。
2. 使用狀態機使用狀態機來管理LED的不同狀態(比如長亮、SOS、熄滅),并根據按鍵的狀態來切換。
代碼實現 #include <STC8.h>
#include <intrins.h>
sbit KEY = P3^5;
sbit LED = P3^4;
unsigned int LED_flag = 0;
unsigned int sos_step = 0;
unsigned int delay_counter = 0;
void Init_IO()
{
P0M1 = 0x00; P0M0 = 0x00;
P1M1 = 0x00; P1M0 = 0x00;
P2M1 = 0x00; P2M0 = 0x00;
P3M1 = 0x00; P3M0 = 0x00;
P4M1 = 0x00; P4M0 = 0x00;
P5M1 = 0x00; P5M0 = 0x00;
P6M1 = 0x00; P6M0 = 0x00;
P7M1 = 0x00; P7M0 = 0x00;
}
void Delay10ms()
{
unsigned char i, j, k;
i = 2; j = 56; k = 172;
do { do { while (--k); } while (--j); } while (--i);
}
void LED_SOS_Handler()
{
switch (sos_step)
{
case 0: case 2: case 4:
LED = 1; delay_counter = 20; sos_step++; break; // LED on for 200ms
case 1: case 3: case 5:
LED = 0; delay_counter = 20; sos_step++; break; // LED off for 200ms
case 6: case 8: case 10:
LED = 1; delay_counter = 50; sos_step++; break; // LED on for 500ms
case 7: case 9: case 11:
LED = 0; delay_counter = 50; sos_step++; break; // LED off for 500ms
case 12: case 14: case 16:
LED = 1; delay_counter = 20; sos_step++; break; // LED on for 200ms
case 13: case 15: case 17:
LED = 0; delay_counter = 20; sos_step++; break; // LED off for 200ms
case 18:
delay_counter = 200; sos_step = 0; LED_flag = 3; break; // Wait 2s, then turn off LED
}
}
void display()
{
if (LED_flag == 1)
{
LED = 1; // Turn on LED
}
else if (LED_flag == 2)
{
LED_SOS_Handler(); // Handle SOS signal
}
else if (LED_flag == 3)
{
LED = 0; // Turn off LED
}
}
void KeyScan()
{
if(KEY == 0)
{
Delay10ms();
if(KEY == 0)
{
LED_flag++;
if (LED_flag > 3) LED_flag = 0;
}
while (!KEY);
}
}
void main()
{
Init_IO();
LED = 0;
while (1)
{
KeyScan();
if (delay_counter > 0)
{
delay_counter--;
}
else
{
display();
}
}
}解釋:LED_SOS_Handler() 函數按步驟控制LED閃爍,實現SOS信號。
display() 函數根據 LED_flag 的值控制LED行為。
延時計數器 delay_counter 用于代替阻塞延時,讓主循環能繼續執行按鍵掃描。
這種設計能夠在處理LED行為的同時,繼續監控按鍵輸入,避免按鍵在特定情況下失效。