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

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

QQ登錄

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

搜索
查看: 2574|回復(fù): 9
收起左側(cè)

最近在學(xué)習(xí)單片機(jī)用狀態(tài)機(jī)來(lái)做按鈕檢測(cè),遇到了一點(diǎn)問(wèn)題,希望大佬看一下我是哪里出錯(cuò)?

[復(fù)制鏈接]
ID:962686 發(fā)表于 2021-8-31 18:21 | 顯示全部樓層 |閱讀模式
想嘗試做一個(gè)簡(jiǎn)單帶有鬧鐘功能的時(shí)鐘,結(jié)果在按鈕檢測(cè)方面遇到了一些問(wèn)題。在這里放上我寫的按鍵代碼:(我遇到的問(wèn)題是:在判斷不同按鍵按下,我使用了if...esle if...。結(jié)果只能執(zhí)行else if后面的語(yǔ)句,不執(zhí)行 if 語(yǔ)句。)


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

單片機(jī) avr 16

時(shí)鐘頻率 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è)計(jì)的。結(jié)果仿真的時(shí)候。只執(zhí)行else if這一語(yǔ)句
                }
        }
}
#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)有按鍵按下,開(kāi)始識(shí)別按鍵按下位置
                        {
                                 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)機(jī)test.rar

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

仿真文件

回復(fù)

使用道具 舉報(bào)

ID:962686 發(fā)表于 2021-8-31 21:26 | 顯示全部樓層
找到解決方法,但還是不太清楚這個(gè)問(wèn)題出在哪
回復(fù)

使用道具 舉報(bào)

ID:390416 發(fā)表于 2021-9-1 08:18 | 顯示全部樓層
15 03 20 03   按鍵狀態(tài)機(jī).png
回復(fù)

使用道具 舉報(bào)

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è)計(jì)的。結(jié)果仿真的時(shí)候。只執(zhí)行else if這一語(yǔ)句,你這個(gè)執(zhí)行語(yǔ)句不對(duì),都是一樣的。
回復(fù)

使用道具 舉報(bào)

ID:190577 發(fā)表于 2021-9-1 08:27 | 顯示全部樓層

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

使用道具 舉報(bào)

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

使用道具 舉報(bào)

ID:130230 發(fā)表于 2021-9-1 09:24 | 顯示全部樓層
按鍵掃描里面判斷對(duì)應(yīng)按鍵被按下去應(yīng)該是對(duì)0x01左移分別取出PB0 PB1 PB2。
回復(fù)

使用道具 舉報(bào)

ID:962686 發(fā)表于 2021-9-1 21:03 | 顯示全部樓層
zyluglugl 發(fā)表于 2021-9-1 09:23
樓主,建議你 1、在寫程序時(shí),一行只寫一句。
2、if(key_scan() == 2) PORTD = ~PORTD; //每按下按鍵2,3 ...

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

使用道具 舉報(bào)

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

使用道具 舉報(bào)

ID:962686 發(fā)表于 2021-9-2 19:03 | 顯示全部樓層
wyqf 發(fā)表于 2021-9-2 15:25
同意6樓觀點(diǎn)同時(shí)希望樓主將按鍵檢測(cè)的結(jié)果以變量的形式單獨(dú)存儲(chǔ)。你的程序相當(dāng)于讀取了兩次按鍵值,這樣寫 ...

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

使用道具 舉報(bào)

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 精品欧美乱码久久久久久 | 国产高清精品一区二区三区 | 草草视频在线观看 | av毛片在线播放 | 欧美激情精品久久久久 | 欧美一级全黄 | 免费激情网站 | 日本在线一二 | 亚洲一区二区三区在线观看免费 | 一区二区国产精品 | 久久久精品一区 | 国产精品欧美一区二区三区 | 欧美一级在线 | 美国av毛片 | 日韩一二区在线 | 国产精品一区二区三区久久久 | 一区二区三区高清在线观看 | 欧美色专区 | 成人欧美一区二区三区黑人孕妇 | 亚洲 自拍 另类 欧美 丝袜 | wwwxx在线观看 | 中文字幕1区2区3区 亚洲国产成人精品女人久久久 | 亚洲综合在线一区 | 欧美日韩在线一区 | 国产免费拔擦拔擦8x高清 | 亚洲a视频| 国产精品视频在线观看 | 自拍视频国产 | 在线天堂免费中文字幕视频 | 久久不射电影网 | 久久久久久91 | 亚洲午夜精品一区二区三区 | 在线播放中文字幕 | 99热热99| 久久国产精品首页 | 精品一区二区av | 久久久久久成人 | 青青激情网| 草草影院ccyy| www亚洲免费国内精品 | 91精品国产高清一区二区三区 |