硬件设计
工作原理
利用矩阵键盘进行按键的输入,通过对矩阵键盘的扫描,获取用户的输入,并实时的显示在1602液晶上,每次获取到输入时,根据软件设计的相应方法对输入进行处理、运算,输入结束后(以“=“为标志),将最终的运算结果输出的液晶上。
仿真图1: (LCD1602显示,支持负数和进制运算及有限的连续运算,连续运算时候无法识别优先级,不支持小数;)
仿真图2: LCD1602显示,支持负数和小数及开根号,不支持连续运算;
程序设计1
#include #include #include #include #include #include #define u8 unsigned char #define u16 unsigned char sbit LCDEN=P3^4; sbit RS=P3^5; sbit RW=P3^6; sbit BF=P0^7; sbit change_m=P3^7; u8 code keyval[]="789/456*123-c0=+"; //按键对应的符号 u8 data1[10]; u8 k=0; char m[8]={0}; double sum=0; int flag; void WrDatLCD(unsigned char DatVal); void WrComLCD(unsigned char ComVal); void delay(u16 x) //延时x毫秒 { u16 i,j; for(i=0;i ; } int convertBinaryToDecimal(long n) { int decimalNumber = 0, i = 0, remainder; while (n != 0) { remainder = n % 10; n /= 10; decimalNumber += remainder * pow(2, i); ++i; } return decimalNumber; } int convertBinaryToDecimal8(long n) { int decimalNumber = 0, i = 0, remainder; while (n != 0) { remainder = n % 10; n /= 10; decimalNumber += remainder * pow(8, i); ++i; } return decimalNumber; } 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); //等待按键释放 } } if(change_m == 0) { delay(50); if(change_m == 0) { flag++; if(flag == 3) { flag = 0; } } while(!change_m); } } 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[3]={0}; int sum1,data2[4]={0}; int a,b,c,d,o; int getValue[6]={0}; sum=0; for(i=0;data1[i]!='