為學習嵌入式做準備,重新拿起51單片機學習。此貼為學習筆記,僅記錄易忘點,實用理論基礎,并不是0基礎。
資料參考:清翔零基礎教你學51單片機
51單片機學習筆記
- 1. C語言中的易忘點
- 1.1 數據類型
- 1.2 位運算符
- 1.3 常用控制語句
- 1.4 C51程序的基本結構
- 2.電子電路基礎
- 2.1 電平
- 2.2 I/O(引腳)
- 2.2.1 P3口的第二用途
- 2.3 電子元器件
- 2.3.1 電阻:
- 2.3.2 電容:
- 2.3.3 蜂鳴器
- 2.3.3.1 判斷有源蜂鳴器和無源蜂鳴器
- 2.3.3.2 驅動蜂鳴器
- 2.3.4 常見符號
- 3.單片機 基礎知識點
- 3.1 單片機最小系統
- 3.2 基本時序
- 4. 51單片機基礎例程(I/O外設)
- 4.1 點亮LED燈
- 4.1.1編程知識點
- 4.1.1.1 位定義
- 4.1.2 編程
- 4.2 LED閃爍
- 4.2.1 編程知識點
- 4.2.1.1 變量作用域
- 4.2.1.2 軟件延時
- 4.2.2 編程
- 4.3 流水燈
- 4.3.1 編程知識點
- 4.3.1.1宏定義
- 4.3.1.2 函數的定義
- 4.3.1.3 延時函數
- 4.3.1.4 循環移位函數
- 4.3.1.4.1 循環移位函數與左移和右移運算符的區別
- 4.3.2 編程
- 4.4 數碼管靜、動態顯示
- 4.4.1 單個數碼管--==靜態==顯示原理
- 4.4.2 74HC573鎖存器工作原理
- 4.4.3 多個數碼管--==動態==顯示原理
- 4.4.4 編程知識點
- 4.4.4.1 數組的定義與引用
- 4.4.5 編程
- 4.4.5.1 共陰極數碼管,靜態顯示(只亮一個數碼管)
- 4.4.5.2 共陰極數碼管,動態顯示
- 4.5 非編碼鍵盤
- 4.5.1 獨立鍵盤
- 4.5.2 矩陣鍵盤
- 1.硬件接線
- 2.掃描
- 4.5.3 編程知識點
- 4.5.3.1程序去抖
- 4.5.3.2 開關語句
- 4.5.4 編程
- 4.5.4.1 獨立鍵盤
- 4.5.4.2 矩陣鍵盤
1. C語言中的易忘點
1.1 數據類型
1.2 位運算符
~ 按位取反
<< 左移
>> 右移
& 按位與
^ 按位異或
| 按位或
異或:相同取0,不同取1.
1.3 常用控制語句
條件 if
循環while 、 for
開關switch
1.4 C51程序的基本結構
#include <reg52.h> //包含51單片機頭文件void main() //主函數
{}
C語言設置的程序中只允許有一個main函數。程序總是從main函數開始運行的,main函數是void型(無返回值)。
2.電子電路基礎
2.1 電平
數字電路中只有兩種電平:高電平和低電平。
高電平:5V
低電平:0V
TTL電平規定高電平輸出電壓>2.4V,低電平輸出電壓<0.4V
計算機串口使用的是RS232電平
高電平:-12V
低電平:+12V
Tips:單片機與計算機串口通信時需要使用電平轉換芯片,把RS232電平轉為TTL電平后單片機才能識別。
2.2 I/O(引腳)
例程中
P0接LED,P2^3接蜂鳴器。
2.2.1 P3口的第二用途
2.3 電子元器件
2.3.1 電阻:
常用的貼片電阻封裝:0402、0603、0805、1206、1210
貼片電阻讀數參考:貼片電阻上的字符是如何表示電阻的?
103,那么10是有效數字,3表示10的3次方,所以103表示的阻值就是10x10^{3}
1502,150是有效數字,2表示10的2次方,所以,1502表示的阻值就是150*10^{2}
5R6=5.6Ω、R16=0.16Ω
01C就是10k
2.3.2 電容:
電容的作用:儲能,濾波,通交流隔直流,旁路,耦合,補償,充放電等
1F(法拉) = 1000000μF(微法)
1μF(微法)= 1000nF(納法)
1nF(納法) = 1000pF(皮法)
2.3.3 蜂鳴器
2.3.3.1 判斷有源蜂鳴器和無源蜂鳴器
可以用萬用表電阻檔Rxl檔測試:用黑表筆接蜂鳴器 "+"引腳,紅表筆在另一引腳上來回碰觸,如果觸發出咔、咔聲的且電阻只有8Ω(或16Ω)的是無源蜂鳴器;如果能發出持續聲音的,且電阻在幾百歐以上的,是有源蜂鳴器。
2.3.3.2 驅動蜂鳴器
由于蜂鳴器的工作電流一般比較大,以致于單片機的I/O 口是無法直接驅動的,所以要利用放大電路來驅動,一般使用三極管來放大電流就可以了。
(除此之外還有一些其他驅動方式:PWM 輸出口直接驅、I/O 口定時翻轉電平驅動蜂鳴器方式)
2.3.4 常見符號
3.單片機 基礎知識點
3.1 單片機最小系統
電源 (給整個系統提供能量)
單片機芯片 (運行程序/處理數據)
晶振電路 (給單片機工作提供節拍)
復位電路 (單片機上電時需要復位使程序從頭開始運行)
3.2 基本時序
振蕩周期: 也稱時鐘周期, 是指為單片機提供時鐘脈沖信號的振蕩源的周期。
機器周期: 一個機器周期包含 12 個時鐘周期。 在一個機器周期內, CPU可以完成一個獨立的操作。
例如計算外部晶振頻率為11.0592Mhz的單片機一個機器周期所需的時間:
1/11.0592 * 12 ≈ 1.085μS
說明:“1/(11.0592*1000000)”乘以106把Mhz轉為hz再乘以“12”是12個時鐘周期等于一個機器周期最終值為秒,把這個單位為秒的值乘以106所得值約等于1.085微秒。
4. 51單片機基礎例程(I/O外設)
例程中LED位共陽極!
要點亮開發板上LED燈只需要控制P1口輸出低電平即可
(編程時給P1口賦值“0”)
4.1 點亮LED燈
普通發光二極管工作壓降為:1.6v ~ 2.1 V。
工作電流為:1~20mA
注意:二極管需要上拉電阻。
否則電流=(5V-2.1V)/0Ω,電流無限大
有電阻后,電流=(5V-2.1V)/1kΩ,約等于3mA.
4.1.1編程知識點
4.1.1.1 位定義
關鍵字:sbit
功能:位定義
一般格式: sbit 標識符 = 地址值;
例如:sbit LED1 = P1^0;
注意:地址值中P1的“P”必須為大寫的P
4.1.2 編程
#include <reg52.h> //引用51頭文件sbit LED1 = P1^0; //位定義void main() //主函數
{LED1 = 0;//點亮P1.0上的LED
}
4.2 LED閃爍
4.2.1 編程知識點
4.2.1.1 變量作用域
全局變量:在函數體外定義的變量通常為全局變量,作用范圍:從定義開始的整個程序局部變量:在函數體內定義的變量通常為局部變量,作用范圍:函數體內
4.2.1.2 軟件延時
軟件延時例如:
unsigned int i;
i=65535;
while(i);
4.2.2 編程
實現:P1口上所有LED閃爍
#include <reg52.h>//包含51頭文件unsigned int i;//0~65535void main()//main函數自身會循環
{while(1)//大循環{P1 = 0; //點亮P1口8個LEDi = 65535;while(i--);//軟件延時P1 = 0xff;//1111 1111 熄滅P1口8個LEDi = 65535;while(i--);//軟件延時 }
}
按位取反 閃爍寫法:
#include <reg52.h>unsigned int i;//0~65535void main()//main函數自身會循環
{P1 = 0xff;//熄滅8位LEDwhile(1) //大循環{P1 = ~P1; //使用按位取反運算符使LED閃爍i = 65535;while(i--);//軟件延時}
}
4.3 流水燈
4.3.1 編程知識點
4.3.1.1宏定義
理解成 用define/ typedef 取小名
#define uchar unsigned char
注意宏定義后面不能加分號,它是預處理指令不是語句。
其中用“uchar”直接替換了unsigned char
此時我們可以用uchar去定義變量類型如:uchar i;等價于unsigned char i;
【C語言】typedef與define的區別
typedef,我們可以為基本類型(如int、float)或自定義的結構體、聯合體等定義新的名稱。define,定義常量、函數替換宏、條件編譯等,它的作用范圍更為廣泛。所有滿足條件的宏定義在預處理階段都會被替換為指定的文本。
4.3.1.2 函數的定義
自定義函數一般格式為:
函數類型 函數名 (形式參數表)
{局部變量定義函數體語句
}
4.3.1.3 延時函數
自定義函數:延時函數delay(毫秒級)
void delay(unsigned int z)
{unsigned int x,y;for(x = z; x > 0; x--)for(y = 114; y > 0 ; y--);
}
給形參z賦值,如延時100毫秒:delay(100);
4.3.1.4 循環移位函數
標準庫函數: intrins.h
內部函數:
字符型循環左移:_crol_
字符型循環右移:_cror_
#include <intrins.h>
void test_crol (void) {unsigned char a;unsigned char b;a = 0xFE; //1111 1110b = _crol_(a,1); // b now is 0xFD 二進制為1111 1101
}
4.3.1.4.1 循環移位函數與左移和右移運算符的區別
循環左移是把最高位移到最低位上,
左移運算符是把最高位移除最低位補0
4.3.2 編程
實現:流水燈一直左循環
#include <reg52.h> //包含51頭文件
#include <intrins.h> //包含移位標準庫函數頭文件#define uint unsigned int
#define uchar unsigned charuchar temp;//LED燈相關變量
/*====================================
函數 : delay(uint z)
參數 :z 延時毫秒設定,取值范圍0-65535
返回值 :無
描述 :12T/Fosc11.0592M毫秒級延時
====================================*/
void delay(uint z)
{uint x,y;for(x = z; x > 0; x--)for(y = 114; y > 0 ; y--);
} void main()//main函數自身會循環
{temp = 0xfe;P1 = temp; //1111 1110 初值LED1亮delay(100);//毫秒級延時 100毫秒while(1){temp = _crol_(temp, 1);//循環左移P1 = temp;//移位完成后賦值給P1 每個一個燈點亮delay(100);//毫秒級延時 100毫秒}
}
4.4 數碼管靜、動態顯示
4.4.1 單個數碼管–靜態顯示原理
有共陽、共陰極,例程使用共陰!即b圖左邊。
共陰極數碼碼表:
0x3F, //"0"
0x06, //"1"
0x5B, //"2"
0x4F, //"3"
0x66, //"4"
0x6D, //"5"
0x7D, //"6"
0x07, //"7"
0x7F, //"8"
0x6F, //"9"
0x77, //"A"
0x7C, //"B"
0x39, //"C"
0x5E, //"D"
0x79, //"E"
0x71, //"F"
0x76, //"H"
0x38, //"L"
0x40, //"-"
0x00, //熄滅
4.4.2 74HC573鎖存器工作原理
鎖存器作用:可以把數據輸入端與輸出端進行隔離或連接
左邊D為輸入,右邊Q為輸出
輸出口Q要想輸出高低電平OE腳必須接GND。
LE腳為高時,輸出端Q隨輸入端D的數據而變化。
LE腳為低時,輸出端Q數據保持不變,輸入端D數據變化不會改變Q的數據。
4.4.3 多個數碼管–動態顯示原理
段選和位選
位選:選擇哪一個數碼管亮
段選:該數碼管怎么亮(數碼管里的二極管怎么亮)
工作流:
打開位選鎖存器->指定某個數碼管->關閉位選鎖存器,
打開段選鎖存器->指定亮什么數字->關閉段選鎖存器,
因為掃描周期短,所以肉眼可以看到多數碼管同時亮 不同的數字。
4.4.4 編程知識點
4.4.4.1 數組的定義與引用
數組是一組有序數據的集合,數組中每一個數據都是同一數據類型。數組中的元素可以用數組名和下標來唯一確定。
數組的一般格式定義如下:
數據類型 數組名[常量表達式] = {元素表};
例如:
unsigned char tabel[3] ={0x3F, 0x06, 0x5B, };
P0 = tabel[0]; //P0此時的值為0x3F
4.4.5 編程
4.4.5.1 共陰極數碼管,靜態顯示(只亮一個數碼管)
#include <reg52.h>
#include <intrins.h>#define uint unsigned int
#define uchar unsigned charsbit DU = P2^6;//數碼管段選
sbit WE = P2^7;//數碼管位選////毫秒級延時函數定義
//void delay(uint z)
//{
// uint x,y;
// for(x = z; x > 0; x--)
// for(y = 114; y > 0 ; y--);
//} void main()//main函數自身會循環
{WE = 1;//打開位選鎖存器P0 = 0XFE; //1111 1110 選通第一位數碼管WE = 0;//鎖存位選數據DU = 1;//打開段選鎖存器P0 = 0X06;//0000 0110 顯示“1”DU = 0;//鎖存段選數據while(1){}
}
4.4.5.2 共陰極數碼管,動態顯示
#include <reg52.h>//包含51頭文件
#include <intrins.h>//包含移位標準庫函數頭文件#define uint unsigned int
#define uchar unsigned charsbit DU = P2^6;//數碼管段選
sbit WE = P2^7;//數碼管段選//共陰數碼管段選表0-9
uchar code tabel[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};/*====================================
函數 : delay(uint z)
參數 :z 延時毫秒設定,取值范圍0-65535
返回值 :無
描述 :12T/Fosc11.0592M毫秒級延時
====================================*/
void delay(uint z)
{uint x,y;for(x = z; x > 0; x--)for(y = 114; y > 0 ; y--);
} /*====================================
函數 :display(uchar i)
參數 :i 顯示數值,取值范圍0-255
返回值 :無
描述 :三位共陰數碼管動態顯示
====================================*/
void display(uchar i)
{uchar bai, shi, ge;bai = i / 100; //236 / 100 = 2shi = i % 100 / 10; //236 % 100 / 10 = 3ge = i % 10;//236 % 10 =6//第一位數碼管 P0 = 0XFF;//清除斷碼WE = 1;//打開位選鎖存器P0 = 0XFE; //1111 1110WE = 0;//鎖存位選數據DU = 1;//打開段選鎖存器P0 = tabel[bai];//DU = 0;//鎖存段選數據delay(5);//第二位數碼管P0 = 0XFF;//清除斷碼WE = 1;//打開位選鎖存器P0 = 0XFD; //1111 1101WE = 0;//鎖存位選數據DU = 1;//打開段選鎖存器P0 = tabel[shi];//DU = 0;//鎖存段選數據delay(5);//第三位數碼管P0 = 0XFF;//清除斷碼WE = 1;//打開位選鎖存器P0 = 0XFB; //1111 1011WE = 0;//鎖存位選數據DU = 1;//打開段選鎖存器P0 = tabel[ge];//DU = 0;//鎖存段選數據delay(5);
}void main()//main函數自身會循環
{ while(1){display(236); //數碼管顯示函數}
}
4.5 非編碼鍵盤
4.5.1 獨立鍵盤
每個按鍵占用一個IO口,當按鍵數量較多時,IO口利用效率不高,
但程序簡單,適用于所需按鍵較少的場合。
按鍵一端與IO口連接,另外一端接地。I/O進行檢測,
按鍵按下會被檢測到低電平,未按下被檢測為高電平。
4.5.2 矩陣鍵盤
電路連接復雜,但提高了IO口利用率,軟件編程較復雜。
適用于使用大量按鍵的場合。
上圖為4行和4列,一共16個按鍵組成。
確定矩陣鍵盤上哪一個按鍵被按下可以采用列掃描和行掃描。
列掃描時先把接在列上面的所有IO口拉高,接在行上的所有IO置低。
當其中有一列內任何一個按鍵按下那么整條列線都會被拉低。
1.硬件接線
P3口的高4位(P3.4~P3.7)作為列線(輸出)
P3口的低4位(P3.0~P3.3)作為行線(輸入)
uchar cord_l,cord_h;//聲明列線和行線的值的儲存變量P3 = 0xf0;//1111 0000
2.掃描
掃描分為兩步:列掃描和行掃描,通過檢測電平變化確定按鍵位置。
step1–列判斷:行線(P3.0 ~ P3.7)為0,列線(P3.4 ~ P3.7)為1,即P3=0xf0。
當四列中,某一列被按下,列線的對應的值就會改變。
cord_l = P3 & 0xf0;// 只儲存列線值 (f0的0作用:無論行線是多少,都不保存,寫0)
例:2行2列的S11按下,讀到L=0xd0(圖中從下P37往上P30,1101 0000)
step2–行判斷:在列判斷后,保留讀到的列線值,行線值寫1。即用讀到的列線值 或 0x0f。
例:0xd0|0x0f (1101 0000|00001111)得到1101 1111,
2行2列的S11按下,導致P31的1變為0,即變為1101 1101 (0xdd)
0xdd&0x0f=0x0d,此為行線值
P3 = cord_l | 0x0f;cord_h = P3 & 0x0f;// 只儲存行線值(0f的0作用:無論列線是多少,都不保存,寫0)
step3:
列線值+行線值
return (cord_l + cord_h);//返回鍵值碼
4.5.3 編程知識點
4.5.3.1程序去抖
if(key_s3 == 0)//判斷S3是否被按下{delay(20);//按鍵消抖if(key_s3 == 0){...while(!key_s3);//松手檢測} }
4.5.3.2 開關語句
switch (表達式)
{case 常量表達式1: 語句1break;case 常量表達式2: 語句2break;}
4.5.4 編程
4.5.4.1 獨立鍵盤
實現:按下開發板左下角S2按鍵數碼管值+1,最大到9按下S3按下,值減一,最小減到0
#include <reg52.h>
#include <intrins.h>#define uint unsigned int
#define uchar unsigned charsbit DU = P2^6;//數碼管段選
sbit WE = P2^7;//數碼管位選
sbit key_s2 = P3^0;//獨立按鍵S2
sbit key_s3 = P3^1;//獨立按鍵S3
uchar num;//數碼管顯示的值//共陰數碼管段選表0-9
uchar code tabel[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};//毫秒級延時函數定義
void delay(uint z)
{uint x,y;for(x = z; x > 0; x--)for(y = 114; y > 0 ; y--);
} void main()//main函數自身會循環
{ num = 0; WE = 1;//打開位選鎖存器P0 = 0XFE; //1111 1110WE = 0;//鎖存位選數據while(1){if(key_s2 == 0)//判斷S2是否被按下{delay(20);//按鍵消抖if(key_s2 == 0){if(num != 9)//如果值不等于9則+1,功能把值限定為小于9num++;while(!key_s2);//松手檢測} }if(key_s3 == 0)//判斷S3是否被按下{delay(20);//按鍵消抖if(key_s3 == 0){if(num > 0) //如果大于0則執行減一num--;while(!key_s3);//松手檢測} }//松手之后刷新顯示DU = 1;//打開段選鎖存器P0 = tabel[num];//DU = 0;//鎖存段選數據}
}
4.5.4.2 矩陣鍵盤
實現:矩陣鍵盤
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit we = P2^7;
sbit du = P2^6;
uchar code leddata[]={ 0x3F, //"0"0x06, //"1"0x5B, //"2"0x4F, //"3"0x66, //"4"0x6D, //"5"0x7D, //"6"0x07, //"7"0x7F, //"8"0x6F, //"9"0x77, //"A"0x7C, //"B"0x39, //"C"0x5E, //"D"0x79, //"E"0x71, //"F"0x76, //"H"0x38, //"L"0x37, //"n"0x3E, //"u"0x73, //"P"0x5C, //"o"0x40, //"-"0x00, //熄滅0x00 //自定義};
void delay(uint z)
{uint x,y;for(x = z; x > 0; x--)for(y = 114; y > 0 ; y--);
}uchar KeyScan() //帶返回值的子函數
{uchar cord_l,cord_h;//聲明列線和行線的值的儲存變量P3 = 0xf0;//1111 0000if( (P3 & 0xf0) != 0xf0)//判斷是否有按鍵按下{delay(5);//軟件消抖if( (P3 & 0xf0) != 0xf0)//判斷是否有按鍵按下{cord_l = P3 & 0xf0;// 儲存列線值P3 = cord_l | 0x0f;cord_h = P3 & 0x0f;// 儲存行線值while( (P3 & 0x0f) != 0x0f );//松手檢測return (cord_l + cord_h);//返回鍵值碼} }}void KeyPro()
{switch( KeyScan() ){//第一行鍵值碼case 0xee: P0 = leddata[0]; break;case 0xde: P0 = leddata[1]; break;case 0xbe: P0 = leddata[2]; break;case 0x7e: P0 = leddata[3]; break;//第二行鍵值碼case 0xed: P0 = leddata[4]; break;case 0xdd: P0 = leddata[5]; break;case 0xbd: P0 = leddata[6]; break;case 0x7d: P0 = leddata[7]; break;//第三行鍵值碼case 0xeb: P0 = leddata[8]; break;case 0xdb: P0 = leddata[9]; break;case 0xbb: P0 = leddata[10]; break;case 0x7b: P0 = leddata[11]; break;//第四行鍵值碼case 0xe7: P0 = leddata[12]; break;case 0xd7: P0 = leddata[13]; break;case 0xb7: P0 = leddata[14]; break;case 0x77: P0 = leddata[15]; break;}
}void main()
{we = 1;//打開位選P0 = 0;//八位數碼管全顯示we = 0;//鎖存位選du = 1;//打開段選端P0 = leddata[22];while(1){KeyPro();//提取鍵值碼并且送不同數值給數碼管顯示}
}
實現:按下矩陣鍵盤和獨立鍵盤任意鍵,數碼管顯示相應數值初始顯示“-”橫
#include <reg52.h>//包含51頭文件
#include <intrins.h>//包含移位標準庫函數頭文件#define uint unsigned int
#define uchar unsigned charsbit DU = P2^6;//數碼管段選
sbit WE = P2^7;//數碼管段選
uchar num;//數碼管顯示的值
uchar KeyValue = 20;//按鍵值 顯示-//共陰數碼管段選表
uchar code tabel[]= {
//0 1 2 3 4 5 6 7 8
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F,
//9 A B C D E F H L
0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x76, 0x38,
//n u - 熄滅
0x37, 0x3E, 0x40, 0x00 };/*====================================
函數 : delay(uint z)
參數 :z 延時毫秒設定,取值范圍0-65535
返回值 :無
描述 :12T/Fosc11.0592M毫秒級延時
====================================*/
void delay(uint z)
{uint x,y;for(x = z; x > 0; x--)for(y = 114; y > 0 ; y--);
}
/*====================================
函數 :KeyScan()
參數 :無
返回值 :無
描述 :4*4矩陣鍵盤與獨立鍵盤掃描
按鍵按下KeyValue全局變量值發生相應變化
====================================*/
void KeyScan()
{//4*4矩陣鍵盤掃描P3 = 0XF0;//列掃描if(P3 != 0XF0)//判斷按鍵是否被按下{delay(10);//軟件消抖10msif(P3 != 0XF0)//判斷按鍵是否被按下{switch(P3) //判斷那一列被按下{case 0xe0: KeyValue = 0; break;//第一列被按下case 0xd0: KeyValue = 1; break;//第二列被按下case 0xb0: KeyValue = 2; break;//第三列被按下case 0x70: KeyValue = 3; break;//第四列被按下 }P3 = 0X0F;//行掃描switch(P3) //判斷那一行被按下{case 0x0e: KeyValue = KeyValue; break;//第一行被按下case 0x0d: KeyValue = KeyValue + 4; break;//第二行被按下case 0x0b: KeyValue = KeyValue + 8; break;//第三行被按下case 0x07: KeyValue = KeyValue + 12; break;//第四行被按下 }while(P3 != 0X0F);//松手檢測 }}P3 = 0XFF;//獨立按鍵掃描if(P3 != 0XFF){delay(10);//軟件消抖10msif(P3 != 0XFF){switch(P3) //判斷那一行被按下{case 0xfe: KeyValue = 16; break;//S2被按下case 0xfd: KeyValue = 17; break;//S3被按下case 0xfb: KeyValue = 18; break;//S4被按下case 0xf7: KeyValue = 19; break;//S5被按下 }while(P3 != 0XFF);//松手檢測 } }}void main()//main函數自身會循環
{WE = 1;//打開位選鎖存器P0 = 0XFE; //1111 1110WE = 0;//鎖存位選數據DU = 1;//打開段選鎖存器while(1){KeyScan();//20個按鍵鍵盤掃描P0 = tabel[KeyValue];//顯示按鍵值}
}