1. IO介紹
51單片機總的管腳有40個,但是其中能夠作為IO使用的只有32個,每8個分為一組,共4組。單片機要想實現(xiàn)預(yù)定功能必然要使用到各種IO口,來完成各項功能,包括點亮LED,連接按鍵、鍵盤,各種I2C、SPI設(shè)備等。51單片機,4組IO的結(jié)構(gòu)略有不同,使用時應(yīng)當(dāng)注意。
P0屬于雙向IO,內(nèi)部沒有上拉電阻,作為輸出時,最好外加上拉電阻。
P1、P2、P3屬于準(zhǔn)雙向IO?!皽?zhǔn)”體現(xiàn)在輸入時,必須先輸出“1”,才能正確讀到IO的輸入情況。
?
P3口的各個IO均有復(fù)用功能:
2. IO編程
對于IO的操作無非是讀輸入和寫輸出,通過讀寫相應(yīng)的寄存器(P0、P1、P2、P3)就可以實現(xiàn)。
?
2.1 字節(jié)尋址
字節(jié)尋址可以一次把8個IO全部訪問了,使用時把Px(x=0、1、2或3)當(dāng)作無符號字符變量(unsigned char)即可。
2.2 位尋址
51單片機有一類特殊的變量——位變量(bit),可以用來保存“0”或者“1”。
為了讀寫某個IO,可以定義特殊位變量(sbit)指定某一個IO,再進(jìn)行讀寫
?
#include "reg52.h"
sbit LED=P1^0;
bit temp;
void main()
{
temp=LED;//確保temp為位變量(bit)
LED=1;
LED=0;
LED=temp;
}
?
3.常用器件的驅(qū)動電路
3.1 LED
單片機能夠提供的電流有限,一般采用這種方式驅(qū)動LED:
當(dāng)P2^0=1是,LED兩端電壓差位0V,LED不發(fā)光。當(dāng)P2^0=1是,LED兩端存在電壓差,LED發(fā)光,串聯(lián)電阻的作用在于限流,阻值根據(jù)電源電壓和LED工作電流決定
?
3.2?數(shù)碼管。
數(shù)碼管本質(zhì)是發(fā)光二極管按照一定位置排列的顯示數(shù)字的器件,可分為共陰極和共陽極兩類。按照數(shù)量可分為一位,兩位,四位甚至八位。
一位七段共陽極數(shù)碼管:
有的數(shù)碼管有八段,右下角會增加一個小數(shù)點。
?
當(dāng)驅(qū)動兩位8段數(shù)碼管時,按上面的方式會占用16個IO,這種方式成為靜態(tài)顯示。靜態(tài)顯示可以控制每一個數(shù)碼管,但是會極大的占用IO資源,當(dāng)數(shù)碼管數(shù)量較多時,這種方式明顯不適合。
?
與靜態(tài)相對應(yīng)的是動態(tài)顯示。每一個數(shù)碼管顯示一段時間,然后在切換到下一個。根據(jù)人眼的視覺暫留效應(yīng),只要刷新的頻率超過24Hz,在人眼中就是連續(xù)的。把每一位數(shù)碼管的a,b,c,d,e,f,g,dp接在同一組IO上,再用另一組IO來控制具體顯示哪一個數(shù)碼管(公共端)。
?
下面四位共陰極數(shù)碼管示例,公共端用三極管做開關(guān):
數(shù)碼管顯示段碼如下
?
unsigned char code DUMA[]={ //共陰極顯示段碼,共陽極取反即可
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, //0-9
0x77,0x7c,0x39,0x5e,0x79,0x71 //a-f
};
?
3.3 按鍵
可以用這種最簡單的方式連接在IO上,為了保證能正確讀到輸入,先輸出“1”。如下圖,當(dāng)按鍵按下,P1^0=0, 當(dāng)按鍵松開,P1^0=1。
但實際上,由于開關(guān)接觸瞬間,電壓會產(chǎn)生不穩(wěn)定的跳變,稱為抖動,如下圖:
抖動的時間小于10ms,因此當(dāng)我們檢測到電平變化是,延時10ms即可。
?
3.4 鍵盤
通過把按鍵組成4x4矩陣,可以使用8個IO連接16個按鍵。當(dāng)按鍵數(shù)量較多時,采用這種方式可以大大節(jié)約IO資源。
下面代碼是這種矩陣鍵盤的驅(qū)動,delay10ms()根據(jù)具體的情況定義。
?
#define key_port P2
?
//檢測按鍵的返回值,可以檢測多個按鍵,返回一個16位的unsigned int型變量,某一個按鍵按下,相應(yīng)位置“1”
unsigned int KeyBoard_scan(void)
{
unsigned int ms=0,value=0;
key_port=0x0f;
while(key_port!=0x0f)
{
delay10ms();
if(key_port!=0x0f)
{
key_port=0x7f;
value |= (key_port^0x7f);
key_port=0xbf;
value |= (key_port^0xbf)<<4;
key_port=0xdf;
value |= (key_port^0xdf)<<8;
key_port=0xef;
value |= (key_port^0xef)<<12;
}
key_port=0x0f;
}
return value;
}
//檢測單個按鍵,value參數(shù)會寫回相應(yīng)鍵值0-15,返回值表示按鍵按下的時間,ms計
unsigned int KeyBoard(unsigned char *value)
{
unsigned int ms=0;
key_port=0x0f;
if(key_port!=0x0f)
{
delay10ms();
if(key_port!=0x0f)
{
ms=10;
key_port=0X0f;
switch(key_port)
{
case(0X07): *value=0;break;
case(0X0b): *value=1;break;
case(0X0d): *value=2;break;
case(0X0e): *value=3;break;
default: *value=0xff;
}
key_port=0Xf0;
switch(key_port)
{
case(0X70): *value=*value;break;
case(0Xb0): *value=*value+4;break;
case(0Xd0): *value=*value+8;break;
case(0Xe0): *value=*value+12;break;
default: *value=0xff;
}
while((key_port!=0xf0))
{
delay_ms_keyboard(1);
ms++;
}
return ms;
}
else *value=0xff;
}
else *value=0xff;
return 0;
}
?
3.5?蜂鳴器
蜂鳴器分為有源蜂鳴器和無源蜂鳴器兩種。
有源蜂鳴器用低電平就可以觸發(fā),發(fā)出的聲音頻率不會發(fā)生變化。
無源蜂鳴器需要用脈沖觸發(fā),脈沖的頻率決定了聲音的頻率。
無源蜂鳴器的驅(qū)動電路如下:
審核編輯:湯梓紅
評論