找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3700|回復: 3
收起左側(cè)

單片機多進制計算器程序+Proteus仿真

[復制鏈接]
ID:425208 發(fā)表于 2020-12-30 19:13 | 顯示全部樓層 |閱讀模式
可以實現(xiàn)二進制、八進制、十進制計算,進制之間可以通過按鈕點擊轉(zhuǎn)換
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
2.png 51hei圖片20201230191217.png
單片機源程序如下:
  1. #include <reg51.h>
  2. #include <stdio.h>
  3. #include <intrins.h>
  4. #include <string.h>
  5. #include <math.h>
  6. #include <stdlib.h>


  7. #define u8  unsigned char
  8. #define u16  unsigned char
  9. sbit LCDEN=P3^4;
  10. sbit RS=P3^5;
  11. sbit RW=P3^6;
  12. sbit BF=P0^7;
  13. sbit change_m=P3^7;

  14. u8 code keyval[]="789/456*123-c0=+"; //按鍵對應(yīng)的符號
  15. u8 data1[10];
  16. u8 k=0;
  17. char  m[8]={0};
  18. double sum=0;
  19. int flag;
  20. void WrDatLCD(unsigned char DatVal);
  21. void WrComLCD(unsigned char ComVal);
  22. void delay(u16 x)          //延時x毫秒
  23. {
  24. u16 i,j;
  25. for(i=0;i<x;i++)
  26.         for(j=0;j<115;j++)
  27.                 ;
  28. }
  29. int convertBinaryToDecimal(long n)
  30. {
  31.         int decimalNumber = 0, i = 0, remainder;
  32.         while (n != 0)
  33.         {
  34.                 remainder = n % 10;
  35.                 n /= 10;
  36.                 decimalNumber += remainder * pow(2, i);
  37.                 ++i;
  38.         }
  39.         return decimalNumber;
  40. }

  41. int convertBinaryToDecimal8(long n)
  42. {
  43.         int decimalNumber = 0, i = 0, remainder;
  44.         while (n != 0)
  45.         {
  46.                 remainder = n % 10;
  47.                 n /= 10;
  48.                 decimalNumber += remainder * pow(8, i);
  49.                 ++i;
  50.         }
  51.         return decimalNumber;
  52. }





  53. u8 keypad4_4()//按鍵掃描函數(shù):要去抖,若有按鍵按下,返回對應(yīng)的按鍵值(0-15),沒有按鍵按下返回16
  54. {
  55. u8 i,row,temp;
  56. u8 key=16;//按鍵號,初值設(shè)置為16,目的是:沒有按鍵按下時返回16;
  57.           //若不設(shè)初值(默認值為0),沒有按鍵按下時,將返回0,會誤認為0被按下  
  58. row=0xef; //從第一列開始      
  59. for(i=0;i<4;i++)
  60. {
  61.         P1=0xff;  
  62.         P1=row;        //第i列信號,對應(yīng)列為低,其他全為高
  63.         row=_crol_(row,1);           //生成下一列信號
  64.         temp=P1; //讀入掃描信號
  65.         temp=temp&0x0f; //屏蔽高4位列信號,只保留低4位行信號
  66.         if(temp!=0x0f)//有按鍵被按下,因為第i列某行有按鍵按下,則低4位中有一位為低  
  67.         {  
  68.                 delay(20);  //延時去抖
  69.                 temp=P1;  
  70.                 temp=temp&0x0f;  
  71.                 if(temp!=0x0f)   //再次確認有按鍵被按下
  72.                   {  
  73.                 switch(temp)  //根據(jù)低4位行信號,判斷哪個按鍵被按下
  74.             {  
  75.                     case 0x0e:key=0+i;break; //第i列第1行按鍵被按下
  76.                 case 0x0d:key=4+i;break; //第i列第2行按鍵被按下  
  77.                 case 0x0b:key=8+i;break; //第i列第3行按鍵被按下
  78.                                 case 0x07:key=12+i;      //第i列第4行按鍵被按下
  79.             }
  80.                        
  81.                         do
  82.                         {
  83.                                 temp=P1;              //再次掃描按鍵
  84.                                   temp=temp&0x0f;  
  85.                           }while(temp!=0x0f); //等待按鍵釋放   
  86.                   }  
  87.      }
  88.        
  89.        
  90.                  if(change_m == 0)
  91.                  {
  92.                          delay(50);
  93.                          if(change_m == 0)
  94.                          {
  95.                                  flag++;
  96.                                  if(flag == 3)
  97.                                  {
  98.                                          flag = 0;
  99.                                  }
  100.                          } while(!change_m);
  101.                  }



  102.                  
  103. }  
  104. return(key);//掃面結(jié)束,返回按鍵值
  105. }

  106. unsigned char DectectBusyBit(void)//狀態(tài)判斷函數(shù)(忙/閑?)
  107. {   
  108.         bit result;
  109.         P0 = 0xff;        //讀狀態(tài)前先置高電平,防止誤判
  110.         RS = 0;
  111.         delay(5);
  112.     RW = 1;
  113.         LCDEN = 1;
  114.         delay(5);
  115.         result=BF; //若LCM忙,則反復測試,在此處原地踏步;當LCM閑時,才往下繼續(xù)
  116.         LCDEN = 0;
  117.         return result;                     
  118. }

  119. void WrComLCD(unsigned char ComVal)//寫命令函數(shù)
  120. {
  121.         while(DectectBusyBit()==1);         //先檢測LCM是否空閑
  122.         RS = 0;
  123.         delay(1);
  124.     RW = 0;
  125.         LCDEN = 1;
  126.         P0 = ComVal;
  127.         delay(1);
  128.         LCDEN = 0;       
  129. }

  130. void WrDatLCD(unsigned char DatVal)//寫數(shù)據(jù)函數(shù)
  131. {
  132. while(DectectBusyBit()==1);
  133.         RS = 1;
  134.         delay(1);
  135.     RW = 0;
  136.         LCDEN = 1;
  137.         P0 = DatVal;
  138.         delay(1);
  139.         LCDEN = 0;       
  140. }

  141. void LCD_Init(void)//1602初始化函數(shù)
  142. {
  143.         WrComLCD(0x38);     // 功能設(shè)定:16*2行、5*7點陣、8位數(shù)據(jù)接口
  144.         WrComLCD(0x38);
  145.         WrComLCD(0x38);   
  146. //多次重復設(shè)定功能指令,因為LCD啟動后并不知道使用的是4位數(shù)據(jù)接口還是8位的,所以開始時總是默認為4位
  147.         WrComLCD(0x01);    // 清屏
  148.         WrComLCD(0x06);    // 光標自增、屏幕不動  
  149.         delay(1);              // 延時,等待上面的指令生效,下面再顯示,防止出現(xiàn)亂碼
  150.         WrComLCD(0x0c);    // 開顯示
  151. }
  152.                          
  153. void compute(){
  154.         u8 i,j=0,k,n=0;
  155.         char data3[3]={0};
  156.         int sum1,data2[4]={0};
  157.         int a,b,c,d,o;
  158.         int getValue[6]={0};
  159.         sum=0;

  160.         for(i=0;data1[i]!='\0';i++){
  161.                   if(data1[i]!='+' && data1[i]!='-' && data1[i]!='*' && data1[i]!='/'){
  162.                           data2[j] =data2[j]*10+(data1[i]-'0');

  163.                   }
  164.                   else{
  165.                           data3[n++] = data1[i];
  166.                           j++;
  167.                   }
  168.         }
  169.         a=data2[0];
  170.         b=data2[1];
  171.         c=data2[2];
  172.         d=data2[3];
  173.         if(flag == 1)  //如果二進制
  174.         {
  175.         a=convertBinaryToDecimal(a);
  176.         b=convertBinaryToDecimal(b);
  177.         c=convertBinaryToDecimal(c);
  178.         d=convertBinaryToDecimal(d);
  179.         }
  180.         if(flag == 2)  //如果8進制
  181.         {
  182.         a=convertBinaryToDecimal8(a);
  183.         b=convertBinaryToDecimal8(b);
  184.         c=convertBinaryToDecimal8(c);
  185.         d=convertBinaryToDecimal8(d);
  186.         }

  187.        
  188.         for(i=0;i<n;i++){
  189.                 if(i==0){
  190.                         if(data3[0]=='+')  sum = a + b;
  191.                         if(data3[0]=='-')  sum = a - b;
  192.                         if(data3[0]=='*')  sum = a * b;
  193.                         if(data3[0]=='/')  sum = a / (double)b;
  194.                 }
  195.                 if(i==1){
  196.                         if(data3[1]=='+')  sum = sum+c;
  197.                         if(data3[1]=='-')  sum = sum-c;
  198.                         if(data3[1]=='*')  sum = sum*c;
  199.                         if(data3[1]=='/')  sum = sum/((float)c);
  200.                 }
  201.                 if(i==2){
  202.                         if(data3[2]=='+')  sum = sum+d;
  203.                         if(data3[2]=='-')  sum = sum-d;
  204.                         if(data3[2]=='*')  sum = sum*d;
  205.                         if(data3[2]=='/')  sum = sum/((float)d);
  206.                 }

  207.        
  208.         }

  209.         //判斷是小數(shù)輸出還是整數(shù)輸出
  210.         sum1 = sum;
  211.         if(sum1==sum){
  212.                
  213.                 switch(flag)
  214.                 {
  215.                         case 0:sprintf(m,"%d",sum1);break;
  216.                         case 2:sprintf(m,"%o",sum1);break;
  217.                         case 1:
  218.         for(a=0;a<6;a++)
  219.         {
  220.                 getValue[a]=0;
  221.         }
  222.         a=0;
  223.         while(sum1!=0)
  224.         {
  225.                
  226.                 o=sum1/2;
  227.                 a++;
  228.                 getValue[a]=sum1-o*2;
  229.                 sum1=sum1/2;
  230.         }               
  231.                         for(b=a;b>=1;b--)
  232.         {
  233.                         WrDatLCD('0'+getValue[b]);
  234.         }
  235.         break;
  236.                         default:break;
  237.                 }
  238.         }
  239.         else{
  240.                 sprintf(m,"%f",sum);
  241.         }

  242.         if(flag!=1){
  243.         //把結(jié)果輸出出來
  244.         for(k=0;m[k]!='\0';k++){
  245.          WrDatLCD(m[k]);
  246.         }
  247. }

  248.         WrComLCD(0x80+0x40+15);
  249.         switch(flag)
  250.         {
  251.                 case 0:                WrDatLCD('D');break;
  252.                 case 1:                WrDatLCD('B');break;
  253.                 case 2:                WrDatLCD('O');break;               
  254.         }
  255. }  





  256. void main()
  257. {
  258.         int y;       
  259.         LCD_Init();
  260.         delay(5);   //延時,等待初始化完成
  261.         WrDatLCD('0');
  262.                 WrComLCD(0x80);           //設(shè)置顯示地址第一行第一位:0X00(0x80+0x00)

  263.         while(1){

  264.        
  265.                 y= keypad4_4();
  266.                 if(y==12)  { k=0;WrComLCD(0x01);WrDatLCD('0'); WrComLCD(0x80);}   //清屏
  267. ……………………

  268. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼

所有資料51hei提供下載:
計算器.zip (96.7 KB, 下載次數(shù): 84)


評分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

回復

使用道具 舉報

ID:971250 發(fā)表于 2021-10-11 23:56 來自手機 | 顯示全部樓層
請問進制之間怎么轉(zhuǎn)換
回復

使用道具 舉報

ID:971940 發(fā)表于 2021-10-14 14:09 | 顯示全部樓層

請問進制之間怎么轉(zhuǎn)換
回復

使用道具 舉報

ID:971940 發(fā)表于 2021-10-14 14:49 | 顯示全部樓層
實現(xiàn)二進制、八進制、十進制計算,進制之間可以通過按鈕點擊轉(zhuǎn)換?可以通過哪個按鈕呀
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表