1. IO介紹
51單片機總的管腳有40個,但是其中能夠作為IO使用的只有32個,每8個分為一組,共4組。單片機要想實現預定功能必然要使用到各種IO口,來完成各項功能,包括點亮LED,連接按鍵、鍵盤,各種I2C、SPI設備等。51單片機,4組IO的結構略有不同,使用時應當注意。
P0屬于雙向IO,內部沒有上拉電阻,作為輸出時,最好外加上拉電阻。
P1、P2、P3屬于準雙向IO。“準”體現在輸入時,必須先輸出“1”,才能正確讀到IO的輸入情況。
?
P3口的各個IO均有復用功能:
2. IO編程
對于IO的操作無非是讀輸入和寫輸出,通過讀寫相應的寄存器(P0、P1、P2、P3)就可以實現。
?
2.1 字節尋址
字節尋址可以一次把8個IO全部訪問了,使用時把Px(x=0、1、2或3)當作無符號字符變量(unsigned char)即可。
2.2 位尋址
51單片機有一類特殊的變量——位變量(bit),可以用來保存“0”或者“1”。
為了讀寫某個IO,可以定義特殊位變量(sbit)指定某一個IO,再進行讀寫
?
#include "reg52.h"
sbit LED=P1^0;
bit temp;
void main()
{
temp=LED;//確保temp為位變量(bit)
LED=1;
LED=0;
LED=temp;
}
?
3.常用器件的驅動電路
3.1 LED
單片機能夠提供的電流有限,一般采用這種方式驅動LED:
當P2^0=1是,LED兩端電壓差位0V,LED不發光。當P2^0=1是,LED兩端存在電壓差,LED發光,串聯電阻的作用在于限流,阻值根據電源電壓和LED工作電流決定
?
3.2?數碼管。
數碼管本質是發光二極管按照一定位置排列的顯示數字的器件,可分為共陰極和共陽極兩類。按照數量可分為一位,兩位,四位甚至八位。
一位七段共陽極數碼管:
有的數碼管有八段,右下角會增加一個小數點。
?
當驅動兩位8段數碼管時,按上面的方式會占用16個IO,這種方式成為靜態顯示。靜態顯示可以控制每一個數碼管,但是會極大的占用IO資源,當數碼管數量較多時,這種方式明顯不適合。
?
與靜態相對應的是動態顯示。每一個數碼管顯示一段時間,然后在切換到下一個。根據人眼的視覺暫留效應,只要刷新的頻率超過24Hz,在人眼中就是連續的。把每一位數碼管的a,b,c,d,e,f,g,dp接在同一組IO上,再用另一組IO來控制具體顯示哪一個數碼管(公共端)。
?
下面四位共陰極數碼管示例,公共端用三極管做開關:
數碼管顯示段碼如下
?
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”。如下圖,當按鍵按下,P1^0=0, 當按鍵松開,P1^0=1。
但實際上,由于開關接觸瞬間,電壓會產生不穩定的跳變,稱為抖動,如下圖:
抖動的時間小于10ms,因此當我們檢測到電平變化是,延時10ms即可。
?
3.4 鍵盤
通過把按鍵組成4x4矩陣,可以使用8個IO連接16個按鍵。當按鍵數量較多時,采用這種方式可以大大節約IO資源。
下面代碼是這種矩陣鍵盤的驅動,delay10ms()根據具體的情況定義。
?
#define key_port P2
?
//檢測按鍵的返回值,可以檢測多個按鍵,返回一個16位的unsigned int型變量,某一個按鍵按下,相應位置“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參數會寫回相應鍵值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?蜂鳴器
蜂鳴器分為有源蜂鳴器和無源蜂鳴器兩種。
有源蜂鳴器用低電平就可以觸發,發出的聲音頻率不會發生變化。
無源蜂鳴器需要用脈沖觸發,脈沖的頻率決定了聲音的頻率。
無源蜂鳴器的驅動電路如下:
審核編輯:湯梓紅
評論
查看更多