以AT89C51单片机为核心实现一个4*4矩阵式键盘计算器,该计算器可以实现基本加减乘除功能,并且用LCD显示键盘输入数和运算符号。
单片机源程序如下:
- #include<reg51.h>
- #include<stdio.h>
- #include<stdlib.h>
- unsigned char n;
- float idata a,b; //两个操作数
- 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; //指令与数据选择
- sbit busy=P0^7; //LCD忙碌标识
- void delay(unsigned int i) //延时程序
- {
- unsigned int n;
- for(n=0;n<=i;n++);
- }
- void main()
- {
- char idata temp[16]; //临时存储区
- char i=0,j=0,fuhao; //i,j分别为temp与LCD的数据指针
- bit flag=0,dh=0,fh=0,xsd=0;
- //flag=0:操作数1,flag=1:操作数2;dh=1时表示已输入等号;fh负号;xsd小数点
- init(); //小数点
- 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)) //一次计算完毕后执行
- {
- write_com(0x01); //清屏
- LCD_dsp_string(0,0,temp); //输出上次计算的结果
- j=0;
- i=0;
- flag=0;
- fh=0;
- while(temp[i++]!='\0') j++;
- //将temp数据指针移向后一个空位,将LCD显示指针移向下一个空位
- }
- if((i==0)&(n=='-')&(fh==0)) //如果输入的第一个数是负数则执行
- {
- fh=1; //表示有负号
- temp[0]='-'; //保存负号
- i++;
- LCD_dsp_char(j++,0,n); //输出减号
- if(flag==0) continue;
- }
- if(((n>='0')&(n<='9')|((n=='c')&(xsd==0)))&(dh==0))
- {
- if(n=='c')
- {
- n='.';
- xsd=1; //防止再次按下c后继续出现小数点
- }
- temp[i++]=n; //保存输入的数字
- LCD_dsp_char(j++,0,n); //显示并将光标移至下一位(光标未显示)
-
- }
- if(((n=='+')|(n=='-')|(n=='*')|(n=='/'))&((flag==0)|(dh==1)))
- //输入完第一个操作数之后或者完成一次计算之后按下运算符按键时执行
- {
- flag=1; //之后输入的操作数是第二个操作数
- fuhao=n;
- temp[i]='\0'; //表示为字符串
- a=atof(temp); //转换为数据
- i=0;
- dh=0;
- xsd=0; //之后第二个操作数中可以添加一个小数点
- 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;
- } //显示运算符
- }
- if((n=='=')&(flag==1)) //已输入完第二个操作数并按下等号
- {
- dh=1;
- temp[i]='\0';
- b=atof(temp);
- i=0;
- xsd=0;
- LCD_dsp_char(j,0,'='); //显示等号
- switch(fuhao)
- {
- case '+': a=a+b; break;
- case '-': a=a-b; break;
- case '*': a=a*b; break;
- case '/': a=a/b; break;
- } //计算
- if(a>9999)
- {
- sprintf(temp,"%s","Error");
- //若计算结果超过四位数则输出错误信息
- 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; //恢复初始化
- }
- else
- {
- sprintf(temp,"%g",a); //输出计算结果
- 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; //恢复初始化
- }
- }
- }
- 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); //当busy=1,即LCD忙时,等待
- }
- void write_com(unsigned char com) //写显示命令
- {
- P0=com;
- rs=0;
- rw=0;
- lcden=0;
- check();
- lcden=1;
- }
- void write_data(unsigned char date) //写显示数据
- {
- P0=date;
- rs=1;
- rw=0;
- lcden=0;
- check();
- lcden=1;
- }
- void init() //初始化LCD
- {
- write_com(0x38); //16x2行显示,5x7点阵,8位数据接口
- write_com(0x0c); //开显示,光标不显示、不闪烁
- write_com(0x06); //光标自增,画面不动
- write_com(0x80); //选择第一行
- write_com(0x01); //清屏
- }
- void LCD_set_xy( unsigned char x, unsigned char y )//设置LCD显示的位置
- {
- unsigned char address;
- if (y == 0) //y=0为第一行
- address = 0x80 + x; //x=0为一行的第一个
- else //第二行
- address =0xc0+ x;
- write_com(address); //设置数据指针位置
- }
- void LCD_dsp_char( unsigned x,unsigned char y,unsigned char dat)
- //单个字符显示函数
- {
- LCD_set_xy( x, y ); //设置显示位置
- write_data(dat); //写入待显示数据
- }
- void LCD_dsp_string(unsigned char X,unsigned char Y,unsigned char *s)
- //字符串显示函数
- {
- LCD_set_xy( X, Y );
- while (*s) //当字符串未到达结尾('\0')时,循环输出单个字符
- {
- write_data(*s);
- s ++; //指向下一个字符
- }
- }
复制代码
所有资料51hei提供下载:
计算器.zip
(1.24 MB, 下载次数: 65)
|