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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

最近在學(xué)習(xí)單片機用狀態(tài)機來做按鈕檢測,遇到了一點問題,希望大佬看一下我是哪里出錯?

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:962686 發(fā)表于 2021-8-31 18:21 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
想嘗試做一個簡單帶有鬧鐘功能的時鐘,結(jié)果在按鈕檢測方面遇到了一些問題。在這里放上我寫的按鍵代碼:(我遇到的問題是:在判斷不同按鍵按下,我使用了if...esle if...。結(jié)果只能執(zhí)行else if后面的語句,不執(zhí)行 if 語句。)


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

單片機 avr 16

時鐘頻率 8M

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



#include<iom16v.h>

#define uchar unsigned char

char time_10ms_ok;//10ms按鍵掃描標(biāo)志

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取一次反。本是打算這樣設(shè)計的。結(jié)果仿真的時候。只執(zhí)行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)//若有按鍵按下,則進(jìn)入確認(rèn)狀態(tài)
                        {
                                 key_state = key_state1;
                        }
                        break;
                }
                case key_state1:
                {
                         if(~key_press)//確認(rèn)有按鍵按下,開始識別按鍵按下位置
                        {
                                 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;//若按鍵抬起則回到初始狀態(tài)
                        break;
                }
                case key_state2:
                {
                         if(key_press == 0XFF)//若按鍵抬起則回到初始狀態(tài)
                        {
                                 key_state = key_state0;
                        }
                        break;
                }
        }
        return key_return;
}


狀態(tài)機test.rar

13.42 KB, 下載次數(shù): 1

仿真文件

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

使用道具 舉報

沙發(fā)
ID:962686 發(fā)表于 2021-8-31 21:26 | 只看該作者
找到解決方法,但還是不太清楚這個問題出在哪
回復(fù)

使用道具 舉報

板凳
ID:390416 發(fā)表于 2021-9-1 08:18 | 只看該作者

回復(fù)

使用道具 舉報

地板
ID:190577 發(fā)表于 2021-9-1 08:26 | 只看該作者
if(key_scan() == 2) PORTD = ~PORTD; //每按下按鍵2,3,
                        else if(key_scan() == 3) PORTD = ~PORTD; //PORTD取一次反。本是打算這樣設(shè)計的。結(jié)果仿真的時候。只執(zhí)行else if這一語句,你這個執(zhí)行語句不對,都是一樣的。
回復(fù)

使用道具 舉報

5#
ID:190577 發(fā)表于 2021-9-1 08:27 | 只看該作者

有限狀態(tài)機由有限的狀態(tài)和相互之間的轉(zhuǎn)移構(gòu)成,在任何時候只
能處于給定數(shù)目的狀態(tài)中的一個。當(dāng)接收到一個輸入事件時,狀態(tài)機產(chǎn)生一個輸出,同時也可能伴隨著狀態(tài)的轉(zhuǎn)移。
#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 (狀態(tài)機的輸入)
switch (key_state)
{
case key_state_0:        // 按鍵初始態(tài)
        if (!key_press) key_state = key_state_1;  // 鍵被按下,狀態(tài)轉(zhuǎn)換到鍵確認(rèn)態(tài) , 確定下一次按鍵的狀態(tài)值
break;
case key_state_1:        // 按鍵確認(rèn)態(tài)
if (!key_press)
{
            key_return = 1;      // 按鍵仍按下,按鍵確認(rèn)輸出為“1”
            key_state = key_state_2;  // 狀態(tài)轉(zhuǎn)換到鍵釋放態(tài)
}
else
            key_state = key_state_0;  // 按鍵已抬起,轉(zhuǎn)換到 按鍵初始態(tài)
       break;
case key_state_2:
            if (key_press) key_state = key_state_0;  //按鍵已釋放,轉(zhuǎn)換到按鍵初始態(tài)
       break;
}  
      return key_return;
}
該簡單按鍵接口函數(shù) read_key()在整個系統(tǒng)程序中應(yīng)每隔10ms
調(diào)用執(zhí)行一次,每次執(zhí)行時將先讀取與按鍵連接的 I/O 的電平到變量 key_press 中,然后進(jìn)入用 switch 結(jié)構(gòu)構(gòu)成的狀態(tài)機。switch 結(jié)構(gòu)中的 case 語句分別實現(xiàn)了 3 個不同狀態(tài)的處理判別過程,在每個狀態(tài)中將根據(jù)狀態(tài)的不同,以及 key_press 的值(狀態(tài)機的輸入)確定輸出值(key_return),和確定下一次按鍵的狀態(tài)值(key_state) 。 函數(shù) read_key()的返回參數(shù)提供上層程序使用。返回值為 0 時,表示按鍵無動作;而返回 1 表示有一次按鍵閉合動作,需要進(jìn)入按鍵處理程序做相應(yīng)的鍵處理。在函數(shù) read_key()中定義了 3 個局部變量,其中 key_press和key_return為一般普通的局部變量,每次函數(shù)執(zhí)行時,key_press 中保存著剛檢測的按鍵值。key_return 為函數(shù)的返回值,總是先初始化為 0,只有在狀態(tài) 1 中重新置 1,作為表示按鍵確認(rèn)的標(biāo)志返回。變量 key_state 非常重要,它保存著按鍵的狀態(tài)值,該變量的值在函數(shù)調(diào)用結(jié)束后不能消失,
必須保留原值,因此在程序中定義為“局部靜態(tài)變量” ,用static 聲明。如果使用的語言環(huán)境不支持 static 類型的局部變量,應(yīng)將 key_state 定義為全局變量(關(guān)于局部靜態(tài)變量的特點請參考相關(guān)介紹 C 語言程序設(shè)計的書籍) 。
回復(fù)

使用道具 舉報

6#
ID:584195 發(fā)表于 2021-9-1 09:23 | 只看該作者
樓主,建議你 1、在寫程序時,一行只寫一句。
2、if(key_scan() == 2) PORTD = ~PORTD; //每按下按鍵2,3,
                        else if(key_scan() == 3) PORTD = ~PORTD; //PORTD取一次反。本是打算這樣設(shè)計的。結(jié)果仿真的時候。只執(zhí)行else if這一語句
這兩句執(zhí)行結(jié)果都是一樣,為什么還要寫兩句。
3、你這是想寫狀態(tài)機,感沉這狀態(tài)設(shè)計得讓人看不懂。
4、最好你要把安揵消抖的算法加進(jìn)去。
回復(fù)

使用道具 舉報

7#
ID:130230 發(fā)表于 2021-9-1 09:24 | 只看該作者
按鍵掃描里面判斷對應(yīng)按鍵被按下去應(yīng)該是對0x01左移分別取出PB0 PB1 PB2。
回復(fù)

使用道具 舉報

8#
ID:962686 發(fā)表于 2021-9-1 21:03 | 只看該作者
zyluglugl 發(fā)表于 2021-9-1 09:23
樓主,建議你 1、在寫程序時,一行只寫一句。
2、if(key_scan() == 2) PORTD = ~PORTD; //每按下按鍵2,3 ...

謝謝指點。其實我也是剛剛開始學(xué)習(xí),有一些自己認(rèn)為理所應(yīng)當(dāng),到了實踐的時候才發(fā)現(xiàn)這樣不正確
回復(fù)

使用道具 舉報

9#
ID:750420 發(fā)表于 2021-9-2 15:25 | 只看該作者
同意6樓觀點同時希望樓主將按鍵檢測的結(jié)果以變量的形式單獨存儲。你的程序相當(dāng)于讀取了兩次按鍵值,這樣寫是有可能出現(xiàn)按鍵切換時鍵值被改變了的情況。
回復(fù)

使用道具 舉報

10#
ID:962686 發(fā)表于 2021-9-2 19:03 | 只看該作者
wyqf 發(fā)表于 2021-9-2 15:25
同意6樓觀點同時希望樓主將按鍵檢測的結(jié)果以變量的形式單獨存儲。你的程序相當(dāng)于讀取了兩次按鍵值,這樣寫 ...

確實,我已經(jīng)發(fā)現(xiàn)這個問題,不對其進(jìn)行存儲,數(shù)據(jù)太容易丟失了
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 亚洲午夜av | 久久网国产 | 亚洲视频三区 | 日本在线网址 | 成人久久久 | 日韩在线看片 | 亚洲精品久久久久久一区二区 | 久草福利| 亚洲国产成人精品久久久国产成人一区 | 午夜精品久久久久久久久久久久 | 在线播放国产一区二区三区 | 天堂网中文 | 国产亚洲精品成人av久久ww | 99久久99| 99久久久久久久久 | 操操操av| 久久精品免费 | 久久电影一区 | 91精品国产91久久久 | 久久i| 亚洲精品久久久久avwww潮水 | 久热精品在线观看视频 | 福利视频二区 | 国产一区二区黑人欧美xxxx | 羞羞色影院 | 成人免费大片黄在线播放 | 久久久网 | 日韩精品一区在线 | 国产欧美在线观看 | 久久国产精品99久久久大便 | 日本又色又爽又黄的大片 | 一区欧美 | 亚洲精品一区二区三区丝袜 | 国产精品免费一区二区三区四区 | 91精品国产91久久久久久吃药 | 色视频免费 | 国产午夜久久 | 日韩欧美在线视频 | 中国黄色在线视频 | 亚洲国产精品久久久久秋霞不卡 | 丝袜一区二区三区 |