- #include <reg51.h>
- #include <stdio.h>
- #include <intrins.h>
- #define u8 unsigned char
- #define u16 unsigned char
- sbit LCDEN=P3^4;
- sbit RS=P3^5;
- sbit RW=P3^6;
- sbit BF=P0^7;
- u8 code keyval[]="789/456*123-c0=+"; //按键对应的符号
- u8 data1[10];
- u8 k=0;
- char m[10]={0};
- double sum=0;
- void delay(u16 x) //延时x毫秒
- {
- u16 i,j;
- for(i=0;i<x;i++)
- for(j=0;j<115;j++)
- ;
- }
- u8 keypad4_4()//按键扫描函数:要去抖,若有按键按下,返回对应的按键值(0-15),没有按键按下返回16
- {
- u8 i,row,temp;
- u8 key=16;//按键号,初值设置为16,目的是:没有按键按下时返回16;
- //若不设初值(默认值为0),没有按键按下时,将返回0,会误认为0被按下
- row=0xef; //从第一列开始
- for(i=0;i<4;i++)
- {
- P1=0xff;
- P1=row; //第i列信号,对应列为低,其他全为高
- row=_crol_(row,1); //生成下一列信号
- temp=P1; //读入扫描信号
- temp=temp&0x0f; //屏蔽高4位列信号,只保留低4位行信号
- if(temp!=0x0f)//有按键被按下,因为第i列某行有按键按下,则低4位中有一位为低
- {
- delay(20); //延时去抖
- temp=P1;
- temp=temp&0x0f;
- if(temp!=0x0f) //再次确认有按键被按下
- {
- switch(temp) //根据低4位行信号,判断哪个按键被按下
- {
- case 0x0e:key=0+i;break; //第i列第1行按键被按下
- case 0x0d:key=4+i;break; //第i列第2行按键被按下
- case 0x0b:key=8+i;break; //第i列第3行按键被按下
- case 0x07:key=12+i; //第i列第4行按键被按下
- }
-
- do
- {
- temp=P1; //再次扫描按键
- temp=temp&0x0f;
- }while(temp!=0x0f); //等待按键释放
- }
- }
- }
- return(key);//扫面结束,返回按键值
- }
- unsigned char DectectBusyBit(void)//状态判断函数(忙/闲?)
- {
- bit result;
- P0 = 0xff; //读状态前先置高电平,防止误判
- RS = 0;
- delay(5);
- RW = 1;
- LCDEN = 1;
- delay(5);
- result=BF; //若LCM忙,则反复测试,在此处原地踏步;当LCM闲时,才往下继续
- LCDEN = 0;
- return result;
- }
- void WrComLCD(unsigned char ComVal)//写命令函数
- {
- while(DectectBusyBit()==1); //先检测LCM是否空闲
- RS = 0;
- delay(1);
- RW = 0;
- LCDEN = 1;
- P0 = ComVal;
- delay(1);
- LCDEN = 0;
- }
- void WrDatLCD(unsigned char DatVal)//写数据函数
- {
- while(DectectBusyBit()==1);
- RS = 1;
- delay(1);
- RW = 0;
- LCDEN = 1;
- P0 = DatVal;
- delay(1);
- LCDEN = 0;
- }
- void LCD_Init(void)//1602初始化函数
- {
- WrComLCD(0x38); // 功能设定:16*2行、5*7点阵、8位数据接口
- WrComLCD(0x38);
- WrComLCD(0x38);
- //多次重复设定功能指令,因为LCD启动后并不知道使用的是4位数据接口还是8位的,所以开始时总是默认为4位
- WrComLCD(0x01); // 清屏
- WrComLCD(0x06); // 光标自增、屏幕不动
- delay(1); // 延时,等待上面的指令生效,下面再显示,防止出现乱码
- WrComLCD(0x0c); // 开显示
- }
-
- void compute(){
- u8 i,j=0,k,n=0;
- char data3[10]={0};
- int sum1,data2[10]={0};
- sum=0;
-
- for(i=0;data1[i]!='\0';i++){
- if(data1[i]!='+' && data1[i]!='-' && data1[i]!='*' && data1[i]!='/'){
- data2[j] =data2[j]*10+(data1[i]-'0');
- }
- else{
- data3[n++] = data1[i];
- j++;
- }
- }
- for(i=0;i<n;i++){
- if(i==0){
- if(data3[0]=='+') sum = data2[0] + data2[1];
- if(data3[0]=='-') sum = data2[0] - data2[1];
- if(data3[0]=='*') sum = data2[0] * data2[1];
- if(data3[0]=='/') sum = data2[0] / (double)data2[1];
- }
- if(i==1){
- if(data3[1]=='+') sum = sum+data2[2];
- if(data3[1]=='-') sum = sum-data2[2];
- if(data3[1]=='*') sum = sum*data2[2];
- if(data3[1]=='/') sum = sum/((float)data2[2]);
- }
- if(i==2){
- if(data3[2]=='+') sum = sum+data2[3];
- if(data3[2]=='-') sum = sum-data2[3];
- if(data3[2]=='*') sum = sum*data2[3];
- if(data3[2]=='/') sum = sum/((float)data2[3]);
- }
-
- }
- //判断是小数输出还是整数输出
- sum1 = sum;
- if(sum1==sum){
- sprintf(m,"%d",sum1);
- }
- else{
- sprintf(m,"%f",sum);
- }
- //把结果输出出来
- for(k=0;m[k]!='\0';k++){
- WrDatLCD(m[k]);
- }
- }
- void main()
- {
- u8 y;
- LCD_Init();
- delay(5); //延时,等待初始化完成
- WrDatLCD('0');
- WrComLCD(0x80); //设置显示地址第一行第一位:0X00(0x80+0x00)
- while(1){
- y= keypad4_4();
- if(y==12) { k=0;WrComLCD(0x01);WrDatLCD('0'); WrComLCD(0x80);} //清屏
-
- if(y==14) {
- WrComLCD(0xC0); WrDatLCD(keyval[y]); WrDatLCD(' '); data1[k]='\0';compute();//调用出结果函数
- }
- if(y<16 && y!=12 && y!=14)
- {
- WrDatLCD(keyval[y]);
- data1[k++]= keyval[y];
- }
- }
-
- }
复制代码 |