久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

51入門系列教程| 第一次被控制

 Zmflc 2016-04-28

前面一貼簡單討論了一下51單片機的IO輸出功能

既然是IO,有output肯定就有input

今次咱聊聊input,,輸入功能

有了input,,51就能夠根據(jù)輸入的信號

去做出下一步工作的決定

其實單片機的輸入不外乎就是兩種

一是數(shù)字輸入,由單片機去判斷輸入的高低電平

再就是模擬輸入,,最典型的就是內(nèi)置ADC外設(shè)的單片機

可以把外部輸入的電壓值與基準電壓進行比較

從而得到一定數(shù)值的二進制編碼

譬如基準電壓3.3v,,12位的線性ADC外設(shè)

就可以將外部輸入的0-3.3v電壓按比例用0-4096的十進制數(shù)去表示

換成二進制便是000000000000-111111111111

限于手頭上51片子沒有AD這個外設(shè)

咱今天聊的輸入,就從數(shù)字輸入下手

一,、按鍵基本原理

先上電路

51入門系列教程| 第一次被控制--按鍵

先看上面一個圖

P0.1口,,連接到一個10k的電阻,上拉到電源Vcc(這里Vcc=5.0v)

同時連接到按鍵的一端

按鍵的另一端則直接連到地

簡單分析一下這個電路

當(dāng)按鍵沒有按下的時候

10k電阻和P0.1口沒有連接到地

由于P0端口是開漏輸出,,可以看做是懸空

那么經(jīng)過10k電阻的電流為0,,即10k電阻的壓降為0

這個時候,可以認為P0.1口的電位是5.0v,,一個高電平

So,,按鍵沒有按下,單片機可以認為P0.1口輸入了一個邏輯“1”,,也就是高電平

當(dāng)按鍵按下時

P0.1口和10k電阻均被連接到了地

這個時候,,P0.1口的電位直接被拉到0v,也就是地

So,,單片機可以認為P0.1口輸入了一個邏輯“0”,,也就是低電平

這里尤其注意一下這個10K電阻的作用

名曰上拉電阻

它的存在是非常有必要的

沒有這個電阻,P0.1口直接連接到按鍵一端或者電源,,都會產(chǎn)生不好的后果

如果直接連至電源,,按鍵按下的時候,,Vcc和地……,,后果你懂的……

如果直接連接到按鍵的一端,在按鍵按下前

P0.1都是懸空的,,外界的干擾(EMI之類),,非常容易引起單片機的誤判

它的作用主要是按下前穩(wěn)定電平、按下后限流

在按鍵按下的時候,,電源—10k電阻—地 這個回路中

會產(chǎn)生5/100000=5mA電流,,產(chǎn)生一定的功耗

有朋友會想,加大電阻就可以解決這個問題了呀

但是電阻太大的話,,可能會出現(xiàn)開路情況

So,,幾k到幾十k是比較合適的

再看下面一個圖

嗯,簡單的發(fā)光二極管回路

這里就不多解釋了

順道拿電木板焊了個電路

51入門系列教程| 第一次被控制--按鍵電源,、地和2個IO口用排針等插

51入門系列教程| 第一次被控制--按鍵

菊花面,,10k上拉電阻和220歐LED限流電阻

這個電木板質(zhì)量真次,,焊盤掉了好幾個

51讀端口的代碼特別簡單

只要直接按位或者按port來逐位讀取即可

譬如要把P01口的邏輯值賦給變量temp

直接temp = P01即可

P01輸入一個低電平,temp=0x00

P01輸入一個高電平,,temp=0x01

上個測試代碼

#include

sbit P11 = P1^1;//按位定義

sbit P01 = P0^1;

int main()

{

while(1)

{

if(P01==0)//判斷P01口的值,,0為按下

{P11 = ~P11;}//按下后的操作,P11口取反

else (P11 = P11;)

}

return 0;

}

簡單閱讀一下代碼

大概的功能就是判斷P01口電平是否為0

為0的話,,P11口電平取反,,也就是LED點亮或者熄滅

編譯下載,看看結(jié)果

51入門系列教程| 第一次被控制--按鍵

不難發(fā)現(xiàn)

按鍵雖然能夠控制51去點亮或者熄滅LED

但是似乎并不是那么順手

不能非常準確地操作LED的亮或者滅

為嘛,?

二,、去抖

在解決上面問題之前

必須意識到,按鍵其實是一個機械彈性開關(guān)結(jié)構(gòu)

在按下或者松開的瞬間,,也就是機械觸點斷開,、閉合時

不會穩(wěn)定地接通或者斷開,存在一連串的抖動

這種抖動時間與按鍵的機械特性有關(guān),,幾個ms到幾十個ms都有可能

由于51執(zhí)行代碼的速度是us級

So,,自己感覺只按下了一次按鍵

其實51已經(jīng)反復(fù)多次執(zhí)行了按鍵按下的操作

所以造成上面gif中的現(xiàn)象

所以,按鍵去抖,,是無論哪種單片機都需要面臨的問題

當(dāng)然,,有些比較有特點的單片機會有按鍵相關(guān)的外設(shè),無需過多關(guān)注去抖,,這個在此不討論

有關(guān)去抖,,有硬件和軟件兩種辦法

硬件上去抖的辦法

第一種是使用RS觸發(fā)器/鎖存器

51入門系列教程| 第一次被控制--按鍵

鎖存器的工作特點就決定了,即使有按鍵抖動,,也不會影響上如兩個與非門構(gòu)成的RS鎖存器的輸出

再一種是在按鍵上并聯(lián)一個合適大小的電容

51入門系列教程| 第一次被控制--按鍵

其實就是利用電容充放電的特性,,無它

硬件去抖,基本上不占用單片機的資源

致命的缺陷是需要額外的器件

會使PCB面積,、BOM,、成本有所增加

在成本為王的時代,基本上這種辦法很少有人使用了

但是非??煽?/p>

再來看看軟件去抖

第一種是使用延時去抖,,是目前用得比較多的

上個代碼

#include

sbit P11 = P1^1;

sbit P01 = P0^1;

unsigned char flag;

void delay_ms(unsigned int xms)//定義一個ms級的延時函數(shù)

{

unsigned int i,j;

for(i=xms;i>0;i--)

{

for(j=124;j>0;j--);

}

}

unsigned char keyscan()//掃描按鍵

{

unsigned char key_value;

if(P01 == 0)//P01被拉低,也就是有按鍵按下

{

delay_ms(100);//延時100ms

if(P01 == 0) //延時后再判斷P01口是不是被拉低(按下)

{key_value = 1;}//如果是,,鍵值位置1

else {key_value = 0;}//否則置0

}

return key_value;//返回鍵值

}

void key_op()

{

if(flag) //判斷標志位,,然后進行操作

{

P11 = ~P11;

flag = 0;

}

else {;}

}

int main()

{

while(1)

{

flag = keyscan();//把掃描的鍵值賦給標志位

key_op();//根據(jù)標志位進行操作

}

return 0;

}

簡單分析一下上面的代碼

最最核心的就是

如果發(fā)現(xiàn)P01的按鍵被按下

就延時100ms后再讀一下P01的值

注意一下,這里的100ms其實和按鍵的機械特性有關(guān)

根據(jù)實際情況調(diào)整

如果還是被按下的狀態(tài),,則認為按鍵確實被按下

單片機再進行下一步操作

上個GIF

51入門系列教程| 第一次被控制--按鍵

可以發(fā)現(xiàn)

按鍵已經(jīng)可以很準確地控制LED的亮滅了

但是,,單片在執(zhí)行delay_ms(100)的時候

其它任何事情都不能做呀

所以很多時候,這個延時會采用定時器中斷來完成

這個后面再討論

其實還有一種不需要延時的去抖方法

可以理解成一個狀態(tài)機

上代碼

#include

sbit P11 = P1^1;

sbit P01 = P0^1;

unsigned char flag;

void delay_ms(unsigned int xms)

{

unsigned int i,j;

for(i=xms;i>0;i--)

{

for(j=124;j>0;j--);

}

}

unsigned char keyscan()

{

static unsigned char key_state = 0;

static unsigned char key_value = 0;

unsigned char key_press,key_return = 0;

key_press = P01; //讀按鍵

switch(key_state)

{

case 0 ://按鍵初始態(tài)

if(key_press == 0){key_state = 1;}//按鍵被按下,,但需要確認

break;

case 1://按鍵進行確認

if(key_press == 0)//如果還是被按下,,則開始決定鍵值

{

key_value = 1;

key_state = 2;//確定被按下,,轉(zhuǎn)到按鍵被按下狀態(tài)

}

else { key_value = 0;}//否則認為是抖動

break;

case 2://按鍵釋放狀態(tài)

if(key_press == 1)

{

key_return = key_value; //按鍵釋放后輸出鍵值

key_value = 0;

key_state = 0; //按鍵釋放,進入按鍵初始態(tài)

}

break;

}

return key_return; //返回鍵值

}

void key_op()

{

if(flag)

{

P11 = ~P11;

flag = 0;

}

else {;}

}

int main()

{

while(1)

{

flag = keyscan();

key_op();

}

return 0;

}

利用狀態(tài)機的編程思想

代碼上有解釋了,,這里不過多深入討論

上GIF

51入門系列教程| 第一次被控制--按鍵

可以看得出來

其實效果也還不錯

三,、矩陣鍵盤

到這里,一個基本鍵盤需要考慮的東西

大概就是這么多了

還有一種針對比較多按鍵的電路組態(tài)

叫做是矩陣鍵盤

簡單介紹一下吧

上個結(jié)構(gòu)圖

51入門系列教程| 第一次被控制--按鍵

上圖是個4x4鍵盤,,16個按鍵

按照前面的方法,,得需要16個IO口才能完成接入

這里其實只需要P1口的8個端口即可

這種矩陣鍵盤判斷按鍵的方法有好幾種

用的比較多的有2種

一是行/列掃描法,分兩步

1,、判斷鍵盤中有無鍵按丿將全部行線Y0-Y3置低電平,,然后檢測列線的狀態(tài)。只要有一列的電平為低,,則表示鍵盤中有鍵被按下,,而且閉合的鍵位于低電平線丿根行線相交叉皿個按鍵之中。若所有列線均為高電平,,則鍵盤中無鍵按下

2,、判斷閉合鍵所在的位置 在確認有鍵按下后,即可進入確定具體閉合鍵的過程,。其方法是:依次將行線置為低電平,,即在置某根行線為低電平時,其它線為高電平,。在確定某根行線位置為低電平后,,再逐行檢測各列線的電平狀態(tài)。若某列為低,,則該列線與置為低電平的行線交叉處的按鍵就是閉合的按鍵

再一個是翻轉(zhuǎn)法,,三步

1、行線輸出全為0,,讀出列線值,。

2、列線輸出上次讀入的列線值,。

3,、讀入行線值,,并與前次列線值組合,,生成組合碼值。根據(jù)這個組合碼來確定被按下的按鍵,。

沒來得及做個矩陣鍵盤

如有疑問,,可把問題發(fā)送給“云漢電子社區(qū)”微信公眾號平臺,我們會及時回復(fù),,關(guān)注公眾號可閱讀更多51系列教程,!我們歡迎您的溝通,!

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多