摘要:計(jì)算器是我們生活中常用的工具,在我們生活中不可或缺。本次設(shè)計(jì)是設(shè)計(jì)一個(gè)算術(shù)型計(jì)算器,該計(jì)算器能夠完成簡(jiǎn)單的四則運(yùn)算,還可以實(shí)現(xiàn)連續(xù)運(yùn)算。本次是以51單片機(jī)為運(yùn)算核心,以LCD1602為顯示的進(jìn)行硬件上的設(shè)計(jì),在軟件上以Keil4進(jìn)行軟件編程,以Proteus進(jìn)行仿真調(diào)試,設(shè)計(jì)出一個(gè)能夠完成簡(jiǎn)單的四則運(yùn)算,實(shí)現(xiàn)連續(xù)運(yùn)算的小型算術(shù)型計(jì)算器。
正文:
一、設(shè)計(jì)概述
1. 課題意義
計(jì)算器有鍵盤部分、單片機(jī)、顯示部分三部分組成,鍵盤部分主要完成輸入功能;單片機(jī)主要完成數(shù)據(jù)處理功能,包括確定按鍵,完成運(yùn)算,以及輸出數(shù)據(jù);顯示器部分主要完成單片機(jī)輸出的顯示;菊莆沼(jì)算器的設(shè)計(jì)原理和LCD1602的顯示原理,進(jìn)而熟悉C51的編程和調(diào)試方法。
2. 系統(tǒng)功能
能夠完成簡(jiǎn)單的四則運(yùn)算,還可以實(shí)現(xiàn)連續(xù)運(yùn)算的小型算術(shù)型計(jì)算器。
硬件設(shè)計(jì)上通過Proteus進(jìn)行電路原理圖和仿真運(yùn)行圖的設(shè)計(jì),軟件設(shè)計(jì)上以Keil4為基礎(chǔ)進(jìn)行軟件編程,將編程生成的.hex文件放入在Proteus已畫好的原理圖中調(diào)試,觀察設(shè)計(jì)結(jié)果,并對(duì)代碼進(jìn)行修改。
二、硬件設(shè)計(jì)
[size=9.0000pt] 圖1 [size=9.0000pt]總原理圖
1.按鍵設(shè)計(jì)
矩陣鍵盤的原理是見I/O口分為行線和列線,按鍵設(shè)置在跨接行線和列線的交點(diǎn)上,列線通過上拉電阻接正電源,進(jìn)而形成基本的4x4行列式鍵盤。本次設(shè)計(jì)以矩陣鍵盤為基本的輸入按鍵分別為1,2,3,+,4,5,6,-,7,8,9,x,0,CLR,=,/ 形成計(jì)算器對(duì)應(yīng)的基本的數(shù)字鍵和功能鍵
顯示設(shè)計(jì)
LCD1602是一種專門用來顯示字母、數(shù)字、符號(hào)等的點(diǎn)陣型液晶模塊,它由若干個(gè)5X7或者5X11等點(diǎn)陣字符位組成,每個(gè)點(diǎn)陣字符位都可以顯示一個(gè)字符,每位之間有一個(gè)點(diǎn)距的間隔,每行之間也有間隔,起到了字符間距和行間距的作用,因此它比較適合用在計(jì)算器的顯示。
三、軟件設(shè)計(jì)
1. 按鍵掃描
本次設(shè)計(jì)中在軟件上使用了反轉(zhuǎn)法進(jìn)行按鍵的掃描,其過程為先讓行輸出全為0列輸出全為1讀取與按鍵相接的P1口的狀態(tài),讀取按鍵的列值,然后讓行輸出全為1列輸出全為0讀取與按鍵相接的P1口的狀態(tài),讀取按鍵的行值,根據(jù)行值和列值可知其鍵值。
[size=9.0000pt] 圖4按鍵掃描流程圖[size=9.0000pt]
2.顯示設(shè)計(jì)
LCD1602是一個(gè)16字雙行的顯示模塊,在使用LCD1602之前我們應(yīng)該先對(duì)其進(jìn)行初始化,其初始化的內(nèi)容有光標(biāo)設(shè)置、顯示設(shè)置和清屏指令等。初始化完成后從其參考手冊(cè)可知LCD1602中已經(jīng)存儲(chǔ)有基本字模數(shù)據(jù),所以想要在LCD1602中顯示字符,只需要對(duì)LCD1602寫入該字符相對(duì)應(yīng)的ASCII碼即可顯示出相應(yīng)的字符。LCD1602的寫入可分為寫數(shù)據(jù)和寫命令,當(dāng)要寫入數(shù)據(jù)時(shí)其對(duì)應(yīng)的狀態(tài)為RS=1,RW=0,E為下降沿,然后通過單片機(jī)I/O口寫入相應(yīng)的數(shù)據(jù)。當(dāng)要寫入命令時(shí)其對(duì)應(yīng)的狀態(tài)為RS=0,RW=0,E為下降沿,然后通過單片機(jī)I/O口寫入相應(yīng)的命令。
[size=9.0000pt]圖5 LCD1602寫指令圖
3.鍵值處理
首先我們初始化液晶顯示器,然后顯示出第一個(gè)被按下的數(shù),并且使光標(biāo)右移,如果有第二個(gè)數(shù)按下,則據(jù)繼續(xù)顯示,以此類推,然后把所有顯示出來的數(shù)換算成一個(gè)數(shù),如果按下“+”號(hào),則顯示出“+”,并且同理顯示出“+”號(hào)后面按下的數(shù)字,然后調(diào)用加子程序,運(yùn)算出結(jié)果,如果按下的是“-”,則調(diào)用減子程序,如果按下“*”,則調(diào)用乘子程序,如果按下“/”,則調(diào)用除子程序。然后再調(diào)用顯示結(jié)果子程序,顯示出結(jié)果。
圖6鍵值運(yùn)算流程圖
四、系統(tǒng)測(cè)試
1.加法測(cè)試
2.減法測(cè)試
3.乘法測(cè)試
4.除法測(cè)試
5.連續(xù)運(yùn)算測(cè)試
五、結(jié)論
經(jīng)過調(diào)試可知此次設(shè)計(jì)已經(jīng)基本達(dá)到要求,該計(jì)算器能夠完成簡(jiǎn)單的四則運(yùn)算,還可以實(shí)現(xiàn)連續(xù)運(yùn)算。但只能進(jìn)行整數(shù)的運(yùn)算,無(wú)法進(jìn)行浮點(diǎn)型數(shù)據(jù)運(yùn)算,運(yùn)算的連續(xù)運(yùn)行需要一個(gè)個(gè)數(shù)的連續(xù)運(yùn)算,無(wú)法做到一次性連續(xù)運(yùn)算。
七、附錄
1.系統(tǒng)電路圖
2.實(shí)物運(yùn)行圖
單片機(jī)源程序如下:
- /* 實(shí)現(xiàn)兩個(gè)數(shù)的運(yùn)算,每個(gè)數(shù)的位數(shù)至少可以八位 */
- #include<reg52.h>
- #include<math.h>
- typedef unsigned char uint8;
- typedef unsigned int uint16;
- #define GPIO_KEY P1
- sbit rw=P2^5;
- sbit rs=P2^6;
- sbit e=P2^7;
- sbit k1=P3^0;
- uint8 num='N'; //鍵值
- uint16 k0,k2,k3; // 數(shù)組位
- uint8 fuhao; //定義具體的那個(gè)符號(hào),是加減還是乘除。
- uint8 flag,r; //定義符號(hào)鍵標(biāo)志位,小數(shù)點(diǎn)標(biāo)志位和繼續(xù)運(yùn)算標(biāo)志位 這個(gè)是統(tǒng)稱
- float a,b,c,zheng,xiao; //定義運(yùn)算數(shù)據(jù)的第一個(gè)和第二個(gè)及等于的數(shù)變量
- uint8 shuzi1[5]={0},shuzi2[5]={0},shuzi3[4]={0};
- uint8 code dat1[]={1,2,3,0x2b-0x30, 4,5,6,0x2d-0x30, 7,8,9,0x78-0x30, 0,0x2e-0x30,0x3d-0x30,0xfd-0x30 };//保存顯示的數(shù)據(jù) 123+ 456- 789* 0.CLR /
- void delay(uint16 i)
- { uint16 x,y;
- for(x=0;x<i;x++)
- for(y=0;y<114;y++);
- }
- void lcdcommand(uint8 m) //寫命令
- {
- delay(1);
- rs=0;
- rw=0;
- e=0;
- P0=m;
- e=1;
- delay(1);
- e=0;
- }
- void lcddata(uint8 dat) //寫數(shù)據(jù)
- {
- delay(1);
- rs=1;
- rw=0;
- e=0;
- P0=dat;
- e=1;
- delay(1);
- e=0;
- rs=0;
- }
- void lcdcsh() //初始化
- {
- delay(5);
- lcdcommand(0x38); //功能設(shè)定 8位總線 兩行 5X7點(diǎn)陣
- delay(5);
- lcdcommand(0x38);
- lcdcommand(0x38);
- lcdcommand(0x0c); // 開顯示 無(wú)光標(biāo)
- lcdcommand(0x06); //光標(biāo)左移
- lcdcommand(0x01); // 清屏
- lcdcommand(0x80);//數(shù)據(jù)從左上開始
- num='N';
- flag=0;
- fuhao=0;
- a=0;
- b=0;
- c=0;
- zheng=xiao=0;;
- k0=0;k2=0;k3=0;
- }
- void shuchu(float e) //在屏幕上顯示數(shù)值e
- {
- char shuzu[10];
- long z;
- int x=0;
- float f;
-
- (long)z=e; //整數(shù)處理
- if(z==0)
- lcddata('0');
- while(z!=0)
- { shuzu[x]=z%10;
- z=z/10;
- x++;
- }
- for(x=x-1;x>=0;x--)
- lcddata(shuzu[x]+0x30);
- (long)z=e; //小數(shù)處理
- (float)f=e-z;
- if(f>0.000)
- { x=0;
- lcddata('.');
- z=f*1000;
- while(z!=0)
- { shuzu[x]=z%10;
- z=z/10;
- x++;
- }
- for(x=x-1;x>=0;x--)
- lcddata(shuzu[x]+0x30);
- }
- }
- void fuzhi() // 顯示與向數(shù)組賦值
- {
-
- if(flag==0) //是否按下符號(hào)鍵
- {
- delay(50);
- if(dat1[num]=='.')
- r=1;
- if((r==0)&&(k0<5))
- {
- shuzi1[k0]=dat1[num];
- k0++;
- lcddata(0x30+dat1[num]);
- }
- else if((r==1)&&(k3<4))
- {
-
- shuzi3[k3]=dat1[num];
- k3++;
- lcddata(0x30+dat1[num]);
- }
- }
- r=0;
- if(flag==1) //是否按下符號(hào)鍵
- {
- delay(50);
- if(dat1[num]=='.')
- r=1;
- if((r==0)&&(k2<5))
- {
- shuzi2[k2]=dat1[num];
- k2++;
- lcddata(0x30+dat1[num]);
- }
- else if((r==1)&&(k3<4))
- {
-
- shuzi3[k3]=dat1[num];
- k3++;
- lcddata(0x30+dat1[num]);
- }
- }
- }
- void sz(uint8 s[8],int x) //數(shù)組轉(zhuǎn)為數(shù)值
- {
- int i,j;
- zheng=0;
- xiao=0;
- i=0; //整數(shù)
- while(x>0)
- {
- zheng=zheng*10+s[i];
- i++;
- x--;
- }
- i=1; //小數(shù)
- j=k3;
- while(j>0)
- {
- xiao=xiao*10+s[i];
- i++;
- j--;
- }
-
- for(;k3>0;k3--)
- xiao=xiao/10;
- zheng=zheng+xiao;
- k0=k2=k3=0;
- }
- void KeyDown(void)
- {
- char L=0;
- GPIO_KEY=0x0f;
- if(GPIO_KEY!=0x0f)//讀取按鍵是否按下
- {
- delay(10);//延時(shí)10ms進(jìn)行消抖
- if(GPIO_KEY!=0x0f)//再次檢測(cè)鍵盤是否按下
- {
- //測(cè)試列
- GPIO_KEY=0X0F;
- switch(GPIO_KEY)
- {
- case(0X07): num=0;break;
- case(0X0b): num=1;break;
- case(0X0d): num=2;break;
- case(0X0e): num=3;break;
- }
- //測(cè)試行
- GPIO_KEY=0XF0;
- switch(GPIO_KEY)
- {
- case(0X70): num=num;break;
- case(0Xb0): num=num+4;break;
- case(0Xd0): num=num+8;break;
- case(0Xe0): num=num+12;break;
- }
- while((L<50)&&(GPIO_KEY!=0xf0)) //檢測(cè)按鍵松手檢測(cè)
- {
- delay(10);
- L++;
- }
- }
- }
- }
- void banduan()
- {
- switch(fuhao)
- {
- case 0:
- sz(shuzi1,k0);
- a=zheng;
- lcdcommand(0x01);
- lcdcommand(0x40+0x80);
- shuchu(a);
- b=0;
- flag=0;
- fuhao=0; //全部清除為0
- zheng=0;
- xiao=0;
- break;
- case 1:
-
- lcdcommand(0x40+0x80);
- c=a+b;
- lcddata(0x3d); //顯示等于號(hào)=
- shuchu(c);
- a=0;
- b=0;
- flag=0;
- fuhao=0; //全部清除為0
- zheng=0;
- xiao=0;
- break;
- case 2:
- lcdcommand(0x40+0x80);
-
- if(a>b)
- { c=a-b;
- lcddata(0x3d); //顯示等于號(hào)=
- }
- else if(a<b)
- {
- c=b-a;
- lcddata(0x3d); //顯示等于號(hào)=
- lcddata(0x2d); //顯示負(fù)號(hào)-
- }
- if(a==b)
- c=0;
- shuchu(c);
- a=0;
- b=0;
- flag=0;
- fuhao=0; //全部清除為0
- zheng=0;
- xiao=0;
- break;
- case 3:
- lcdcommand(0x40+0x80);
- c=a*b;
- lcddata(0x3d); //顯示等于號(hào)=
- shuchu(c);
- a=0;
- b=0;
- flag=0;
- fuhao=0; //全部清除為0
- zheng=0;
- xiao=0;
- break;
- case 4:
- lcdcommand(0x40+0x80);
- c=a/b;
- lcddata(0x3d); //顯示等號(hào)
- shuchu(c);
- a=0;
- b=0;
- flag=0;
- fuhao=0; //全部清除為0
- zheng=0;
- xiao=0;
-
- break;
- }
-
- }
- void main()
- {
-
-
-
- lcdcsh();
- while(1)
- { num='N';
- KeyDown();
- if(num==13)
- {
- lcdcommand(0x01);//清零
-
- flag=0;
- fuhao=0;
- a=0;
- b=0;
- c=0;
- zheng=xiao=0;
- k0=k2=k3=0;
- }
- while(1)
- {
- num='N';
- KeyDown();
- if(num==0||num==1||num==2||num==4||num==5||num==6||num==8||num==9||num==10||num==12||num==16) //1-9-0-.
- fuzhi();
- if(num==13)
- {
- lcdcommand(0x01);//清零
-
- flag=0;
- fuhao=0;
- a=0;
- b=0;
- c=0;
- zheng=xiao=0;
- k0=k2=k3=0;
- break;
- }
- if(num==3||num==7||num==11||num==15)
- {
-
- flag=1;
- switch(num)
- { case 3: fuhao=1; break;
- case 7: fuhao=2; break;
- case 11: fuhao=3; break;
- case 15: fuhao=4; break;
- }
- sz(shuzi1,k0);
- c=zheng;
- loop: a=c;
- lcdcommand(0x01);
- lcdcommand(0x80);
- shuchu(a);
- lcddata(0x30+dat1[num]);
- break;
- }
- }
-
- while(1)
- {
- num='N';
- KeyDown();
- if(num==0||num==1||num==2||num==4||num==5||num==6||num==8||num==9||num==10||num==12) //1-9-0
- fuzhi();
- if(num==13)
- {
- lcdcommand(0x01);//清零
-
- flag=0;
- fuhao=0;
- a=0;
- b=0;
- c=0;
- zheng=xiao=0;
- k0=k2=k3=0;
- break;
-
- ……………………
- …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼
所有程序51hei提供下載:
1.c.zip
(2.41 KB, 下載次數(shù): 129)
2019-10-10 18:38 上傳
點(diǎn)擊文件名下載附件
程序清單
|