欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

標題: 最近在學習單片機用狀態機來做按鈕檢測,遇到了一點問題,希望大佬看一下我是哪里出錯? [打印本頁]

作者: wzl570    時間: 2021-8-31 18:21
標題: 最近在學習單片機用狀態機來做按鈕檢測,遇到了一點問題,希望大佬看一下我是哪里出錯?
想嘗試做一個簡單帶有鬧鐘功能的時鐘,結果在按鈕檢測方面遇到了一些問題。在這里放上我寫的按鍵代碼:(我遇到的問題是:在判斷不同按鍵按下,我使用了if...esle if...。結果只能執行else if后面的語句,不執行 if 語句。)


////////////////////////////////////////////////////////////////////////////////////////

單片機 avr 16

時鐘頻率 8M

///////////////////////////////////////////////////////////////////////////////////////



#include<iom16v.h>

#define uchar unsigned char

char time_10ms_ok;//10ms按鍵掃描標志

void main(void);
void io_init(void);
void time_init(void);
void cpu_init(void);
void time_10ms(void);
char key_scan(void);

void io_init(void)
{
         DDRB = 0X00;
        PORTB = 0XFF;
        DDRD = 0XFF;
        PORTD = 0XFF;
}

void time_init(void)
{
         TCCR1A = 0X00;
         TCCR1B = (1<<WGM12)|(3<<CS10);//CTC,64分頻
        OCR1AH = 1250>>8;
        OCR1AL = 1250;
         TIMSK = 1<<OCIE1A;
         SREG = 1<<7;
}

void cpu_init(void)
{
         io_init();
        time_init();
}

void main(void)
{
         cpu_init();
        while(1)
        {
                 if(time_10ms_ok)
                {
                         time_10ms_ok = 0;
                        if(key_scan() == 2) PORTD = ~PORTD; //每按下按鍵2,3,
                        else if(key_scan() == 3) PORTD = ~PORTD; //PORTD取一次反。本是打算這樣設計的。結果仿真的時候。只執行else if這一語句
                }
        }
}
#pragma interrupt_handler time_10ms:7
void time_10ms(void)
{
        time_10ms_ok = 1;
}

#define key_state0 0
#define key_state1 1
#define key_state2 2
謝謝。

char key_scan(void)
{
         static char key_state = 0;
        char key_press, key_return = 0;
        key_press = PINB;
        switch(key_state)
        {
                 case key_state0:
                {
                         if(~key_press)//若有按鍵按下,則進入確認狀態
                        {
                                 key_state = key_state1;
                        }
                        break;
                }
                case key_state1:
                {
                         if(~key_press)//確認有按鍵按下,開始識別按鍵按下位置
                        {
                                 if(!(key_press & (1<<PB0))) key_return = 1;//按鍵1被按下
                                else if(!(key_press & (1<<PB1))) key_return = 2;//按鍵2被按下
                                else if(!(key_press & (1<<PB2))) key_return = 3;//按鍵3被按下
                                 key_state = key_state2;
                        }
                        else key_state = key_state0;//若按鍵抬起則回到初始狀態
                        break;
                }
                case key_state2:
                {
                         if(key_press == 0XFF)//若按鍵抬起則回到初始狀態
                        {
                                 key_state = key_state0;
                        }
                        break;
                }
        }
        return key_return;
}


狀態機test.rar

13.42 KB, 下載次數: 1

仿真文件


作者: wzl570    時間: 2021-8-31 21:26
找到解決方法,但還是不太清楚這個問題出在哪
作者: 人人學會單片機    時間: 2021-9-1 08:18


作者: bbxyliyang    時間: 2021-9-1 08:26
if(key_scan() == 2) PORTD = ~PORTD; //每按下按鍵2,3,
                        else if(key_scan() == 3) PORTD = ~PORTD; //PORTD取一次反。本是打算這樣設計的。結果仿真的時候。只執行else if這一語句,你這個執行語句不對,都是一樣的。
作者: bbxyliyang    時間: 2021-9-1 08:27

有限狀態機由有限的狀態和相互之間的轉移構成,在任何時候只
能處于給定數目的狀態中的一個。當接收到一個輸入事件時,狀態機產生一個輸出,同時也可能伴隨著狀態的轉移。
#define key_input    PIND.7      // 按鍵輸入口
#define key_state_0  0
#define key_state_1  1
#define key_state_2  2
char read_key(void)
{
static char key_state = 0;
char key_press, key_return = 0;
key_press = key_input;        // 讀按鍵 I/O (狀態機的輸入)
switch (key_state)
{
case key_state_0:        // 按鍵初始態
        if (!key_press) key_state = key_state_1;  // 鍵被按下,狀態轉換到鍵確認態 , 確定下一次按鍵的狀態值
break;
case key_state_1:        // 按鍵確認態
if (!key_press)
{
            key_return = 1;      // 按鍵仍按下,按鍵確認輸出為“1”
            key_state = key_state_2;  // 狀態轉換到鍵釋放態
}
else
            key_state = key_state_0;  // 按鍵已抬起,轉換到 按鍵初始態
       break;
case key_state_2:
            if (key_press) key_state = key_state_0;  //按鍵已釋放,轉換到按鍵初始態
       break;
}  
      return key_return;
}
該簡單按鍵接口函數 read_key()在整個系統程序中應每隔10ms
調用執行一次,每次執行時將先讀取與按鍵連接的 I/O 的電平到變量 key_press 中,然后進入用 switch 結構構成的狀態機。switch 結構中的 case 語句分別實現了 3 個不同狀態的處理判別過程,在每個狀態中將根據狀態的不同,以及 key_press 的值(狀態機的輸入)確定輸出值(key_return),和確定下一次按鍵的狀態值(key_state) 。 函數 read_key()的返回參數提供上層程序使用。返回值為 0 時,表示按鍵無動作;而返回 1 表示有一次按鍵閉合動作,需要進入按鍵處理程序做相應的鍵處理。在函數 read_key()中定義了 3 個局部變量,其中 key_press和key_return為一般普通的局部變量,每次函數執行時,key_press 中保存著剛檢測的按鍵值。key_return 為函數的返回值,總是先初始化為 0,只有在狀態 1 中重新置 1,作為表示按鍵確認的標志返回。變量 key_state 非常重要,它保存著按鍵的狀態值,該變量的值在函數調用結束后不能消失,
必須保留原值,因此在程序中定義為“局部靜態變量” ,用static 聲明。如果使用的語言環境不支持 static 類型的局部變量,應將 key_state 定義為全局變量(關于局部靜態變量的特點請參考相關介紹 C 語言程序設計的書籍) 。
作者: zyluglugl    時間: 2021-9-1 09:23
樓主,建議你 1、在寫程序時,一行只寫一句。
2、if(key_scan() == 2) PORTD = ~PORTD; //每按下按鍵2,3,
                        else if(key_scan() == 3) PORTD = ~PORTD; //PORTD取一次反。本是打算這樣設計的。結果仿真的時候。只執行else if這一語句
這兩句執行結果都是一樣,為什么還要寫兩句。
3、你這是想寫狀態機,感沉這狀態設計得讓人看不懂。
4、最好你要把安揵消抖的算法加進去。
作者: jizhongbiao    時間: 2021-9-1 09:24
按鍵掃描里面判斷對應按鍵被按下去應該是對0x01左移分別取出PB0 PB1 PB2。
作者: wzl570    時間: 2021-9-1 21:03
zyluglugl 發表于 2021-9-1 09:23
樓主,建議你 1、在寫程序時,一行只寫一句。
2、if(key_scan() == 2) PORTD = ~PORTD; //每按下按鍵2,3 ...

謝謝指點。其實我也是剛剛開始學習,有一些自己認為理所應當,到了實踐的時候才發現這樣不正確
作者: wyqf    時間: 2021-9-2 15:25
同意6樓觀點同時希望樓主將按鍵檢測的結果以變量的形式單獨存儲。你的程序相當于讀取了兩次按鍵值,這樣寫是有可能出現按鍵切換時鍵值被改變了的情況。
作者: wzl570    時間: 2021-9-2 19:03
wyqf 發表于 2021-9-2 15:25
同意6樓觀點同時希望樓主將按鍵檢測的結果以變量的形式單獨存儲。你的程序相當于讀取了兩次按鍵值,這樣寫 ...

確實,我已經發現這個問題,不對其進行存儲,數據太容易丟失了




歡迎光臨 (http://m.raoushi.com/bbs/) Powered by Discuz! X3.1