我对你情有独钟 发表于 2019-3-30 18:08 0X30 在LCD上显示数字‘0’;加0X30也就是在0的基础加上你要显示的数值,这样才能显示你要的数值。当然方法不止这一种 |
| 用switch语句 |
| 为什么加0x30 |
| 1、用R5、R6、R7三位显示,段码为0,全暗,段码为0xff,全亮。 2、R3用于保存运算符。 3、两数都用B压入栈中,最后取结果时可以分别弹出,并根据操作符计算。 4、程序在两数的第一位默认都输入数字,其他位置皆可复位。 5、一次计算完成后、按任意。 |
|
/* S16 S12 S8 S4分别是123+ S15 S11 S7 S3分别是456- S14 S10 S6 S2分别是789* S13 S9 S5 S1分别是0 CLR = / */ /* 实现两个数的运算,每个数的位数至少可以八位 */ #include<reg52.h> typedef unsigned char uint8; typedef unsigned int uint16; sbit rw=P2^5; sbit rs=P2^6; sbit e=P2^7; sbit led=P3^7; sbit beep=P2^0; uint8 key,num; uint8 fuhao;//定义具体的那个符号,是加减还是乘除。 uint8 flag; //定义有没有按下符号键,这个是统称 long a,b,c,d; //定义运算数据的第一个和第二个及等于的数变量 uint8 k; //定义小数点后面显示的位数 uint8 biao; uint8 dat1[]={1,2,3,0x2b-0x30, 4,5,6,0x2d-0x30, 7,8,9,0x2a-0x30, 0,0x01-0x30,0x3d-0x30,0x2b-0x30 };//保存显示的数据 void delay(uint16 i) { while(i--); } void lcdwrc(uint8 c) { delay(1000); rs=0; rw=0; e=0; P0=c; e=1; delay(1000); e=0; } void lcdwrd(uint8 dat) { delay(1000); rs=1; rw=0; e=0; P0=dat; e=1; delay(1000); e=0; rs=0; } void lcdinit() { delay(1500); lcdwrc(0x38); delay(500); lcdwrc(0x38); delay(500); lcdwrc(0x38); delay(500); lcdwrc(0x38); lcdwrc(0x08); lcdwrc(0x01); lcdwrc(0x06); lcdwrc(0x0c); key=0; num=0; flag=0; fuhao=0; a=0; b=0; c=0; d=0; biao=0; led=0; } void keyscan() { P1=0xfe; //令第一行为0,然后判断是哪一列按下 if(P1!=0xfe) { delay(1000); if(P1!=0xfe) { key=P1&0xf0; switch(key) { case 0xe0: num=0;break; //1 case 0xd0: num=1;break; //2 case 0xb0: num=2;break; //3 case 0x70: num=3;break; //加 } } while(P1!=0xfe); if(num==0||num==1||num==2) //确认第一行的数1,2,3 { if(flag==0) //没有按下符号键 { //led=1; a=a*10+dat1[num]; } else { //led=1; b=b*10+dat1[num]; } } if(num==3) { //led=0; flag=1; fuhao=1;//加号+ } lcdwrd(0x30+dat1[num]); } P1=0xfd; //令第二行为0,判断是哪一列按下 if(P1!=0xfd) { delay(1000); if(P1!=0xfd) { key=P1&0xf0; switch(key) { case 0xe0: num=4;break; //4 case 0xd0: num=5;break; //5 case 0xb0: num=6;break; //6 case 0x70: num=7;break; //减— } } while(P1!=0xfd); if(num==4||num==5||num==6) { if(flag==0) //没有按下符号键 { //led=1; a=a*10+dat1[num]; } else { //led=1; b=b*10+dat1[num]; } } else { flag=1; fuhao=2;//带表减号 } lcdwrd(0x30+dat1[num]); } P1=0xfb; //令第三行为0,判断哪一列按下 if(P1!=0xfb) { delay(1000); if(P1!=0xfb) { key=P1&0xf0; switch(key) { case 0xe0: num=8;break; //7 case 0xd0: num=9;break; //8 case 0xb0: num=10;break; //9 case 0x70: num=11;break; //乘* } } while(P1!=0xfb); if(num==8||num==9||num==10) { if(flag==0) //没有按下符号键 { //led=1; a=a*10+dat1[num]; } else { //led=1; b=b*10+dat1[num]; } } else { flag=1; fuhao=3;//带表乘号* } lcdwrd(0x30+dat1[num]); } P1=0xf7; //令第四行为0,判断哪一列按下 if(P1!=0xf7) { delay(1000); if(P1!=0xf7) { key=P1&0xf0; switch(key) { case 0xe0: num=12;break; //0 case 0xd0: num=13;break; //清除rst case 0xb0: num=14;break; //等号= case 0x70: num=15;break; //除/ } } while(P1!=0xf7); switch(num) { case 12: if(flag==0) //没有按下符号键 { //led=1; a=a*10+dat1[num]; lcdwrd(0x30); } else { //led=1; b=b*10+dat1[num]; lcdwrd(0x30); } break; case 13: lcdwrc(0x01); //清屏指令 a=0; b=0; flag=0; fuhao=0; break; case 15: flag=1; fuhao=4; lcdwrd(0x2f);//除号/ break; case 14: if(fuhao==1)//加 { lcdwrc(0x4f+0x80); lcdwrc(0x04);//设置光标左移,屏幕不移动 c=a+b; while(c!=0) //一位一位显示 { lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置 c=c/10;//取前面的结果数据 } lcdwrd(0x3d); //显示等于号= a=0; b=0; flag=0; fuhao=0;//全部清除为0 } if(fuhao==2) //减 { lcdwrc(0x4f+0x80); lcdwrc(0x04);//设置光标左移,屏幕不移动 if(a>b) c=a-b; else c=b-a; while(c!=0) //一位一位显示 { lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置 c=c/10;//取前面的结果数据 } if(a<b) lcdwrd(0x2d); //显示-号 lcdwrd(0x3d); //显示等于号= a=0; b=0; flag=0; fuhao=0;//全部清除为0 } if(fuhao==3)//乘法 { lcdwrc(0x4f+0x80); lcdwrc(0x04);//设置光标左移,屏幕不移动 c=a*b; while(c!=0) //一位一位显示 { lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置 c=c/10;//取前面的结果数据 } lcdwrd(0x3d); //显示等于号= a=0; b=0; flag=0; fuhao=0;//全部清除为0 } if(fuhao==3)//乘法 { lcdwrc(0x4f+0x80); lcdwrc(0x04);//设置光标左移,屏幕不移动 c=a*b; while(c!=0) //一位一位显示 { lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置 c=c/10;//取前面的结果数据 } lcdwrd(0x3d); //显示等于号= a=0; b=0; flag=0; fuhao=0;//全部清除为0 } if(fuhao==4) { k=0; lcdwrc(0x4f+0x80); lcdwrc(0x04);//设置光标左移,屏幕不移动 c=(long)(((float)a/b)*1000);//强制转换为long。 while(c!=0) //一位一位显示 { k++; lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置 c=c/10;//取前面的结果数据 if(k==3) { lcdwrd(0x2e); k=0; } } if(a/b<0) //如果a比b小的话那么除的结果最高位是0 { lcdwrd(0x30); } lcdwrd(0x3d); //显示等号 a=0; b=0; flag=0; fuhao=0;//全部清除为0 } break; } } } void main() { lcdinit(); while(1) { keyscan(); } } 这个代码用清翔的单片机能成功 |
|
/******************************** 实验箱实现计算器 ********************************* 器件连接: 89C51 P0.0 - LCD D0 89C51 P0.1 - LCD D1 89C51 P0.2 - LCD D2 89C51 P0.3 - LCD D3 89C51 P0.4 - LCD D4 89C51 P0.5 - LCD D5 89C51 P0.6 - LCD D6 89C51 P0.7 - LCD D7 89C51 P2.0 - LCD RS 89C51 P2.1 - LCD RW 89C51 P2.2 - LCD EN 89C51 P3.0 - k1 89C51 P3.1 - k2 89C51 P3.2 - k3 89C51 P1.0 - BUTTON L1 89C51 P1.1 - BUTTON L2 89C51 P1.2 - BUTTON L3 89C51 P1.3 - BUTTON L4 89C51 P1.4 - BUTTON H1 89C51 P1.5 - BUTTON H2 89C51 P1.6 - BUTTON H3 89C51 P1.7 - BUTTON H4 ********************************* 按键对应数值 1 2 3 + 4 5 6 - 7 8 9 * . 0 # / 独立按键 k1: ( k2: ) k3: C ********************************/ #include <reg52.h> #include <stdio.h> #include <stdlib.h> #include <math.h> #define OK 1 #define ERROR 0 typedef unsigned char uchar; typedef unsigned int uint; typedef char Status; sbit rs = P2 ^ 0; // LCD-RS sbit rw = P2 ^ 1; // LCD-RW sbit en = P2 ^ 2; // LCD-EN sbit leftBracket = P3 ^ 0; // 右括号 sbit rightBracket = P3 ^ 1; // 左括号 sbit reset = P3 ^ 2; // 重置算式按键 /*******************************/ void Delay(uint z); // 延时函数 void UART_Init(); // 串口初始化 void UART_Send_Byte(uchar ucData); // 串口发送单字节 void UART_Send_Str(uchar *string); // 串口发送字符串 void UART_Send_Enter(); // 串口发送回车 void Init_LCD(); // 初始化LCD1602 void WriteData(uchar dat); // LCD写字节 void WriteCom(uchar com); // LCD写指令 void ClearScreen(); // LCD清屏 int InputJudge(char keyValue); // 判断按键是操作符还是操作数 char PriorityJudge(char optr1, char optr2); // 操作数比较 float Calc(char optr, float num1, float num2); // 四则运算 void LCD_Float(float f); // 测试函数,LCD第二行显示float void LCD_Int(int dat); // 测试函数,LCD第二行显示int void LCD_Char(char c); // 测试函数,根据指针显示char /*******************************/ void main() { /* 定义运算变量 */ char arrayChar[20]; // 操作数存放数组 float arrayFloat[20]; // 操作数存放数组 int topChar; // 操作符数量 int topFloat; // 操作数数量 char tempChar; // 读取数组顶部存放的操作符 float tempFloat; // 读取数组顶部存放的操作数 char optr; // 四则运算操作符 float num1, num2; // 四则运算操作数 int i; // i作为临时循环使用 int tenPower; // 参与小数点运算时被除数 /* 定义硬件操作变量 */ unsigned char temp; // 按键检索时存放临时值 unsigned char key; // 按键值 16进制 unsigned char keyValue; // 按键值 char类型 unsigned int ipos; // LCD显示指针计数 unsigned int flag; // flag标记,操作数为1 操作符为0 点运算为2 re: // 按下C键复位,重新输入计算式子 /* 初始化变量 */ for (i = 0; i < 20; ++i) { arrayChar[i] = '0'; arrayFloat[20] = 0; } topChar = 0; topFloat = 0; tenPower = 1; ipos = 0; flag = 0; /* 压入# */ arrayChar[topChar] = '#'; topChar++; /* 初始化硬件 */ UART_Init(); Init_LCD(); Delay(100); while(1) { P1 = 0xf0; leftBracket = 1; rightBracket = 1; reset = 1; /* 按键检测 */ if (P1 != 0xf0 || !leftBracket || !rightBracket || !reset) { Delay(20); if (P1 != 0xf0) { temp = P1; P1 = 0x0f; key = temp | P1; while(P1 != 0x0f); ipos++; if (ipos == 16) { ClearScreen(); ipos = 0; } /* 按键赋值 */ switch(key) { case 0xEE:keyValue = '1';WriteData(keyValue);break; case 0xED:keyValue = '2';WriteData(keyValue);break; case 0xEB:keyValue = '3';WriteData(keyValue);break; case 0xDE:keyValue = '4';WriteData(keyValue);break; case 0xDD:keyValue = '5';WriteData(keyValue);break; case 0xDB:keyValue = '6';WriteData(keyValue);break; case 0xBE:keyValue = '7';WriteData(keyValue);break; case 0xBD:keyValue = '8';WriteData(keyValue);break; case 0xBB:keyValue = '9';WriteData(keyValue);break; case 0x7D:keyValue = '0';WriteData(keyValue);break; case 0xE7:keyValue = '+';WriteData(keyValue);break; case 0xD7:keyValue = '-';WriteData(keyValue);break; case 0xB7:keyValue = '*';WriteData(keyValue);break; case 0x77:keyValue = '/';WriteData(keyValue);break; case 0x7E:keyValue = '.';WriteData(keyValue);break; case 0x7B:keyValue = '#';WriteData('=');break; } } else if(!leftBracket) { Delay(20); if (!leftBracket) { while(!leftBracket); keyValue = '('; WriteData(keyValue); } } else if(!rightBracket) { Delay(20); if (!rightBracket) { while(!rightBracket); keyValue = ')'; WriteData(keyValue); } } else if(!reset) // 当按下复位C键时,清屏并回到初始状态 { Delay(20); if (!reset) { while(!reset); ClearScreen(); goto re; } } /* 运算过程 */ if (keyValue == '.') // 当为点运算时,flag标识为2,后续输入的数字进行小数运算 { flag = 2; tenPower = 1; continue; } if (InputJudge(keyValue)) //判断输入是否为数字 { if (flag == 0) // <上次是操作符,本次是操作数> 压栈 { arrayFloat[topFloat] = (float)(keyValue - '0'); topFloat++; flag = 1; continue; } else if(flag == 1) // <输入10位以上数字> 弹栈值*10+本次值 { topFloat--; tempFloat = arrayFloat[topFloat]; arrayFloat[topFloat] = (float)(tempFloat * 10 + (keyValue - '0')); topFloat++; flag = 1; continue; } else if (flag == 2) // <输入小数> 弹栈值+本次值/(10的n次方) { topFloat--; tempFloat = arrayFloat[topFloat]; tenPower = tenPower * 10; tempFloat = tempFloat + ((float)(keyValue - '0') / tenPower); arrayFloat[topFloat] = tempFloat; topFloat++; flag = 2; continue; } } /**************************************************** 当按键值为符号时,进行计算或压入运算符组 优先级为 > 时,重复对比并计算 ****************************************************/ else { reCalc: tempChar = arrayChar[topChar - 1]; switch(PriorityJudge(tempChar, keyValue)) // 判断本次输入符号与操作符数组顶部元素优先级 { /**************************************************** 本次输入压入操作符组顶部,完毕后重新获取按键 ****************************************************/ case '<': arrayChar[topChar] = keyValue; topChar++; flag = 0; continue; /**************************************************** ()或#闭合时,弹出顶部元素 ()闭合后重新获取按键 #弹出说明公式计算完毕,LCD显示结果并进入死循环 计算结束后,按下复位键代码回到Line 90,程序重置 ****************************************************/ case '=': topChar--; tempChar = arrayChar[topChar]; if (tempChar == '#') { LCD_Float(arrayFloat[topFloat - 1]); /* LCD_Int(topFloat); UART_Send_Enter(); UART_Send_Str("End"); */ while(1) { if(!reset) { Delay(20); if (!reset) { while(!reset); ClearScreen(); goto re; // line 90 } } } } flag = 0; continue; /**************************************************** 弹出两个操作数和一个操作符进行四则运算 运算结束后将结果操作数压入 程序回到 reCalc处 Line231,继续弹出操作符对比 ****************************************************/ case '>': topChar--; optr = arrayChar[topChar]; topFloat--; num2 = arrayFloat[topFloat]; topFloat--; num1 = arrayFloat[topFloat]; arrayFloat[topFloat] = Calc(optr, num1, num2); topFloat++; flag = 0; goto reCalc; } } } /* char串口打印测试 UART_Send_Enter(); UART_Send_Str("optr:"); UART_Send_Byte(optr); int串口打印测试 UART_Send_Enter(); UART_Send_Byte(topFloat + '0'); */ } } void UART_Init() { SCON = 0x50; TMOD = 0x20; PCON = 0x00; TH1 = 0xFD; TL1 = 0xFD; TR1 = 1; ES = 1; EA = 1; ET1 = 0; } void UART_Send_Byte(uchar ucData) { SBUF = ucData; while(!TI); TI = 0; } void UART_Send_Str(uchar *string) { while(*string) UART_Send_Byte(*string++); } void UART_Send_Enter() { UART_Send_Byte(0x0d); UART_Send_Byte(0x0a); } void Init_LCD() { en = 0; WriteCom(0x38); WriteCom(0x0e); WriteCom(0x06); WriteCom(0x01); WriteCom(0x80 + 0x1); } void WriteData(uchar dat) { rs = 1; rw = 0; P0 = dat; Delay(5); en = 1; Delay(5); en = 0; } void WriteCom(uchar com) { rs = 0; rw = 0; P0 = com; Delay(5); en = 1; Delay(5); en = 0; } void ClearScreen() { WriteCom(0x01); } void Delay(uint z) { uint x, y; for(x = z; x > 0; x--) for(y = 110; y > 0; y--); } int InputJudge(char keyValue) { switch(keyValue) { case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':return OK;break; case '+':case '-':case '*':case '/':case '(':case ')':case '#':return ERROR;break; default:break; } } char PriorityJudge(char optr1, char optr2) { int i, j; char priorityTable[7][7] = { // + - * / ( ) # {'>', '>', '<', '<', '<', '>', '>'}, // + {'>', '>', '<', '<', '<', '>', '>'}, // - {'>', '>', '>', '>', '<', '>', '>'}, // * {'>', '>', '>', '>', '<', '>', '>'}, // / {'<', '<', '<', '<', '<', '=', '0'}, // ( {'>', '>', '>', '>', '0', '>', '>'}, // ) {'<', '<', '<', '<', '<', '0', '='} // # }; switch(optr1) { case '+':i = 0;break; case '-':i = 1;break; case '*':i = 2;break; case '/':i = 3;break; case '(':i = 4;break; case ')':i = 5;break; case '#':i = 6;break; } switch(optr2) { case '+':j = 0;break; case '-':j = 1;break; case '*':j = 2;break; case '/':j = 3;break; case '(':j = 4;break; case ')':j = 5;break; case '#':j = 6;break; } return priorityTable[i][j]; } float Calc(char optr, float num1, float num2) { switch(optr) { case '+':return (num1 + num2);break; case '-':return (num1 - num2);break; case '*':return (num1 * num2);break; case '/':return (num1 / num2);break; } } void LCD_Float(float f) { char str[7]; int i, length; for (i = 0; i < 7; ++i) str[i] = '0'; length = sprintf(str, "%g", f); WriteCom(0x80 + 0x40); Delay(20); for (i = 0; i < length; ++i) { WriteData(str[i]); Delay(20); } } void LCD_Int(int dat) { char str[7]; int i, length; for (i = 0; i < 7; ++i) str[i] = '0'; length = sprintf(str, "%d", dat); WriteCom(0x80 + 0x48); Delay(20); for (i = 0; i < length; ++i) { WriteData(str[i]); Delay(20); } } void LCD_Char(char c) { WriteData(c); Delay(20); } |
|
help help help 求大神 |