一、 實驗題目 基于51單片機的簡易計算器 二、 內(nèi)容1、實驗內(nèi)容 該系統(tǒng)通過單片機控制,實現(xiàn)對4*4鍵盤掃描進行實時的按鍵檢測,并把檢測數(shù)據(jù)存儲下來。整個計算器系統(tǒng)的工作過程為:首先存儲單元初始化,顯示初始值和鍵盤掃描,判斷按鍵位置,得出按鍵值,單片機則對數(shù)據(jù)進行儲存與相應處理轉(zhuǎn)換,之后送入數(shù)碼管動態(tài)顯示。整個系統(tǒng)可分為三個主要功能模塊:功能模塊一,實時鍵盤掃描;功能模塊二,數(shù)據(jù)轉(zhuǎn)換為了數(shù)碼管顯示;功能模塊三,數(shù)碼管動態(tài)顯示。 2、功能說明 s1 s2 s3 s4 1 2 3 + s5 s6 s7 s8 4 5 6 - s9 s10 s11 s12 7 8 9 * s13 s14 s15 s16 0 clr = / 本來計劃用數(shù)碼管顯示,結(jié)果發(fā)的單片機數(shù)碼管驅(qū)動芯片與預想的不一樣,不是通過段選,位選的方式。然后就沒看的特別懂,臨時換成了lcd1602顯示屏,驅(qū)動程序較為固定,且顯示的也更加全面。 通過中斷定時器零設置中斷,定時10s,開機10秒后,執(zhí)行中斷,自動清零,相當于自動按下按鍵14。 三、 原理圖見下頁。
四、 實驗記錄因為在課堂上未記錄實驗現(xiàn)象,所以在課下在按照自己的單片機的引腳設置更改了程序后,再將程序下載到51單片機中,得到以下實驗結(jié)果: 剛下入程序時,初始化后的顯示如下: 然后進行一些簡單的計算顯示: 最多可以進行八位數(shù)的運算: 五、 修改后程序框圖
六、總結(jié) 本來在實驗課上由于前期準備不夠充分,課上經(jīng)歷了更改顯示方式,由數(shù)碼管顯示改為了1602液晶屏顯示,且在實驗課上僅完成了計算器的功能,能夠?qū)崿F(xiàn)加減乘除的運算,但是不能實現(xiàn)連續(xù)運算功能。在課下又經(jīng)過充分的學習了解,成功的加上了定時器中斷,實現(xiàn)了定時清屏功能。由此可見,充足的課前準備能夠極大地提高效率。 本次實驗滿足了設計要求,包含有矩陣按鍵的使用,定時器中斷,LCD1602外設,將要求用到的內(nèi)容都成功的聯(lián)系在了一起。雖然該例子中的定時器中斷在實際生活中并不會這樣使用,不過通過這種方式,也讓我對定時器中斷的使用有了更加深刻的認識,也能夠通過定時器中斷進行一些簡單的設計。 通過本次實驗,加深了對51單片機原理的理解與認知,尤其是對矩陣按鍵掃描判斷,定時器中斷,LCD1602外設的應用等方面的原理的學習也提高了一個層次。通過本次實驗,提高了自己的邏輯分析能力,發(fā)現(xiàn)問題解決問題的能力。提高了對C語言編程的理解與應用,能夠靈活的運用例程達到自己的設計要求,完成實驗。 七、附錄 - #include "REG52.h"
- typedef unsigned char uint8;
- typedef unsigned int uint16;
- typedef unsigned long ulong;
- uint8 key;//存放按鍵值
- uint8 num,number,t;
- uint8 fuhao;//定義具體的那個符號,是加減還是乘除。
- uint8 flag; //定義有沒有按下符號鍵,這個是統(tǒng)稱
- long a,b,c,d; //定義運算數(shù)據(jù)的第一個和第二個及等于的數(shù)變量
- uint8 k; //定義小數(shù)點后面顯示的位數(shù)
- uint8 biao;
-
- sbit rs = P1^0;
- sbit rw = P1^1;
- sbit e = P1^2; //LCD使能端
- uint8 dat1[]={1,2,3,0x2b-0x30, 4,5,6,0x2d-0x30, 7,8,9,0x2a-0x30, 0,0x01-0x30,0x3d-0x30,0x2b-0x30 };//保存顯示的數(shù)據(jù)
-
- void Delay(unsigned int); //聲明延時函數(shù)
- void InterruptTimer0() ;
-
- void lcdwrc(uint8 c) //寫指令數(shù)據(jù)
- {
- Delay(5);
- rs=0;
- rw=0;
- e=0;
- P0=c;
- e=1;
- Delay(5);
- e=0;
- }
- void lcdwrd(uint8 dat) //寫顯示數(shù)據(jù)
- {
- Delay(5);
- rs=1;
- rw=0;
- e=0;
- P0=dat;
- e=1;
- Delay(5);
- e=0;
- rs=0;
- }
-
- void lcdinit() //lcd初始化
- {
- Delay(7);
- lcdwrc(0x38);
- Delay(3);
- lcdwrc(0x38);
- Delay(3);
- lcdwrc(0x38);
- Delay(3);
- lcdwrc(0x38);
- lcdwrc(0x08);
- lcdwrc(0x01);
- lcdwrc(0x06);
- lcdwrc(0x0c);
- key=0;
- num=0;
- flag=0;
- fuhao=0;
- a=0;
- b=0;
- c=0;
- d=0;
- biao=0;
- }
-
- //函數(shù)名稱:Delay
- //函數(shù)功能:延時函數(shù)
- //入口參數(shù):uiCount-延時參數(shù),每加1增加0.5ms
- void Delay(unsigned int uiCount)
- {
- unsigned char j = 244;
- for(;uiCount > 0;uiCount--) while(--j);
- }
-
- void keyscan() //矩陣按鍵掃描函數(shù)
- {
- P2=0xef; //令第一行為0,然后判斷是哪一列按下
- if(P2!=0xef)
- {
- Delay(5);
- if(P2!=0xef)
- {
- key=P2&0x0f;
- switch(key)
- {
- case 0x0e: num=0;break; //1
- case 0x0d: num=1;break; //2
- case 0x0b: num=2;break; //3
- case 0x07: num=3;break; //加
- }
- }
- while(P2!=0xef);
- if(num==0||num==1||num==2) //確認第一行的數(shù)1,2,3
- {
- if(flag==0) //沒有按下符號鍵
- {
- a=a*10+dat1[num];
- }
- else
- {
- b=b*10+dat1[num];
- }
-
- }
- if(num==3)
- {
- flag=1;
- fuhao=1;//加號+
- }
- lcdwrd(0x30+dat1[num]);
- }
-
-
- P2=0xdf; //令第二行為0,判斷是哪一列按下
- if(P2!=0xdf)
- {
- Delay(5);
- if(P2!=0xdf)
- {
- key=P2&0x0f;
- switch(key)
- {
- case 0x0e: num=4;break; //4
- case 0x0d: num=5;break; //5
- case 0x0b: num=6;break; //6
- case 0x07: num=7;break; //減—
- }
- }
- while(P2!=0xdf);
- if(num==4||num==5||num==6)
- {
- if(flag==0) //沒有按下符號鍵
- {
- a=a*10+dat1[num];
- }
- else
- {
- b=b*10+dat1[num];
- }
- }
- else
- {
- flag=1;
- fuhao=2;//代表減號
- }
- lcdwrd(0x30+dat1[num]);
- }
-
-
- P2=0xbf; //令第三行為0,判斷哪一列按下
- if(P2!=0xbf)
- {
- Delay(5);
- if(P2!=0xbf)
- {
- key=P2&0x0f;
- switch(key)
- {
- case 0x0e: num=8;break; //7
- case 0x0d: num=9;break; //8
- case 0x0b: num=10;break; //9
- case 0x07: num=11;break; //乘*
- }
- }
- while(P2!=0xbf);
- if(num==8||num==9||num==10)
- {
- if(flag==0) //沒有按下符號鍵
- {
- a=a*10+dat1[num];
- }
- else
- {
- b=b*10+dat1[num];
- }
- }
- else
- {
- flag=1;
- fuhao=3;//代表乘號*
- }
- lcdwrd(0x30+dat1[num]);
- }
-
-
- P2=0x7f; //令第四行為0,判斷哪一列按下
- if(P2!=0x7f)
- {
- Delay(5);
- if(P2!=0x7f)
- {
- key=P2&0x0f;
- switch(key)
- {
- case 0x0e: num=12;break; //0
- case 0x0d: num=13;break; //清除rst
- case 0x0b: num=14;break; //等號=
- case 0x07: num=15;break; //除/
- }
- }
- while(P2!=0x7f);
- switch(num)
- {
- case 12:
- if(flag==0) //沒有按下符號鍵
- {
- a=a*10+dat1[num];
- lcdwrd(0x30);
- }
- else
- {
- b=b*10+dat1[num];
- lcdwrd(0x30);
- }
- break;
-
- case 13:
- lcdwrc(0x01); //清屏指令
- a=0;
- b=0;
- flag=0;
- fuhao=0;
- break;
-
- case 15:
- flag=1;
- fuhao=4;
- lcdwrd(0x2f);//除號/
- break;
-
- case 14:
- if(fuhao==1)//加
- {
- lcdwrc(0x4f+0x80);
- lcdwrc(0x04);//設置光標左移,屏幕不移動
- c=a+b;
- while(c!=0) //一位一位顯示
- {
- lcdwrd(0x30+c%10);//顯示結(jié)果的最后一位在0x4f的位置
- c=c/10;//取前面的結(jié)果數(shù)據(jù)
- }
- lcdwrd(0x3d); //顯示等于號=
- a=0;
- b=0;
- flag=0;
- fuhao=0;//全部清除為0
- }
- if(fuhao==2) //減
- {
- lcdwrc(0x4f+0x80);
- lcdwrc(0x04);//設置光標左移,屏幕不移動
- if(a>b)
- c=a-b;
- else
- c=b-a;
-
- while(c!=0) //一位一位顯示
- {
- lcdwrd(0x30+c%10);//顯示結(jié)果的最后一位在0x4f的位置
- c=c/10;//取前面的結(jié)果數(shù)據(jù)
- }
- if(a<b) lcdwrd(0x2d); //顯示-號
- lcdwrd(0x3d); //顯示等于號=
- a=0;
- b=0;
- flag=0;
- fuhao=0;//全部清除為0
- }
- if(fuhao==3)//乘法
- {
- lcdwrc(0x4f+0x80);
- lcdwrc(0x04);//設置光標左移,屏幕不移動
- c=a*b;
- while(c!=0) //一位一位顯示
- {
- lcdwrd(0x30+c%10);//顯示結(jié)果的最后一位在0x4f的位置
- c=c/10;//取前面的結(jié)果數(shù)據(jù)
- }
- lcdwrd(0x3d); //顯示等于號=
- a=0;
- b=0;
- flag=0;
- fuhao=0;//全部清除為0
- }
-
- if(fuhao==4)
- {
- k=0;
- lcdwrc(0x4f+0x80);
- lcdwrc(0x04);//設置光標左移,屏幕不移動
- c=(long)(((float)a/b)*1000);//強制轉(zhuǎn)換為long。
- while(c!=0) //一位一位顯示
- {
- k++;
- lcdwrd(0x30+c%10);//顯示結(jié)果的最后一位在0x4f的位置
- c=c/10;//取前面的結(jié)果數(shù)據(jù)
- if(k==3)
- {
- lcdwrd(0x2e);
- k=0;
- }
- }
- if(a/b<0) //如果a比b小的話那么除的結(jié)果最高位是0
- {
- lcdwrd(0x30);
- }
- lcdwrd(0x3d); //顯示等號
- a=0;
- b=0;
- flag=0;
- fuhao=0;//全部清除為0
- }
- break;
-
- }
- }
-
- }
-
- void InterruptTimer0() interrupt 1 //定時器中斷0
- {
- TH0=0xDC; //裝初值
- TL0=0x00;
- number++;
- if(number==100) //定時1s
- {
- number=0;
- t++;
- if(t==10) //定時10s
- {
- t=0;
- lcdwrc(0x01); //清屏指令
- a=0;
- b=0;
- flag=0;
- fuhao=0;
- }
- }
- }
-
- void main() //主函數(shù)
- {
- TH0=0xDC; //裝初值
- TL0=0x00;
- TMOD=0x01; //定時器0工作于16位,用于定時產(chǎn)生中斷
- EA=1; //允許總中斷
- ET0=1; //允許定時器0中斷
- TR0=1; //開定時器0
- lcdinit();
- while(1)
- {
- keyscan();
- }
- }
復制代碼
完整的Word格式實驗報告文檔51黑下載地址:
單片機實驗報告.docx
(1.09 MB, 下載次數(shù): 44)
2019-2-18 13:58 上傳
點擊文件名下載附件
|