|
以AT89C51單片機(jī)為核心實(shí)現(xiàn)一個(gè)4*4矩陣式鍵盤計(jì)算器,該計(jì)算器可以實(shí)現(xiàn)基本加減乘除功能,并且用LCD顯示鍵盤輸入數(shù)和運(yùn)算符號(hào)。
單片機(jī)源程序如下:
- #include<reg51.h>
- #include<stdio.h>
- #include<stdlib.h>
- unsigned char n;
- float idata a,b; //兩個(gè)操作數(shù)
- void key_scan(void); //鍵盤掃描
- void init(); //LCD初始化
- void LCD_dsp_string(unsigned char X,unsigned char Y,unsigned char *s);//字符串顯示
- void LCD_dsp_char( unsigned x,unsigned char y,unsigned char dat); //字符顯示
- void write_com(unsigned char com);
- sbit lcden=P2^7; //讀寫控制輸入端
- sbit rw=P2^6; //讀寫控制端
- sbit rs=P2^5; //指令與數(shù)據(jù)選擇
- sbit busy=P0^7; //LCD忙碌標(biāo)識(shí)
- void delay(unsigned int i) //延時(shí)程序
- {
- unsigned int n;
- for(n=0;n<=i;n++);
- }
- void main()
- {
- char idata temp[16]; //臨時(shí)存儲(chǔ)區(qū)
- char i=0,j=0,fuhao; //i,j分別為temp與LCD的數(shù)據(jù)指針
- bit flag=0,dh=0,fh=0,xsd=0;
- //flag=0:操作數(shù)1,flag=1:操作數(shù)2;dh=1時(shí)表示已輸入等號(hào);fh負(fù)號(hào);xsd小數(shù)點(diǎn)
- init(); //小數(shù)點(diǎn)
- LCD_dsp_string(4,0,"Welcome!");
- do
- {
- key_scan();
- } while(n==17); //等待按鍵
- write_com(0x01); //清屏
- while(1)
- {
- key_scan(); //等待按鍵
- if((dh==1)&(flag==1)&(n!=17)) //一次計(jì)算完畢后執(zhí)行
- {
- write_com(0x01); //清屏
- LCD_dsp_string(0,0,temp); //輸出上次計(jì)算的結(jié)果
- j=0;
- i=0;
- flag=0;
- fh=0;
- while(temp[i++]!='\0') j++;
- //將temp數(shù)據(jù)指針移向后一個(gè)空位,將LCD顯示指針移向下一個(gè)空位
- }
- if((i==0)&(n=='-')&(fh==0)) //如果輸入的第一個(gè)數(shù)是負(fù)數(shù)則執(zhí)行
- {
- fh=1; //表示有負(fù)號(hào)
- temp[0]='-'; //保存負(fù)號(hào)
- i++;
- LCD_dsp_char(j++,0,n); //輸出減號(hào)
- if(flag==0) continue;
- }
- if(((n>='0')&(n<='9')|((n=='c')&(xsd==0)))&(dh==0))
- {
- if(n=='c')
- {
- n='.';
- xsd=1; //防止再次按下c后繼續(xù)出現(xiàn)小數(shù)點(diǎn)
- }
- temp[i++]=n; //保存輸入的數(shù)字
- LCD_dsp_char(j++,0,n); //顯示并將光標(biāo)移至下一位(光標(biāo)未顯示)
-
- }
- if(((n=='+')|(n=='-')|(n=='*')|(n=='/'))&((flag==0)|(dh==1)))
- //輸入完第一個(gè)操作數(shù)之后或者完成一次計(jì)算之后按下運(yùn)算符按鍵時(shí)執(zhí)行
- {
- flag=1; //之后輸入的操作數(shù)是第二個(gè)操作數(shù)
- fuhao=n;
- temp[i]='\0'; //表示為字符串
- a=atof(temp); //轉(zhuǎn)換為數(shù)據(jù)
- i=0;
- dh=0;
- xsd=0; //之后第二個(gè)操作數(shù)中可以添加一個(gè)小數(shù)點(diǎn)
- switch(n)
- {
- case '+': LCD_dsp_char(j++,0,n); break;
- case '-': LCD_dsp_char(j++,0,n);
- fh=0; break;
- case '*': LCD_dsp_char(j++,0,n); break;
- case '/': LCD_dsp_char(j++,0,n); break;
- } //顯示運(yùn)算符
- }
- if((n=='=')&(flag==1)) //已輸入完第二個(gè)操作數(shù)并按下等號(hào)
- {
- dh=1;
- temp[i]='\0';
- b=atof(temp);
- i=0;
- xsd=0;
- LCD_dsp_char(j,0,'='); //顯示等號(hào)
- switch(fuhao)
- {
- case '+': a=a+b; break;
- case '-': a=a-b; break;
- case '*': a=a*b; break;
- case '/': a=a/b; break;
- } //計(jì)算
- if(a>9999)
- {
- sprintf(temp,"%s","Error");
- //若計(jì)算結(jié)果超過四位數(shù)則輸出錯(cuò)誤信息
- LCD_dsp_string(0,1,temp);
- n=17;
- do
- {
- key_scan();
- }while(n==17); //等待按鍵
- write_com(0x01); //清屏
- a=b=0;
- fuhao=0;
- flag=0;
- i=0;
- j=0;
- dh=0;
- xsd=0;
- fh=0; //恢復(fù)初始化
- }
- else
- {
- sprintf(temp,"%g",a); //輸出計(jì)算結(jié)果
- LCD_dsp_string(0,1,temp);
- }
- }
- if(n=='c') //按下清除鍵
- {
- write_com(0x01); //清屏
- a=b=0;
- fuhao=0;
- flag=0;
- i=0;
- j=0;
- dh=0;
- xsd=0;
- fh=0; //恢復(fù)初始化
- }
- }
- }
- void key_scan(void)
- {
- unsigned char temp;
- P1=0xfe;
- if(P1!=0xfe)
- {
- delay(200);
- if(P1!=0xfe)
- {
- temp=P1&0xf0;
- switch(temp)
- {
- case 0xe0:n='c';break;
- case 0xd0:n='0';break;
- case 0xb0:n='=';break;
- case 0x70:n='+';break;
- }
- }
- while(P1!=0xfe);
- }
- else
- {
- P1=0xfd;
- if(P1!=0xfd)
- {
- delay(200);
- if(P1!=0xfd)
- {
- temp=P1&0xf0;
- switch(temp)
- {
- case 0xe0:n='1';break;
- case 0xd0:n='2';break;
- case 0xb0:n='3';break;
- case 0x70:n='-';break;
- }
- }
- while(P1!=0xfd);
- }
- else{
- P1=0xfb;
- if(P1!=0xfb)
- {
- delay(200);
- if(P1!=0xfb)
- {
- temp=P1&0xf0;
- switch(temp)
- {
- case 0xe0:n='4';break;
- case 0xd0:n='5';break;
- case 0xb0:n='6';break;
- case 0x70:n='*';break;
- }
- }
- while(P1!=0xfb);
- }
- else{
- P1=0xf7;
- if(P1!=0xf7)
- {
- delay(200);
- if(P1!=0xf7)
- {
- temp=P1&0xf0;
- switch(temp)
- {
- case 0xe0:n='7';break;
- case 0xd0:n='8';break;
- case 0xb0:n='9';break;
- case 0x70:n='/';break;
- }
- }
- while(P1!=0xf7);
- }
- else n=17;
- }}}
- }
- void check() //判斷LCD是否忙碌
- {
- do
- {
- P0=0xff;
- rs=0;
- rw=1;
- lcden=0;
- delay(100);
- lcden=1;
- }while(busy==1); //當(dāng)busy=1,即LCD忙時(shí),等待
- }
- void write_com(unsigned char com) //寫顯示命令
- {
- P0=com;
- rs=0;
- rw=0;
- lcden=0;
- check();
- lcden=1;
- }
- void write_data(unsigned char date) //寫顯示數(shù)據(jù)
- {
- P0=date;
- rs=1;
- rw=0;
- lcden=0;
- check();
- lcden=1;
- }
- void init() //初始化LCD
- {
- write_com(0x38); //16x2行顯示,5x7點(diǎn)陣,8位數(shù)據(jù)接口
- write_com(0x0c); //開顯示,光標(biāo)不顯示、不閃爍
- write_com(0x06); //光標(biāo)自增,畫面不動(dòng)
- write_com(0x80); //選擇第一行
- write_com(0x01); //清屏
- }
- void LCD_set_xy( unsigned char x, unsigned char y )//設(shè)置LCD顯示的位置
- {
- unsigned char address;
- if (y == 0) //y=0為第一行
- address = 0x80 + x; //x=0為一行的第一個(gè)
- else //第二行
- address =0xc0+ x;
- write_com(address); //設(shè)置數(shù)據(jù)指針位置
- }
- void LCD_dsp_char( unsigned x,unsigned char y,unsigned char dat)
- //單個(gè)字符顯示函數(shù)
- {
- LCD_set_xy( x, y ); //設(shè)置顯示位置
- write_data(dat); //寫入待顯示數(shù)據(jù)
- }
- void LCD_dsp_string(unsigned char X,unsigned char Y,unsigned char *s)
- //字符串顯示函數(shù)
- {
- LCD_set_xy( X, Y );
- while (*s) //當(dāng)字符串未到達(dá)結(jié)尾('\0')時(shí),循環(huán)輸出單個(gè)字符
- {
- write_data(*s);
- s ++; //指向下一個(gè)字符
- }
- }
復(fù)制代碼
所有資料51hei提供下載:
計(jì)算器.zip
(1.24 MB, 下載次數(shù): 65)
2019-7-10 09:04 上傳
點(diǎn)擊文件名下載附件
|
評(píng)分
-
查看全部評(píng)分
|