久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2038|回復: 16
收起左側

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

[復制鏈接]
ID:1130312 發表于 2024-8-9 16:25 | 顯示全部樓層 |閱讀模式
我要實現的是按鍵按一下LED長亮,第二下顯示SOS信號,第三下LED熄滅,但是現在有時按第三下LED并不熄滅,我想是因為我的SOS顯示代碼沒有執行完,所以按鍵掃描不到,請問這個問題如何解決呢。下面是我的代碼# 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();               
        }
}


回復

使用道具 舉報

ID:633559 發表于 2024-8-10 08:58 | 顯示全部樓層
/*
什么狀不狀態不態,太遠了。在你基礎上改了下,思路是沒問題的,代碼還沒測試過,你看看有沒有有沒有參考價值吧。
*/
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;
    }
/*
下面其實可以寫的漂亮點,用結構體數組for循環處理
*/
    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();            
    }
}
回復

使用道具 舉報

ID:866313 發表于 2024-8-9 21:41 | 顯示全部樓層
以下回答來自GPT-4o

  • 你所遇到的問題的確可能是因為在執行 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行為的同時,繼續監控按鍵輸入,避免按鍵在特定情況下失效。


回復

使用道具 舉報

ID:1130376 發表于 2024-8-9 22:05 | 顯示全部樓層
延時過多,這種造成單片機內部資源消耗一直延時你的SOS信號,這種沒什么太好的解決辦法,建議你學一下中斷函數吧
回復

使用道具 舉報

ID:628113 發表于 2024-8-9 23:00 | 顯示全部樓層
建議使用狀態機。
按鍵切換 狀態機的 狀態, 然后 用狀態去驅動 三個不同顯示函數。
這樣程序很清晰 , 模塊化 很強 .
回復

使用道具 舉報

ID:1012735 發表于 2024-8-9 23:11 | 顯示全部樓層
死循環了:
        else if(LED_flag==2)
         {
                 while(LED_flag==2)              <----如何跳出這個循環的???
                 {
                         display_sos();
                 }        
         }
         else if(LED_flag==3)
回復

使用道具 舉報

ID:1130312 發表于 2024-8-10 09:00 | 顯示全部樓層
cedtek 發表于 2024-8-9 21:41
以下回答來自GPT-4o

您好,我下載您的程序之后發現SOS信號并不能實現(LED完全不亮),請問這是什么原因呀
回復

使用道具 舉報

ID:1130312 發表于 2024-8-10 09:02 | 顯示全部樓層
1754232 發表于 2024-8-9 22:05
延時過多,這種造成單片機內部資源消耗一直延時你的SOS信號,這種沒什么太好的解決辦法,建議你學一下中斷 ...

嗯嗯,感謝
回復

使用道具 舉報

ID:1130312 發表于 2024-8-10 09:03 | 顯示全部樓層
ppcbug 發表于 2024-8-9 23:00
建議使用狀態機。
按鍵切換 狀態機的 狀態, 然后 用狀態去驅動 三個不同顯示函數。
這樣程序很清晰 ,  ...

好的,感謝
回復

使用道具 舉報

ID:1130312 發表于 2024-8-10 16:05 | 顯示全部樓層
想進步要學習 發表于 2024-8-10 08:58
/*
什么狀不狀態不態,太遠了。在你基礎上改了下,思路是沒問題的,代碼還沒測試過,你看看有沒有有沒有參 ...

非常感謝您,參考您的代碼解決了我的問題
回復

使用道具 舉報

ID:161164 發表于 2024-8-10 18:15 | 顯示全部樓層
請善用主循環
  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. }
復制代碼



回復

使用道具 舉報

ID:123917 發表于 2024-8-10 23:30 | 顯示全部樓層
太復雜了。
計算按鍵次數保存在R0,然后判斷R0=1,2,3去執行相應的動作即可
回復

使用道具 舉報

ID:123917 發表于 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為LED
     SOS   EQU  P1.3  ;定義P1.3為SOS
;====主程序=========================
MAIN:
     JNB   K1,  JIA
     LCALL OUT
     JMP   MAIN
;====記錄按鍵次數程序=============
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   
;====延時子程序=====================
DELAY:
     MOV  R6,#255
L1: MOV  R7,#248
     DJNZ R7,$
     DJNZ R6,L1
     RET   
END 按3次.rar (3.81 KB, 下載次數: 1)
回復

使用道具 舉報

ID:123917 發表于 2024-8-11 20:52 | 顯示全部樓層
使用匯編形成的代碼很小的 123.jpg
456.jpg
回復

使用道具 舉報

ID:1130414 發表于 2024-8-11 23:16 | 顯示全部樓層
你的DELAY延時太長了,有200ms,甚至500ms,在延時過程中是不能處理按鍵的。
回復

使用道具 舉報

ID:1130414 發表于 2024-8-11 23:21 | 顯示全部樓層
你的DELAY延時時間太長了,200ms已經很長了,還有500ms的。
有兩種解決方案:
一、放棄延時,用定時器中斷計數,比如1ms觸發一次,主循環中識別按鍵,識別計數值,計數達到設定時間后,顯示下一個內容。此方案的優點是定時精度高,缺點是你需要管理多個狀態變量,我的程序都是用的這種方式;
二、將延時切割小,用循環控制延時時間,在循環中調用按鍵識別程序。此方案程序修改量小,但是定時的精度會有影響。
回復

使用道具 舉報

ID:332444 發表于 2024-8-12 20:09 | 顯示全部樓層
典型的阻塞延時造成的案例,解決方案有放棄阻塞延時,改用詢問延時,改用中斷延時。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 中国美女av| 青青艹在线视频 | 色婷婷综合成人av | 精品久久九九 | 国产美女高潮 | 91伊人| 国产午夜在线 | 亚洲精品久久久久久久久久吃药 | 亚洲一区中文字幕在线观看 | 中文字幕影院 | 亚洲欧美中文日韩在线v日本 | 亚洲精品久久久一区二区三区 | 欧美一二三 | 伊人精品一区二区三区 | 国产一区二区三区免费观看在线 | 色婷婷精品国产一区二区三区 | 日韩av在线一区 | 亚洲一区二区三区福利 | 日韩av一区二区在线观看 | 欧美一区二区三区视频 | 毛片视频网址 | 精品亚洲一区二区 | 午夜小影院 | 午夜影院| 精品1区2区3区4区 | 成人性生交大片 | 国产黑丝在线 | 中午字幕在线观看 | 国产欧美综合在线 | 在线观看av不卡 | 99在线资源| 视频一区在线 | 国产激情视频网站 | 国产91精品网站 | 国产精品久久久久久久久久久久久 | 亚洲精品一区二区三区丝袜 | 久久99精品久久久久久青青日本 | 日本久久网| 国产精品日韩在线观看 | 国产精品久久久久一区二区 | 欧美精品久久久久久久久老牛影院 |