標題: 基于89c52的簡易計算器設計(仿真與源程序) [打印本頁]

作者: 歐陽ouy    時間: 2016-4-28 10:39
標題: 基于89c52的簡易計算器設計(仿真與源程序)
最近在學習單片機,把自己的資料分享給有需要的童鞋。




源碼:(部分預覽 完整代碼請下載附件): 計算器設計.7z (384.54 KB, 下載次數(shù): 410)
  1. #include<reg52.h>
  2. #include<math.h>
  3. #include "lcd1602_8.h"
  4. uint temp,num;//鍵盤掃描數(shù)值
  5. uchar keynum1=0,keynum2=0,sign=0,i=0,j=0; //按鍵計數(shù),符號標示
  6. uchar num1[8]={0},num2[8]={0};         //按鍵存儲數(shù)組
  7. float ans1=0,ans2=0,ans=0,point=0; //運算數(shù)據(jù)
  8. bit conflag=0;         //繼續(xù)運算標志位
  9. bit newcalc=0;        //新運算標志
  10. bit ac=0;                //清零標志,1為清零
  11. bit beepflag=0;         //蜂鳴器標志位
  12. bit sqrtflag1=0;        //開方1標志位
  13. bit sqrtflag2=0;        //開方2標志位
  14. bit        powflag=0;
  15. sbit keybeep=P3^3;//蜂鳴器開關(guān)按鍵
  16. sbit beep=P2^3;         //蜂鳴器控制口
  17. sbit keysqrt=P3^4;//開方按鍵
  18. sbit keypow=P3^5;//任意次方按鍵
  19. uchar keyscan();
  20. void maininit(void);
  21. /****主程序***/
  22. void main(void)
  23. {
  24.         maininit();//初始化
  25.         while(1)        //整個系統(tǒng)大循環(huán),讓計算器一直處于工作狀態(tài)
  26.         {
  27.                 while(1)        //第一運算數(shù)掃描
  28.                 {
  29.                         if(ac==1)
  30.                                 break;         //若清零,則退出輸入
  31.                         if((keyscan()!='N')&&((num>=0&&num<=9)||num=='.')) //記錄按下的數(shù)字
  32.                         {
  33.                                 if(newcalc==1)          //新一次運算開始
  34.                                 {
  35.                                         lcdwrite_com(0x01);//清屏
  36.                                         newcalc=0;
  37.                                         lcd_setxy(0,0);
  38.                                 }
  39.                                 if(keynum1<=7)           //限制輸入位數(shù)
  40.                                 {                        
  41.                                         if(num=='.')
  42.                                         {        
  43.                                                 lcdwrite_data('.');        //顯示小數(shù)點
  44.                                         }
  45.                                         else
  46.                                                 lcdwrite_num1(num);
  47.                                         num1[keynum1]=num;
  48.                                         keynum1++;
  49.                                 }
  50.                         }
  51.                         else if(num=='+'||num=='-'||num=='*'||num=='/'||num=='='||num=='^'||keysqrt==0)  
  52.                         {
  53.                                 if(keynum1==0&&num1[0]==0)          //若直接輸入運算符而沒有輸入數(shù)字則執(zhí)行連續(xù)運算
  54.                                 {        
  55.                         here:        ans1=ans;
  56.                                         sign=num;
  57.                                         lcdwrite_com(0x01);
  58.                                         delayms(5);
  59.                                         lcd_setxy(0,0);
  60.                                         lcdwrite_float(ans1);
  61.                                         if(sqrtflag2!=1&&num!='N')
  62.                                                 lcdwrite_data(num);
  63.                                         break;
  64.                                 }
  65.                                 for(i=0;keynum1>0;i++)           //計算按下的數(shù)字的大小
  66.                                 {
  67.                                         if(num1[i]!='.')
  68.                                                 ans1=ans1*10+num1[i];
  69.                                         else if(num1[i]=='.')
  70.                                                 break;
  71.                                         keynum1--;
  72.                                 }
  73.                                 for(keynum1--,i++,j=0;keynum1>0;j++,i++,keynum1--)
  74.                                         point=point*10+num1[i];
  75.                                 for(;j>0;j--)
  76.                                         point*=0.1;
  77.                                 ans1=ans1+point;
  78.                                 sqrtflag1=0; //清除開方標志
  79.                                 sqrtflag2=0;//清除開方標志
  80.                                 if(keysqrt==0)                  //計算開方
  81.                                 {
  82.                                         delayms(5);
  83.                                                 if(keysqrt==0)
  84.                                                 {
  85.                                                         if(beepflag==1) //若開聲音則每一次按鍵均鳴叫
  86.                                                         {
  87.                                                                 beep=0;
  88.                                                                 delayms(100);
  89.                                                                 beep=1;
  90.                                                         }
  91.                                                         ans=sqrt(ans1);
  92.                                                         sqrtflag1=1;
  93.                                                         lcdwrite_data(0xe8);
  94.                                                         while(keysqrt==0);
  95.                                                         delayms(10);
  96.                                                         while(keysqrt==0);
  97.                                                         break;
  98.                                                 }
  99.                                 }
  100.                                 sign=num;                 //記住運算符號
  101.                                 lcdwrite_data(num);
  102.                                 break;                   //輸入運算符號則退出第一運算數(shù)的輸入
  103.                         }               
  104.                 }
  105.                 while(1)
  106.                 {
  107.                         if(ac==1)
  108.                                 break;          //若清零,則退出輸入
  109.                         if(sqrtflag1==1)  //若第一次按鍵為開方,則直接顯示結(jié)果
  110.                         {
  111.                                 break;
  112.                         }
  113.                         if((keyscan()!='N')&&((num>=0&&num<=9)||num=='.'))         //記錄按下的數(shù)字
  114.                         {
  115.                                 if(keynum2<=7)
  116.                                 {
  117.                                         if(num=='.')
  118.                                         {
  119.                                                 lcdwrite_data('.');        //顯示小數(shù)點
  120.                                         }
  121.                                         else
  122.                                                 lcdwrite_num1(num);
  123.                                         num2[keynum2]=num;
  124.                                         keynum2++;
  125.                                 }
  126.                         }
  127.                         else if(num=='='||keysqrt==0)
  128.                         {
  129.                                 sqrtflag2=0;//清除開方標志
  130.                                 if(keysqrt==0)         //進入開方
  131.                                 {
  132.                                         delayms(5);
  133.                                         if(keysqrt==0)
  134.                                         {
  135.                                                 sqrtflag2=1;   //開方標志
  136.                                                 lcdwrite_data(0xe8);  //寫開方符號
  137.                                                 if(beepflag==1)        //若開聲音則每一次按鍵均鳴叫
  138.                                                 {
  139.                                                         beep=0;
  140.                                                         delayms(100);
  141.                                                         beep=1;
  142.                                                 }
  143.                                                 while(keysqrt==0);
  144.                                                 delayms(10);
  145.                                                 while(keysqrt==0);
  146.                                         }
  147.                                 }
  148.                                 point=0;
  149.                                 for(i=0;keynum2>0;i++)   //計算按下的數(shù)字的大小
  150.                                 {
  151.                                         if(num2[i]!='.')
  152.                                                 ans2=ans2*10+num2[i];
  153.                                         else if(num2[i]=='.')
  154.                                                 break;
  155.                                         keynum2--;
  156.                                 }
  157.                                 for(keynum2--,i++,j=0;keynum2>0;j++,i++,keynum2--)
  158.                                         point=point*10+num2[i];
  159.                                 for(;j>0;j--)
  160.                                         point*=0.1;
  161.                                 if(sqrtflag2!=1)
  162.                                         lcdwrite_data(num);
  163.                                 ans2=ans2+point;
  164.                                 break;                //輸入等于號則退出第二運算數(shù)的輸入
  165.                         }
  166.                         else if(num=='+'||num=='-'||num=='*'||num=='/'||num=='^')
  167.                         {
  168.                                 point=0;
  169.                                 for(i=0;keynum2>0;i++)          //計算按下的數(shù)字的大小
  170.                                 {
  171.                                         if(num2[i]!='.')
  172.                                                 ans2=ans2*10+num2[i];
  173.                                         else if(num2[i]=='.')
  174.                                                 break;
  175.                                         keynum2--;
  176.                                 }
  177.                                 for(keynum2--,i++,j=0;keynum2>0;j++,i++,keynum2--)
  178.                                         point=point*10+num2[i];
  179.                                 for(;j>0;j--)
  180.                                         point*=0.1;
  181.                                 lcdwrite_data(num);
  182.                                 ans2=ans2+point;
  183.                                 conflag=1;
  184.                                 break;                         //進行連續(xù)計算
  185.                         }
  186.                 }
  187.                 if(ac==1)
  188.                 {        
  189.                         ac=0;
  190.                         continue; //清零后進行下一次運算
  191.                 }        
  192.                 if(sign=='+')       //計算結(jié)果
  193.                         ans=ans1+ans2;
  194.                 if(sign=='-')
  195.                         ans=ans1-ans2;
  196.                 if(sign=='*')
  197.                         ans=ans1*ans2;
  198.                 if(sign=='/')
  199.                         ans=ans1/ans2;
  200.                 if(sign=='^')         //計算多次方
  201.                         ans=pow(ans1,ans2);         
  202.                 if(sqrtflag2==1)        //計算開方
  203.                         ans=sqrt(ans1);
  204.                 lcd_setxy(1,0);
  205.                 if((ans2==0&&sign=='/')||(ans1<0&&sqrtflag2==1))
  206.                         lcdwrite_string("math error");//ans2=0或被開方數(shù)小于0時提示錯誤           
  207.                 else lcdwrite_float(ans);                //顯示結(jié)果
  208.                 sqrtflag1=0,newcalc=1;                  //為新的一次運算準備
  209.                 ans1=0;
  210.                 ans2=0;
  211.                 for(i=0;i<8;i++)        //清除按鍵緩存
  212.                         num1[i]=0;
  213.                 for(i=0;i<8;i++)
  214.                         num2[i]=0;
  215.                 if(conflag==1)
  216.                 {
  217.                         conflag=0;
  218.                         goto here;           //跳轉(zhuǎn)到連續(xù)運算
  219.                 }
  220.         }
  221. }
  222. /*****初始化程序*****/
  223. void maininit(void)        
  224. {
  225.         delayms(100); //等待液晶初始化
  226.         lcd_init();
  227.         lcd_setxy(0,0);
  228.         lcdwrite_data('0');
  229.         lcd_setxy(0,0);
  230.         IT0=1;//下降沿觸發(fā)
  231.         EX0=1;//開外部中斷0
  232.         IT1=1;//下降沿觸發(fā)
  233.         EX1=1;//開外部中斷1
  234.         EA=1; //開中斷
  235. }
  236. /***清零中斷程序******/
  237. void EX0_int() interrupt 0
  238. {
  239.         if(beepflag==1)        //若開聲音則每一次按鍵均鳴叫
  240.         {
  241.                 beep=0;
  242.                 delayms(500);
  243.                 beep=1;
  244.         }
  245.         lcdwrite_com(0x01); //顯示清屏
  246.         lcd_setxy(0,0);
  247.         lcdwrite_data('0');
  248.         lcd_setxy(0,0);
  249.         num='N';                          //數(shù)字初始化
  250.         keynum1=0,keynum2=0,sign=0;
  251.     ans1=0,ans2=0,ans=0,point=0;
  252.         conflag=0,newcalc=0;
  253.         ac=1;
  254. }
  255. /***聲音中斷程序******/
  256. void EX1_int() interrupt 2
  257. {
  258.         beepflag=~beepflag;
  259.         if(beepflag==1)  //若開聲音則每一次按鍵均鳴叫
  260.                 {
  261.                 beep=0;
  262.                 delayms(500);
  263.                 beep=1;
  264.         }
  265. }
  266. /*****鍵盤掃描程序*****/
  267. uchar keyscan()
  268. {        
  269.     num='N';        //若沒有按下任何按鍵,則返回'N'
  270.     P1=0xfe;        //掃描第一行
  271.     temp=P1;
  272.     temp=temp&0xf0;
  273.     while(temp!=0xf0) //掃描列
  274.     {
  275.         delayms(10);
  276.         temp=P1;
  277.         temp=temp&0xf0;
  278.         while(temp!=0xf0)
  279.         {
  280.             temp=P1;                        
  281.             switch(temp)
  282.             {
  283.                 case 0xee:num=7;
  284.                     break;                                       
  285.                 case 0xde:num=8;
  286.                     break;                                                
  287.                 case 0xbe:num=9;
  288.                     break;
  289.                 case 0x7e:num='/';
  290.                     break;
  291.             }                                                        
  292.             while(temp!=0xf0)         //等待松手
  293.             {
  294.                 temp=P1;
  295.                 temp=temp&0xf0;
  296.             }
  297.         }
  298.     }
  299.     P1=0xfd;                //掃描第二行         
  300.         temp=P1;
  301.         temp=temp&0xf0;
  302.         while(temp!=0xf0) //掃描列
  303.         {
  304.                 delayms(10);
  305.                 temp=P1;
  306.                 temp=temp&0xf0;
  307.                 while(temp!=0xf0)
  308.                 {
  309.                         temp=P1;                        
  310.                         switch(temp)
  311.                         {
  312.                                 case 0xed:num=4;
  313.                                         break;                                       
  314.                                 case 0xdd:num=5;
  315.                                         break;                                                
  316.                                 case 0xbd:num=6;
  317.                                         break;
  318.                                 case 0x7d:num='*';
  319.                                         break;
  320.                         }
  321.                      while(temp!=0xf0)
  322.                         {
  323.                                 temp=P1;
  324.                                 temp=temp&0xf0;                 //等待松手
  325.                         }
  326.                 }
  327.         }
  328.          P1=0xfb;         //掃描第三行
  329.         temp=P1;
  330.         temp=temp&0xf0;
  331.         while(temp!=0xf0) //掃描列
  332.         {
  333.                 delayms(10);
  334.                 temp=P1;
  335.                 temp=temp&0xf0;
  336.                 while(temp!=0xf0)
  337.                 {
  338.                         temp=P1;                        
  339.                         switch(temp)
  340.                         {
  341.                                 case 0xeb:num=1;
  342.                                         break;                                       
  343.                                 case 0xdb:num=2;
  344.                                         break;                                                
  345.                                 case 0xbb:num=3;
  346.                                         break;
  347.                                 case 0x7b:num='-';
  348.                                         break;
  349.                         }
  350.                      while(temp!=0xf0)        //等待松手
  351.                         {
  352.                                 temp=P1;
  353.                                 temp=temp&0xf0;
  354.                         }
  355.                 }
  356.         }
  357.          P1=0xf7;          //掃描第四行
  358.         temp=P1;
  359.         temp=temp&0xf0;
  360.         while(temp!=0xf0) //掃描列
  361.         {
  362.                 delayms(10);
  363.                 temp=P1;
  364.                 temp=temp&0xf0;
  365.                 while(temp!=0xf0)
  366.                 {
  367.                         temp=P1;                        
  368.                         switch(temp)
  369.                         {
  370.                                 case 0xe7:num=0;
  371.                                         break;                                       
  372.                                 case 0xd7:num='.';
  373.                                         break;                                                
  374.                                 case 0xb7:num='=';
  375.                                         break;
  376.                                 case 0x77:num='+';
  377.                                         break;
  378.                         }
  379.                      while(temp!=0xf0)
  380.                         {
  381.                                 temp=P1;
  382.                                 temp=temp&0xf0;                 //等待松手
  383.                         }
  384.                  }
  385.         }
  386.         if(keypow==0)
  387.         {
  388.                 delayms(5);
  389.                 if(keypow==0)
  390.                 {
  391.                         powflag=1;
  392.                         num='^';
  393.                 }
  394.                 while(keypow==0); //掃描多次方按鍵
  395.                 delayms(5);
  396.                 while(keypow==0);
  397.         }
  398.         if(beepflag==1&&num!='N')  //若開聲音則每一次按鍵均鳴叫
  399.         {
  400.                 beep=0;
  401.                 delayms(100);
  402.                 beep=1;
  403.         }
  404.     return num;
  405. }
復制代碼



作者: 館長    時間: 2017-6-2 22:41
好資料,51黑有你更精彩!!!
作者: 歐陽ouy    時間: 2017-6-14 15:03
館長 發(fā)表于 2017-6-2 22:41
在哪里下載?

下載地址就在上面哦
作者: 妖行    時間: 2017-6-26 10:47
很厲害啊
作者: 安山有狐貍    時間: 2017-11-2 11:23
下載了可以用嗎
作者: yatou520    時間: 2017-11-10 09:21
我想弄這個,試試看
作者: 拉氏變換    時間: 2018-3-19 15:43
看著很不錯,學習一下
作者: yangyangyu    時間: 2018-5-28 10:44
看起來很厲害,參考一下
作者: zmj54545    時間: 2018-6-11 15:21
很棒很不錯
作者: tt609852916    時間: 2018-6-13 10:21
nice,最近在做課程設計,學到了
作者: zeus98k    時間: 2018-6-13 11:35
厲害了
作者: a754487655    時間: 2018-6-21 18:13
里面有沒有工程
作者: aing123    時間: 2018-9-19 08:55
下來玩玩!
作者: 污王灬水鏡    時間: 2019-5-9 16:09
在哪里下載?
作者: makaichuang123    時間: 2019-5-16 17:21
能輸入小數(shù)點嗎   
作者: Minrece    時間: 2019-6-2 21:09
感謝分享
作者: asd456123    時間: 2019-12-3 22:19
感謝分享
作者: 874498724    時間: 2019-12-8 10:35
感謝分享,值得學習,謝謝樓主
作者: 王燕子    時間: 2019-12-19 14:50
那個lc1602_8.h沒有包含怎么辦
作者: 想學習好難    時間: 2019-12-21 18:01
已經(jīng)下載了,謝謝大佬
作者: 小楊同學睡覺了    時間: 2020-1-5 19:40
這個的按鍵具體是哪些?要怎么用
作者: yuh1    時間: 2020-6-7 13:19
感謝大佬
作者: 大棒子    時間: 2020-11-8 19:16
你這個能進行8*8位的運算嗎

作者: 123456弄    時間: 2020-12-27 13:19
感謝感謝分享   值得學習




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1