用Proteus實現計算器功能的實現:實現加(減)功能。
單片機源程序如下:
- #include <reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit rs=P0^0;
- sbit rw=P0^1;
- sbit e=P0^2;
- sbit k0=P1^0;
- sbit k1=P1^1;
- sbit k2=P1^2;
- sbit k3=P1^3;
- sbit k4=P1^4;
- sbit k5=P1^5;
- sbit k6=P1^6;
- sbit k7=P1^7;
- unsigned char code digit[ ]={"0123456789"}; //定義字符數組顯示數字
- unsigned char s,m,h,day,month,year,count;
- void write_dat(uchar dat);
- void write_com(uchar com);
- void keyscan();
- /**********************
- 功能說明:
- 顯示編碼,加上0x30,
- 分別為'1','2','3','+',
- '4','5','6','-',等
- **********************/
- uchar code table1[]=
- {
- 1,2,3,0x2b-0x30,
- 4,5,6,0x2d-0x30,
- 7,8,9,0x2a-0x30,
- 0,0x3d-0x30,0x01-0x30,0x2f-0x30
- };
- uchar k=0,flag=0,num,fuhao,i;
- long a,b,c;
- void delay(uint z)
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- /*****************************************************
- 函數功能:指定字符顯示的實際地址
- 入口參數:x
- ***************************************************/
- void WriteAddress(unsigned char x)
- {
- write_com(x|0x80); //顯示位置的確定方法規定為"80H+地址碼x"
- }
- /******************************************************************************
- 函數功能:顯示小時
- ******************************************************************************/
- void DisplayHour()
- {
- unsigned char i,j;
- i=h/10; //取整運算,求得十位數字
- j=h%10; //取余運算,求得各位數字
- WriteAddress(0x45); //寫顯示地址,將十位數字顯示在第2行第0列
- write_dat(digit[i]); //將十位數字的字符常量寫入LCD
- write_dat(digit[j]); //將個位數字的字符常量寫入LCD
-
- }
- /******************************************************************************
- 函數功能:顯示分鐘
- ******************************************************************************/
- void DisplayMinute()
- {
- unsigned char i,j;
- i=m/10; //取整運算,求得十位數字
- j=m%10; //取余運算,求得各位數字
- WriteAddress(0x48); //寫顯示地址,將十位數字顯示在第2行第3列
- write_dat(digit[i]); //將十位數字的字符常量寫入LCD
- write_dat(digit[j]); //將個位數字的字符常量寫入LCD
-
- }
- /******************************************************************************
- 函數功能:顯示秒
- ******************************************************************************/
- void DisplaySecond()
- {
- unsigned char i,j;
- i=s/10; //取整運算,求得十位數字
- j=s%10; //取余運算,求得各位數字
- WriteAddress(0x4b); //寫顯示地址,將十位數字顯示在第2行第6列
- write_dat(digit[i]); //將十位數字的字符常量寫入LCD
- write_dat(digit[j]); //將個位數字的字符常量寫入LCD
- }
- /******************************************************************************
- 函數功能:顯示小時
- ******************************************************************************/
- void DisplayYear()
- {
- unsigned char i,j;
- i=year/10; //取整運算,求得十位數字
- j=year%10; //取余運算,求得各位數字
- WriteAddress(0x07); //寫顯示地址,將十位數字顯示在第2行第0列
- write_dat(digit[i]); //將十位數字的字符常量寫入LCD
- write_dat(digit[j]); //將個位數字的字符常量寫入LCD
-
- }
- /******************************************************************************
- 函數功能:顯示分鐘
- ******************************************************************************/
- void DisplayMonth()
- {
- unsigned char i,j;
- i=month/10; //取整運算,求得十位數字
- j=month%10; //取余運算,求得各位數字
- WriteAddress(0x0a); //寫顯示地址,將十位數字顯示在第2行第3列
- write_dat(digit[i]); //將十位數字的字符常量寫入LCD
- write_dat(digit[j]); //將個位數字的字符常量寫入LCD
-
- }
- /******************************************************************************
- 函數功能:顯示秒
- ******************************************************************************/
- void DisplayDay()
- {
- unsigned char i,j;
- i=day/10; //取整運算,求得十位數字
- j=day%10; //取余運算,求得各位數字
- WriteAddress(0x0d); //寫顯示地址,將十位數字顯示在第2行第6列
- write_dat(digit[i]); //將十位數字的字符常量寫入LCD
- write_dat(digit[j]); //將個位數字的字符常量寫入LCD
- }
- void keyscan2()
- {if(k0==0)
- {delay(5);
- if(k0==0)
- {
- s++;
- if(s==60)
- s=0;
- }
- }
- if(k1==0)
- {delay(5);
- if(k1==0)
- {m++;
- if(m==60)
- m=0;
- }
- }
- if(k2==0)
- {delay(5);
- if(k2==0)
- {h++;
- if(h==60)
- h=0;
- }
- }
-
- if(k3==0)
- {delay(5);
- if(k3==0)
- {day++;
- if(day==30)
- day=0;
- }
- }
- if(k4==0)
- {delay(5);
- if(k4==0)
- {month++;
- if(month==13)
- month=0;
- }
- }
- if(k5==0)
- {delay(5);
- if(k5==0)
- {year++;
- if(year==99)
- year=0;
- }
- }
- }
-
- void keyscan()
- {
- uchar temp;
- P3=0xfe;
- temp=P3;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- delay(5);
- temp=P3;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- temp=P3;
- switch(temp)
- {
- case 0xee:num=0;
- break;
- case 0xde:num=1;
- break;
- case 0xbe:num=2;
- break;
- case 0x7e:num=3;
- break;
- }
- while(temp!=0xf0)
- { temp=P3;
- temp=temp&0xf0;
- }
- }
- /*當按下1,2,3,松手后執行下面這段語句*/
- if(num==0||num==1||num==2)
- {
-
- if(flag==0)
- a=a*10+table1[num];//如果沒有按符號鍵,符號前的數值為a
- else if(flag==1)
- b=b*10+table1[num]; //如果按了符號鍵,符號后的數值為b
-
- if(k==1) //如果之前按了'='號,再按鍵時清屏,進行下一次計算
- {
- k=0;
- write_com(0x01);
- }
- }
- else if(num==3) //判斷按下'+'
- {
- flag=1;
- fuhao=1;
- }
-
- i=table1[num]; //顯示按下的鍵
- write_dat(0x30+i);
-
- }
- P3=0xfd;
- temp=P3;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- delay(5);
- temp=P3;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- temp=P3;
- switch(temp)
- {
- case 0xed:num=4;
- break;
- case 0xdd:num=5;
- break;
- case 0xbd:num=6;
- break;
- case 0x7d:num=7;
- break;
- }
- while(temp!=0xf0)
- { temp=P3;
- temp=temp&0xf0;
- }
- }
- if(num==4||num==5||num==6) //判斷是否按下'4','5','6'
- {
- if(k==1)
- {
- k=0;
- write_com(0x01);
- }
- if(flag==0)
- a=a*10+table1[num];
- else if(flag==1)
- b=b*10+table1[num];
- }
- else if(num==7)
- {
- flag=1;
- fuhao=2;
- }
- i=table1[num]; //顯示按下的鍵
- write_dat(0x30+i);
- }
- P3=0xfb;
- temp=P3;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- delay(5);
- temp=P3;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- temp=P3;
- switch(temp) //
- {
- case 0xeb:num=8;
- break;
- case 0xdb:num=9;
- break;
- case 0xbb:num=10;
- break;
- case 0x7b:num=11;
- break;
- }
- while(temp!=0xf0)
- { temp=P3;
- temp=temp&0xf0;
- }
- }
- if(num==8||num==9||num==10) //判斷是否按下'7','8','9'
- {
- if(k==1)
- {
- k=0;
- write_com(0x01);
- }
- if(flag==0)
- a=a*10+table1[num];
- else if(flag==1)
- b=b*10+table1[num];
-
- }
- else if(num==11) //判斷是否按下'*'
- {
- flag=1;
- fuhao=3;
-
- }
- i=table1[num];
- write_dat(0x30+i);
-
- }
- P3=0xf7;
- temp=P3;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- delay(5);
- temp=P3;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- temp=P3;
- switch(temp)
- {
- case 0xe7:num=12; // 0鍵
- break;
- case 0xd7:num=13; // '='
- break;
- case 0xb7:num=14; //清零鍵
- break;
- case 0x77:num=15; //'/'
- break;
- }
- while(temp!=0xf0)
- { temp=P3;
- temp=temp&0xf0;
- }
- }
- switch(num)
- {
- case 12:
- {
- if(k==1)
- {
- k=0;
- write_com(0x01);
- }
- if(flag==0)
- a=a*10;
- else if(flag==1)
- b=b*10;
- write_dat(0x30);
- }
- break;
- case 13: //按=鍵
- {
- k=1;
- if(fuhao==1) //如果符號鍵是+,執行+運算
- {
-
- write_com(0x80+0x4f);
- write_com(0x04);
- c=a+b;
- while(c!=0)
- {
- write_dat(0x30+c%10);
- c=c/10;
-
-
- }
- write_dat(0x3d);
- fuhao=0;
- a=0;b=0;flag=0;
- }
- if(fuhao==2)
- {
- write_com(0x80+0x4f);
- write_com(0x04);
- if(a>=b)
- {
- c=a-b;
- while(c!=0)
- {
- write_dat(0x30+c%10);
- c=c/10;
- }
-
- }
- else if(a<b)
- {
- c=b-a;
- while(c!=0)
- {
- write_dat(0x30+c%10);
- c=c/10;
- }
- write_dat(0x2d);
- }
-
- write_dat(0x3d);
- a=0;b=0;flag=0;fuhao=0;
-
- }
- if(fuhao==3) //如果符號鍵是*
- {
- write_com(0x80+0x4f);
- write_com(0x04);
- c=a*b;
- while(c!=0)
- {
- write_dat(0x30+c%10);
- c=c/10;
- }
- write_dat(0x3d);
- a=0;b=0;flag=0;fuhao=0;
-
- }
- if(fuhao==4) //如果符號鍵是/
- {
- i=0;
- write_com(0x80+0x4f);
- write_com(0x04);
- c=(long)(((float)a/b)*1000000); //結果保留6位小數
- while(c!=0)
- {
- write_dat(0x30+c%10);
- c=c/10;
- i++;
- if(i==6) // 顯示完六位小數后,顯示·
- write_dat(0x2e);
- }
- if(a/b<=0)
- write_dat(0x30);
- write_dat(0x3d);
- a=0;b=0;flag=0;fuhao=0;
- }
- }
- break;
- case 14:
- { write_com(0x01);
- a=0;b=0;flag=0;fuhao=0;
- }
- break;
- case 15:
- {
- flag=1;
- fuhao=4;
- write_dat(0x30+table1[num]);
-
- }
- break;
-
- }
-
- }
-
- }
- /*******led1602*******/
- void write_com(uchar com)
- {
- rs=0;//選擇寫指令
- rw=0;
- P2=com;
- e=1;
- delay(5);//無延時不能正常工作
- e=0;
- }
- void write_dat(uchar dat)
- {
- rs=1;//選擇寫數據
- rw=0;
- P2=dat;
- e=1;
- delay(5);//無延時不能正常工作
- e=0;
- }
- void init() //初始化
- {
- delay(15);
- write_com(0x38);
- delay(6);
- write_com(0x38);
- delay(6);
- write_com(0x38);
- write_com(0x38);
- write_com(0x0c); //開顯示,關光標
- write_com(0x06);//光標移動 設置
- write_com(0x01);//清屏
-
- }
- void geshi()
- {
- WriteAddress(0x00);
- write_dat('D');
- WriteAddress(0x01);
- write_dat('a');
- WriteAddress(0x02);
- write_dat('t'); //將分號的字符常量寫入LCD
- WriteAddress(0x03);
- write_dat('e');
- WriteAddress(0x04);
- write_dat(':');
- WriteAddress(0x05);
- write_dat('2');
- WriteAddress(0x06);
- write_dat('0');
- WriteAddress(0x09);
- write_dat('-');
- WriteAddress(0x0c);
- write_dat('-');
- WriteAddress(0x40);
- write_dat('T');
- WriteAddress(0x41);
- write_dat('i');
- WriteAddress(0x42);
- write_dat('m');
- WriteAddress(0x43); //寫地址,將第二個分號顯示在第2行第7列
- write_dat('e'); //將分號的字符常量寫入LCD
- WriteAddress(0x44); //寫地址,將第二個分號顯示在第2行第10列
- write_dat(':'); //將分號的字符常量寫入LCD
- WriteAddress(0x47);
- write_dat(':');
- WriteAddress(0x4a);
- write_dat(':');
- }
-
- void main()
- {
-
-
- init();
- TMOD=0x01; //使用定時器T0的模式1
- TH0=(65536-46083)/256; //定時器T0的高8位設置初值
- TL0=(65536-46083)%256; //定時器T0的低8位設置初值
- EA=1; //開總中斷
- ET0=1; //定時器T0中斷允許
- TR0=1; //啟動定時器T0
- count=0; //中斷次數初始化為0
- s=0; //秒初始化為0
- m=0; //分鐘初始化為0
- h=0; //小時初始化為0
- year=0;
- month=0;
- day=0;
- while(1)
- {
- keyscan();
- if(k6==0)
- { k6=0;
- write_com(0x01);
- while(1)
- {
- keyscan2();
- geshi();
- delay(5);
- DisplayHour();
- delay(5);
- DisplayMinute();
- delay(5);
- DisplaySecond();
- delay(5);
- DisplayYear();
- delay(5);
- DisplayMonth();
- delay(5);
- DisplayDay();
- delay(5);
- if(k7==0)
- {
- k6=1;
- write_com(0x01);
- break;
- }
-
- }
-
- }
-
- }
-
- }
- /*******************************************************
- 函數功能:定時器T0的中斷服務函數
- ********************************************************/
- void Time0(void ) interrupt 1 using 1 //定時器T0的中斷編號為1,使用第1組工作寄存器
- {
- count++; //每產生1次中斷,中斷累計次數加1
- if(count==20) //如果中斷次數計滿20次
- {
- count=0; //中斷累計次數清0
- s++; //秒加1
- if(s==60) //如果計滿60秒
- {
- s=0; //秒清0
- m++; //分鐘加1
- }
- if(m==60) //如果計滿60分
- {
- m=0; //分鐘清0
- h++; //小時加1
- }
-
- if(h==24)
- {
- h=0;
- day++;
- }
- if(day==30)
- {
- day=0;
- month++;
- }
- if(month==13)
- { month=0;
- year++;
- }
- if(year==99)
- {
- year=0;
- }
- TH0=(65536-46083)/256; //定時器T0高8位重新賦初值
- TL0=(65536-46083)%256; //定時器T0低8位重新賦初值
- }
- }
復制代碼
所有資料51hei提供下載:
計算器.rar
(3.28 KB, 下載次數: 13)
2018-6-19 17:52 上傳
點擊文件名下載附件
簡易計算器的設計及實現
|