可以實現(xiàn)二進制、八進制、十進制計算,進制之間可以通過按鈕點擊轉(zhuǎn)換
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
單片機源程序如下:
- #include <reg51.h>
- #include <stdio.h>
- #include <intrins.h>
- #include <string.h>
- #include <math.h>
- #include <stdlib.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;
- sbit change_m=P3^7;
- u8 code keyval[]="789/456*123-c0=+"; //按鍵對應(yīng)的符號
- 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<x;i++)
- for(j=0;j<115;j++)
- ;
- }
- 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()//按鍵掃描函數(shù):要去抖,若有按鍵按下,返回對應(yīng)的按鍵值(0-15),沒有按鍵按下返回16
- {
- u8 i,row,temp;
- u8 key=16;//按鍵號,初值設(shè)置為16,目的是:沒有按鍵按下時返回16;
- //若不設(shè)初值(默認值為0),沒有按鍵按下時,將返回0,會誤認為0被按下
- row=0xef; //從第一列開始
- for(i=0;i<4;i++)
- {
- P1=0xff;
- P1=row; //第i列信號,對應(yīng)列為低,其他全為高
- 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) //根據(jù)低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);//掃面結(jié)束,返回按鍵值
- }
- unsigned char DectectBusyBit(void)//狀態(tài)判斷函數(shù)(忙/閑?)
- {
- bit result;
- P0 = 0xff; //讀狀態(tài)前先置高電平,防止誤判
- RS = 0;
- delay(5);
- RW = 1;
- LCDEN = 1;
- delay(5);
- result=BF; //若LCM忙,則反復測試,在此處原地踏步;當LCM閑時,才往下繼續(xù)
- LCDEN = 0;
- return result;
- }
- void WrComLCD(unsigned char ComVal)//寫命令函數(shù)
- {
- while(DectectBusyBit()==1); //先檢測LCM是否空閑
- RS = 0;
- delay(1);
- RW = 0;
- LCDEN = 1;
- P0 = ComVal;
- delay(1);
- LCDEN = 0;
- }
- void WrDatLCD(unsigned char DatVal)//寫數(shù)據(jù)函數(shù)
- {
- while(DectectBusyBit()==1);
- RS = 1;
- delay(1);
- RW = 0;
- LCDEN = 1;
- P0 = DatVal;
- delay(1);
- LCDEN = 0;
- }
- void LCD_Init(void)//1602初始化函數(shù)
- {
- WrComLCD(0x38); // 功能設(shè)定:16*2行、5*7點陣、8位數(shù)據(jù)接口
- WrComLCD(0x38);
- WrComLCD(0x38);
- //多次重復設(shè)定功能指令,因為LCD啟動后并不知道使用的是4位數(shù)據(jù)接口還是8位的,所以開始時總是默認為4位
- WrComLCD(0x01); // 清屏
- WrComLCD(0x06); // 光標自增、屏幕不動
- delay(1); // 延時,等待上面的指令生效,下面再顯示,防止出現(xiàn)亂碼
- 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]!='\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++;
- }
- }
- a=data2[0];
- b=data2[1];
- c=data2[2];
- d=data2[3];
- if(flag == 1) //如果二進制
- {
- a=convertBinaryToDecimal(a);
- b=convertBinaryToDecimal(b);
- c=convertBinaryToDecimal(c);
- d=convertBinaryToDecimal(d);
- }
- if(flag == 2) //如果8進制
- {
- a=convertBinaryToDecimal8(a);
- b=convertBinaryToDecimal8(b);
- c=convertBinaryToDecimal8(c);
- d=convertBinaryToDecimal8(d);
- }
-
- for(i=0;i<n;i++){
- if(i==0){
- if(data3[0]=='+') sum = a + b;
- if(data3[0]=='-') sum = a - b;
- if(data3[0]=='*') sum = a * b;
- if(data3[0]=='/') sum = a / (double)b;
- }
- if(i==1){
- if(data3[1]=='+') sum = sum+c;
- if(data3[1]=='-') sum = sum-c;
- if(data3[1]=='*') sum = sum*c;
- if(data3[1]=='/') sum = sum/((float)c);
- }
- if(i==2){
- if(data3[2]=='+') sum = sum+d;
- if(data3[2]=='-') sum = sum-d;
- if(data3[2]=='*') sum = sum*d;
- if(data3[2]=='/') sum = sum/((float)d);
- }
-
- }
- //判斷是小數(shù)輸出還是整數(shù)輸出
- sum1 = sum;
- if(sum1==sum){
-
- switch(flag)
- {
- case 0:sprintf(m,"%d",sum1);break;
- case 2:sprintf(m,"%o",sum1);break;
- case 1:
- for(a=0;a<6;a++)
- {
- getValue[a]=0;
- }
- a=0;
- while(sum1!=0)
- {
-
- o=sum1/2;
- a++;
- getValue[a]=sum1-o*2;
- sum1=sum1/2;
- }
- for(b=a;b>=1;b--)
- {
- WrDatLCD('0'+getValue[b]);
- }
- break;
- default:break;
- }
- }
- else{
- sprintf(m,"%f",sum);
- }
- if(flag!=1){
- //把結(jié)果輸出出來
- for(k=0;m[k]!='\0';k++){
- WrDatLCD(m[k]);
- }
- }
- WrComLCD(0x80+0x40+15);
- switch(flag)
- {
- case 0: WrDatLCD('D');break;
- case 1: WrDatLCD('B');break;
- case 2: WrDatLCD('O');break;
- }
- }
- void main()
- {
- int y;
- LCD_Init();
- delay(5); //延時,等待初始化完成
- WrDatLCD('0');
- WrComLCD(0x80); //設(shè)置顯示地址第一行第一位:0X00(0x80+0x00)
- while(1){
-
- y= keypad4_4();
- if(y==12) { k=0;WrComLCD(0x01);WrDatLCD('0'); WrComLCD(0x80);} //清屏
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
計算器.zip
(96.7 KB, 下載次數(shù): 84)
2020-12-30 19:11 上傳
點擊文件名下載附件
|