|
發布時間: 2018-11-9 21:26
正文摘要:本人大一, 現在要做51單片機的計算器 具體要求有三 1.使用矩陣鍵盤 2.lcd1602 顯示 3.支持四則混合運算,例如5/10*13+4 求大神解決 當然有源程序參考就更好了 我在網上找到有人做出來過的,效果就像這樣 ... |
我對你情有獨鐘 發表于 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 求大神 |