一、實驗目的- 學習掌握Proteus仿真軟件;
- 熟悉C51編程;
- 掌握按鍵、LED顯示綜合編程。
二、實驗設備和器件
三、實驗原理圖
圖1 采用單片機I/O端口實現的鍵盤顯示接口電路
實際應用中經常采用單片機的I/O端口實現矩陣鍵盤及LED數碼管顯示接口功能,具體電路如圖3所示。單片機P3口用于矩陣鍵盤接口,P3.0~P3.3作為行掃描輸出線,P3.4~P3.7作為讀列輸入線;P0口和P2口用于LED數碼管顯示接口,從P0口輸出顯示段碼,P2口輸出顯示數位。 四、實驗內容- 將按鍵內容顯示在最右邊的LED上。
- 初始顯示0~7,實現按鍵右移顯示。即;初始顯示01234567,按1后,顯示10123456,按2后顯示21012345,以此類推。
- 自主設計一種按鍵+顯示程序。
五.實驗代碼及結果5.1問題一代碼及結果 
- #include <reg51.h>
- #include <absacc.h>
- #define uchar unsigned char
- #define uint unsigned int
- uchar key1=16;//全局變量,key1為鍵碼,定義為16是為了讓初始時燈滅
- uchar code value[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,
- 0x5e,0x79,0x71,0x00}; //0~F的字段碼表
- //延時函數
- void delay(uint i)
- {
- uint j;
- for(i=0;j<i;j++){}
- }
- //判斷是否按鍵
- uchar checkkey()
- {
- uchar key;
- P3 = 0xF0;//
- key = ~P3 & 0xff;//無鍵按下返回0fh
- return ( key);
- }
- //顯示函數
- void display(void)
- {
- P2=0x7f; //僅亮第8個燈
- P0=value[key1]; //鍵值
- }
- //求按鍵值,沒有按鍵返回0ff,按鍵返回鍵值
- unsigned char key(void)
- {
- unsigned char row,col=0,k=0xff,dd,scan;// 定義行、列、返回值
- scan=0xfe; // 行掃描碼
- for(row=0;row<4;row++) // 行掃描
- {
- P3=scan; dd=P3/16; // 行掃描值送P3
- if(dd!=0x0f) // 列線不全為1 ,進入列掃描
- {
- switch(dd&0x0f)//用case語句求鍵值
- {
- case(0x0e):k=0x00+row*4; break;
- case(0x0d):k=0x01+row*4; break;
- case(0x0b):k=0x02+row*4; break;
- case(0x07):k=0x03+row*4; break;
- }
- }
- scan=scan*2+1; // 左移1位
- }
- return k; // 返回鍵值
- }
- void main(void)
- {
- while(1)
- {
- while(checkkey()==0x0f)//沒有按鍵則顯示當前的數字
- {
- display();
- }
- key1=key(); //有按鍵求鍵值
- }
- }
復制代碼
5.2問題二結果及代碼
- <font color="rgb(0, 0, 0)">#include <reg51.h>
- #include <absacc.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- uchar key1=16;//全局變量,key1為鍵碼,定義為16是為了讓初始時燈滅
- uchar code value[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,
- 0x5e,0x79,0x71,0x00}; //0~F的字段碼表
- uchar buf[8]={0,1,2,3,4,5,6,7};
- //延時函數
- void delay(uint i)
- {
- uint j;
- for(i=0;j<i;j++){}
- }
- //判斷是否按鍵
- uchar checkkey()
- {
- uchar key;
- P3 = 0xF0;//
- key = ~P3 & 0xff;//無鍵按下返回0fh
- return ( key);
- }
- //顯示函數
- void display(void)
- {
- uchar i,p,scan=0xfe;
- for(i=0;i<8;i++)
- {
- p=buf[i];
- P2=scan;
- P0=value[buf[i]];
- delay(1000);
- scan=_crol_(scan,1);
- }
- }
- //求按鍵值,沒有按鍵返回0ff,按鍵返回鍵值
- unsigned char key(void)
- {
- unsigned char row,col=0,k=0xff,dd,scan;// 定義行、列、返回值
- scan=0xfe; // 行掃描碼
- for(row=0;row<4;row++) // 行掃描
- {
- P3=scan; dd=P3/16; // 行掃描值送P3
- if(dd!=0x0f) // 列線不全為1 ,進入列掃描
- {
- switch(dd&0x0f)//用case語句求鍵值
- {
- case(0x0e):k=0x00+row*4; break;
- case(0x0d):k=0x01+row*4; break;
- case(0x0b):k=0x02+row*4; break;
- case(0x07):k=0x03+row*4; break;
- }
- }
- scan=scan*2+1; // 左移1位
- }
- while(checkkey()!=0x0f);
- return k; // 返回鍵值
- }
- void main(void)
- {
- while(1)
- {
- key1=key();
- if(key1!=0xff)
- {
- buf[7]=buf[6];
- buf[6]=buf[5];
- buf[5]=buf[4];
- buf[4]=buf[3];
- buf[3]=buf[2];
- buf[2]=buf[1];
- buf[1]=buf[0];
- buf[0]=key1;
- }
- display();
- }
- }</font>
復制代碼
5.3問題三結果及代碼
實現功能為:計算并顯示個位數的一次減法。手動按鍵,前10個鍵為數字1-9,第11個鍵為減號,第12個鍵為等號。當按鍵時,第一個燈會顯示相應的數,例如輸入按鍵‘8-2=’,第一個燈會依次顯示按鍵對應的字符,當再按‘=’時,就會顯示減法結果。弊端是只能算個位減法,僅能算一次,只有第一個燈可以顯示輸入的數值,不能動態顯示。
 - #include <reg51.h>
- #include <absacc.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- uchar key1=12;//全局變量,key1為鍵碼,定義為16是為了讓初始時燈滅
- uchar key2,key3;//全局變量,key1為鍵碼,定義為16是為了讓初始時燈滅
- uchar code value[13]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x09,0x00};//0-9,減號,等號
- uchar buf[13]={0,1,2,3,4,5,6,7,9,10,11,12};
- //延時函數
- void delay(uint i)
- {
- uint j;
- for(i=0;j<i;j++){}
- }
- //判斷是否按鍵
- uchar checkkey()
- {
- uchar key;
- P3 = 0xF0;//
- key = ~P3 & 0xff;//無鍵按下返回0fh
- return ( key);
- }
- //顯示函數
- void display(void)
- {
- uchar scan=0xfe;
- P2=scan;
- P0=value[key1];
- }
- //求按鍵值,沒有按鍵返回0ff,按鍵返回鍵值
- unsigned char key(void)
- {
- unsigned char row,col=0,k=0xff,dd,scan;// 定義行、列、返回值
- scan=0xfe; // 行掃描碼
- for(row=0;row<4;row++) // 行掃描
- {
- P3=scan; dd=P3/16; // 行掃描值送P3
- if(dd!=0x0f) // 列線不全為1 ,進入列掃描
- {
- switch(dd&0x0f)//用case語句求鍵值
- {
- case(0x0e):k=0x00+row*4; break;
- case(0x0d):k=0x01+row*4; break;
- case(0x0b):k=0x02+row*4; break;
- case(0x07):k=0x03+row*4; break;
- }
- }
- scan=scan*2+1; // 左移1位
- }
- while(checkkey()!=0x0f);
- return k; // 返回鍵值
- }
- void main(void)
- { uchar i=0,j=0;
- while(1)
- {
- key1=key();
- if(key1!=0xff)//如果有鍵按下
- {
- if(i==0)//如果被減數按下,鍵值賦給key2
- {key2=key1;}
- if(i==2)
- {key3=key1;}//如果減數按下,鍵值賦給key3
- if(i==4)
- {
- key1=key2-key3;//如果(被減數-減數=)操作完成,則再按=,顯示減法結果
- }
- display();
- i++;
- }
- }
- }
復制代碼
6.實驗總結
我認為實驗比較難的地方是按鍵會有延時,而機器的處理速度太快,這就導致預期的結果和實際顯示的效果不一致。因此在編輯代碼時,一定要考慮到手按鍵會有延時的影響。
在求按鍵值的子程序里,什么時候把按鍵值返回需要根據不同的實驗做相應的改變,例如:按鍵結束后返回按鍵值,和按鍵時返回鍵值的效果是不一樣的,這也導致在主程序中判斷按鍵是否產生的不同。在問題二中,我就是因為沒有在按鍵結束后返回鍵值,導致不能產生正確效果。
If里邊不能嵌套for語句,在實驗一中掃描列時,我嵌套了for,導致程序不能進入for循環。后來我改成了case語句才成功。
以上的Word格式文檔51黑下載地址:
實驗10.docx
(219.4 KB, 下載次數: 7)
2020-5-26 21:50 上傳
點擊文件名下載附件
|