找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 2098|回復(fù): 16
打印 上一主題 下一主題
收起左側(cè)

單片機(jī)不使用外部中斷,如何LED顯示程序?

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
我要實(shí)現(xiàn)的是按鍵按一下LED長(zhǎng)亮,第二下顯示SOS信號(hào),第三下LED熄滅,但是現(xiàn)在有時(shí)按第三下LED并不熄滅,我想是因?yàn)槲业腟OS顯示代碼沒(méi)有執(zhí)行完,所以按鍵掃描不到,請(qǐng)問(wèn)這個(gè)問(wèn)題如何解決呢。下面是我的代碼# include <STC8.h>
# include <intrins.h>
sbit KEY = P3^5;
sbit LED = P3^4;
unsigned int num=0;
unsigned int LED_flag=0;
void Delay10ms()                //@24.000MHz
{
        unsigned char data i, j, k;

        i = 2;
        j = 56;
        k = 172;
        do
        {
                do
                {
                        while (--k);
                } while (--j);
        } while (--i);
}
void Delay200ms(void)        //@24.000MHz
{
        unsigned char data i, j, k;

        _nop_();
        _nop_();
        i = 25;
        j = 90;
        k = 176;
        do
        {
                do
                {
                        while (--k);
                } while (--j);
        } while (--i);
}

void Delay500ms(void)        //@24.000MHz
{
        unsigned char data i, j, k;

        _nop_();
        _nop_();
        i = 61;
        j = 225;
        k = 62;
        do
        {
                do
                {
                        while (--k);
                } while (--j);
        } while (--i);
}
void Delay2000ms(void)        //@24.000MHz
{
        unsigned char data i, j, k;

        i = 244;
        j = 130;
        k = 4;
        do
        {
                do
                {
                        while (--k);
                } while (--j);
        } while (--i);
}

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 display_sos()
{
        LED = 1;            
        Delay200ms();
        LED = 0;            
        Delay200ms();
        LED = 1;            
        Delay200ms();
        LED = 0;            
        Delay200ms();
        LED = 1;            
        Delay200ms();
        LED = 0;            
        Delay200ms();

        LED = 1;            
  Delay500ms();
        LED = 0;            
  Delay500ms();
        LED = 1;            
  Delay500ms();
        LED = 0;           
  Delay500ms();
        LED = 1;            
  Delay500ms();
        LED = 0;            
  Delay500ms();

        LED = 1;            
        Delay200ms();
        LED = 0;            
        Delay200ms();
        LED = 1;           
        Delay200ms();
        LED = 0;            
        Delay200ms();
        LED = 1;            
        Delay200ms();
        LED = 0;            
        Delay200ms();
        
        Delay2000ms();
}
void display()
{
        if(LED_flag==0)
        {
                LED=0;
        }
        else if(LED_flag==1)
        {
                LED=1;
        }
        else if(LED_flag==2)
        {
                while(LED_flag==2)
                {
                        display_sos();
                }        
        }
        else if(LED_flag==3)
        {
                LED=0;
        }
}        
void KeyScan()
{
        if(KEY == 0)
        {
                Delay10ms();                        
                if(KEY == 0)
                {
                        LED_flag++;
                        display();
                        if(LED_flag==3)
                        {
                                LED_flag=0;
                        }                        
                }
                while(!KEY);                                
        }
}
void main()
{
  LED = 0;
        Init_IO();
        while(1)
        {
                KeyScan();               
        }
}


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

來(lái)自 2#
ID:633559 發(fā)表于 2024-8-10 08:58 | 只看該作者
/*
什么狀不狀態(tài)不態(tài),太遠(yuǎn)了。在你基礎(chǔ)上改了下,思路是沒(méi)問(wèn)題的,代碼還沒(méi)測(cè)試過(guò),你看看有沒(méi)有有沒(méi)有參考價(jià)值吧。
*/
sbit KEY = P3 ^ 5;
sbit LED = P3 ^ 4;
unsigned int num = 0;
unsigned int LED_flag = 0;
void Delay10ms()                //@24.000MHz
{
    unsigned char data i, j, k;

    i = 2;
    j = 56;
    k = 172;
    do
    {
        do
        {
            while (--k);
        }
        while (--j);
    }
    while (--i);
}

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 display_sos(unsigned char state)
{
    static unsigned int cnt = 0;
    if (state == 0)
    {
        cnt = 0;
    }
/*
下面其實(shí)可以寫的漂亮點(diǎn),用結(jié)構(gòu)體數(shù)組for循環(huán)處理
*/
    if (cnt < 540)
    {
        cnt++;
    }  
    if (cnt < 20)
    {
        LED = 1;
    }
    else if (cnt < 40)
    {
        LED = 0;
    }
    else if (cnt < 60)
    {
        LED = 1;
    }
    else if (cnt < 80)
    {
        LED = 0;
    }
    else if (cnt < 100)
    {
        LED = 1;
    }
    else if (cnt < 120)
    {
        LED = 0;
    }
   
    else if (cnt < 170)
    {
        LED = 1;
    }
    else if (cnt < 220)
    {
        LED = 0;
    }
    else if (cnt < 270)
    {
        LED = 1;
    }
    else if (cnt < 320)
    {
        LED = 0;
    }
    else if (cnt < 370)
    {
        LED = 1;
    }
    else if (cnt < 420)
    {
        LED = 0;
    }

    else if (cnt < 440)
    {
        LED = 1;
    }
    else if (cnt < 460)
    {
        LED = 0;
    }
    else if (cnt < 480)
    {
        LED = 1;
    }
    else if (cnt < 500)
    {
        LED = 0;
    }
    else if (cnt < 520)
    {
        LED = 1;
    }
    else if (cnt < 540)
    {
        LED = 0;
    }
}
void display()
{
    static unsigned char state = 0;
    if (LED_flag == 0)
    {
        LED = 0;
        state = 0;
    }
    else if (LED_flag == 1)
    {
        LED = 1;
        state = 0;
    }
    else if (LED_flag == 2)
    {
        display_sos(state);
        state = 1;
    }
    else if (LED_flag == 3)
    {
        LED = 0;
        state = 0;
    }
}

void KeyScan()
{
    static unsigned char last_key_state = 1;
    static unsigned char cnt = 0;   

    if (KEY != last_key_state)
    {
        if (++cnt >= 3)
        {
            if (last_key_state == 1)
            {
                if (++LED_flag >= 3)
                {
                    LED_flag = 0;
                }              
            }                        
            cnt = 0;
            last_key_state = KEY;
        }
    }
    else
    {
        cnt = 0;
    }
}
void main()
{
    LED = 0;
    Init_IO();
    while (1)
    {
        KeyScan();
        display();   
        Delay10ms();            
    }
}
回復(fù)

使用道具 舉報(bào)

板凳
ID:866313 發(fā)表于 2024-8-9 21:41 | 只看該作者
以下回答來(lái)自GPT-4o

  • 你所遇到的問(wèn)題的確可能是因?yàn)樵趫?zhí)行 display_sos() 函數(shù)時(shí),按鍵掃描沒(méi)有被及時(shí)處理,導(dǎo)致按第三下按鍵時(shí),LED沒(méi)有熄滅。這個(gè)問(wèn)題的根本原因是按鍵處理函數(shù)在 display_sos() 運(yùn)行時(shí)沒(méi)有機(jī)會(huì)執(zhí)行,因?yàn)槟愕拇a是單線程順序執(zhí)行的。display_sos() 函數(shù)中包含了長(zhǎng)時(shí)間的延時(shí)操作,導(dǎo)致在這段時(shí)間內(nèi)程序不能響應(yīng)按鍵的變化。
    要解決這個(gè)問(wèn)題,可以采用中斷處理或者使用一個(gè)狀態(tài)機(jī)來(lái)管理LED的狀態(tài),而不是在 display_sos() 函數(shù)中使用阻塞延時(shí)。以下是使用狀態(tài)機(jī)的方法的簡(jiǎn)化思路:
    1. 移除阻塞的延時(shí)
    將阻塞延時(shí)改為非阻塞計(jì)數(shù)器方式,這樣主循環(huán)可以繼續(xù)檢查按鍵狀態(tài)。
    2. 使用狀態(tài)機(jī)
    使用狀態(tài)機(jī)來(lái)管理LED的不同狀態(tài)(比如長(zhǎng)亮、SOS、熄滅),并根據(jù)按鍵的狀態(tài)來(lái)切換。
    代碼實(shí)現(xiàn) #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() 函數(shù)按步驟控制LED閃爍,實(shí)現(xiàn)SOS信號(hào)。
    • display() 函數(shù)根據(jù) LED_flag 的值控制LED行為。
    • 延時(shí)計(jì)數(shù)器 delay_counter 用于代替阻塞延時(shí),讓主循環(huán)能繼續(xù)執(zhí)行按鍵掃描。

    這種設(shè)計(jì)能夠在處理LED行為的同時(shí),繼續(xù)監(jiān)控按鍵輸入,避免按鍵在特定情況下失效。


回復(fù)

使用道具 舉報(bào)

地板
ID:1130376 發(fā)表于 2024-8-9 22:05 | 只看該作者
延時(shí)過(guò)多,這種造成單片機(jī)內(nèi)部資源消耗一直延時(shí)你的SOS信號(hào),這種沒(méi)什么太好的解決辦法,建議你學(xué)一下中斷函數(shù)吧
回復(fù)

使用道具 舉報(bào)

5#
ID:628113 發(fā)表于 2024-8-9 23:00 | 只看該作者
建議使用狀態(tài)機(jī)。
按鍵切換 狀態(tài)機(jī)的 狀態(tài), 然后 用狀態(tài)去驅(qū)動(dòng) 三個(gè)不同顯示函數(shù)。
這樣程序很清晰 , 模塊化 很強(qiáng) .
回復(fù)

使用道具 舉報(bào)

6#
ID:1012735 發(fā)表于 2024-8-9 23:11 | 只看該作者
死循環(huán)了:
        else if(LED_flag==2)
         {
                 while(LED_flag==2)              <----如何跳出這個(gè)循環(huán)的???
                 {
                         display_sos();
                 }        
         }
         else if(LED_flag==3)
回復(fù)

使用道具 舉報(bào)

7#
ID:1130312 發(fā)表于 2024-8-10 09:00 | 只看該作者
cedtek 發(fā)表于 2024-8-9 21:41
以下回答來(lái)自GPT-4o

您好,我下載您的程序之后發(fā)現(xiàn)SOS信號(hào)并不能實(shí)現(xiàn)(LED完全不亮),請(qǐng)問(wèn)這是什么原因呀
回復(fù)

使用道具 舉報(bào)

8#
ID:1130312 發(fā)表于 2024-8-10 09:02 | 只看該作者
1754232 發(fā)表于 2024-8-9 22:05
延時(shí)過(guò)多,這種造成單片機(jī)內(nèi)部資源消耗一直延時(shí)你的SOS信號(hào),這種沒(méi)什么太好的解決辦法,建議你學(xué)一下中斷 ...

嗯嗯,感謝
回復(fù)

使用道具 舉報(bào)

9#
ID:1130312 發(fā)表于 2024-8-10 09:03 | 只看該作者
ppcbug 發(fā)表于 2024-8-9 23:00
建議使用狀態(tài)機(jī)。
按鍵切換 狀態(tài)機(jī)的 狀態(tài), 然后 用狀態(tài)去驅(qū)動(dòng) 三個(gè)不同顯示函數(shù)。
這樣程序很清晰 ,  ...

好的,感謝
回復(fù)

使用道具 舉報(bào)

10#
ID:1130312 發(fā)表于 2024-8-10 16:05 | 只看該作者
想進(jìn)步要學(xué)習(xí) 發(fā)表于 2024-8-10 08:58
/*
什么狀不狀態(tài)不態(tài),太遠(yuǎn)了。在你基礎(chǔ)上改了下,思路是沒(méi)問(wèn)題的,代碼還沒(méi)測(cè)試過(guò),你看看有沒(méi)有有沒(méi)有參 ...

非常感謝您,參考您的代碼解決了我的問(wèn)題
回復(fù)

使用道具 舉報(bào)

11#
ID:161164 發(fā)表于 2024-8-10 18:15 | 只看該作者
請(qǐng)善用主循環(huán)
  1. #include <STC8H.H>
  2. # include <intrins.h>
  3. sbit KEY = P3^5;
  4. sbit LED = P3^4;
  5. unsigned int num=0;
  6. unsigned int LED_flag=0;
  7. void Delay10ms()                //@24.000MHz
  8. {
  9.         unsigned char data i, j, k;

  10.         i = 2;
  11.         j = 56;
  12.         k = 172;
  13.         do
  14.         {
  15.                 do
  16.                 {
  17.                         while (--k);
  18.                 }
  19.                 while (--j);
  20.         }
  21.         while (--i);
  22. }

  23. void Init_IO()
  24. {
  25.         P3M1 = 0x00;
  26.         P3M0 = 0x00;
  27. }
  28. void display_sos()
  29. {
  30.         static unsigned char Step=0, delay=0,repeat = 0;
  31.         if(Step==0)
  32.         {
  33.                 LED = 1;
  34.                 repeat = 6;               
  35.                 Step= 1;
  36.         }
  37.         if(Step==1)
  38.         {
  39.                 if(++delay>=20)
  40.                 {
  41.                         delay=0;
  42.                         repeat--;
  43.                         if(repeat==0)
  44.                         {
  45.                                 Step=2;
  46.                                 repeat = 6;
  47.                         }else{
  48.                                 if(LED)
  49.                                         LED=0;
  50.                                 else
  51.                                         LED=1;                               
  52.                         }
  53.                        
  54.                 }
  55.         }
  56.         if(Step==2)
  57.         {
  58.                 if(++delay>=50)
  59.                 {
  60.                         delay=0;
  61.                         repeat--;
  62.                         if(repeat==0)
  63.                         {
  64.                                 Step=3;
  65.                                 LED=0;
  66.                         }else{
  67.                                 if(LED)
  68.                                         LED=0;
  69.                                 else
  70.                                         LED=1;                               
  71.                         }
  72.                 }
  73.         }
  74.         if(Step==3)
  75.         {
  76.                 if(++delay>=200)
  77.                 {
  78.                         Step=0;
  79.                         delay=0;
  80.                 }
  81.         }
  82.         Delay10ms();
  83. }
  84. void display()
  85. {
  86.         if(LED_flag==0)
  87.         {
  88.                 LED=0;
  89.         }
  90.         else if(LED_flag==1)
  91.         {
  92.                 LED=1;
  93.         }
  94.         else if(LED_flag==2)
  95.         {
  96.                 display_sos();
  97.         }
  98. }
  99. void KeyScan()
  100. {
  101.         if(KEY == 0)
  102.         {
  103.                 Delay10ms();
  104.                 if(KEY == 0)
  105.                 {
  106.                         LED_flag++;
  107.                         if(LED_flag==3)
  108.                         {
  109.                                 LED_flag=0;
  110.                         }
  111.                 }
  112.                 while(!KEY);
  113.         }
  114. }
  115. void main()
  116. {
  117.         LED = 0;
  118.         Init_IO();
  119.         while(1)
  120.         {
  121.                 display();
  122.                 KeyScan();
  123.         }
  124. }
復(fù)制代碼



回復(fù)

使用道具 舉報(bào)

12#
ID:123917 發(fā)表于 2024-8-10 23:30 | 只看該作者
太復(fù)雜了。
計(jì)算按鍵次數(shù)保存在R0,然后判斷R0=1,2,3去執(zhí)行相應(yīng)的動(dòng)作即可
回復(fù)

使用道具 舉報(bào)

13#
ID:123917 發(fā)表于 2024-8-11 20:29 | 只看該作者
;==================================
;----不用中斷,按一次LED亮,按兩次SOS,按三次LED滅,按四次全滅
;==================================
;====淄博金峰電子科技==============
     ORG   0000H
;====初始化========================
     MOV   R0,  #00H
     MOV   P1,  #0FFH
     MOV   P3,  #0FFH
     K1    EQU  P3.0  ;定義P3.0為K1
     LED   EQU  P1.0  ;定義P1.0為L(zhǎng)ED
     SOS   EQU  P1.3  ;定義P1.3為SOS
;====主程序=========================
MAIN:
     JNB   K1,  JIA
     LCALL OUT
     JMP   MAIN
;====記錄按鍵次數(shù)程序=============
JIA:
     LCALL DELAY
     JNB   K1,$
     LCALL DELAY
     INC   R0
     LJMP  MAIN
;====輸出子程序===================   
OUT:
     MOV  A,R0
OUT1:   
     CJNE A,#01,OUT2
     CLR  LED
     RET
OUT2:
     CJNE A,#02,OUT3
     CLR  SOS
     RET
OUT3:
     CJNE A,#03,OUT4
     SETB LED
     RET
OUT4:
     CJNE A,#04,OUT5
OUT5:     
     SETB SOS
     MOV  R0,#00H
     RET   
;====延時(shí)子程序=====================
DELAY:
     MOV  R6,#255
L1: MOV  R7,#248
     DJNZ R7,$
     DJNZ R6,L1
     RET   
END 按3次.rar (3.81 KB, 下載次數(shù): 1)
回復(fù)

使用道具 舉報(bào)

14#
ID:123917 發(fā)表于 2024-8-11 20:52 | 只看該作者
使用匯編形成的代碼很小的
回復(fù)

使用道具 舉報(bào)

15#
ID:1130414 發(fā)表于 2024-8-11 23:16 | 只看該作者
你的DELAY延時(shí)太長(zhǎng)了,有200ms,甚至500ms,在延時(shí)過(guò)程中是不能處理按鍵的。
回復(fù)

使用道具 舉報(bào)

16#
ID:1130414 發(fā)表于 2024-8-11 23:21 | 只看該作者
你的DELAY延時(shí)時(shí)間太長(zhǎng)了,200ms已經(jīng)很長(zhǎng)了,還有500ms的。
有兩種解決方案:
一、放棄延時(shí),用定時(shí)器中斷計(jì)數(shù),比如1ms觸發(fā)一次,主循環(huán)中識(shí)別按鍵,識(shí)別計(jì)數(shù)值,計(jì)數(shù)達(dá)到設(shè)定時(shí)間后,顯示下一個(gè)內(nèi)容。此方案的優(yōu)點(diǎn)是定時(shí)精度高,缺點(diǎn)是你需要管理多個(gè)狀態(tài)變量,我的程序都是用的這種方式;
二、將延時(shí)切割小,用循環(huán)控制延時(shí)時(shí)間,在循環(huán)中調(diào)用按鍵識(shí)別程序。此方案程序修改量小,但是定時(shí)的精度會(huì)有影響。
回復(fù)

使用道具 舉報(bào)

17#
ID:332444 發(fā)表于 2024-8-12 20:09 | 只看該作者
典型的阻塞延時(shí)造成的案例,解決方案有放棄阻塞延時(shí),改用詢問(wèn)延時(shí),改用中斷延時(shí)。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表