找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1501|回复: 0
打印 上一主题 下一主题
收起左侧

简易计算器的设计及实现加(减)功能

[复制链接]
跳转到指定楼层
楼主
ID:354501 发表于 2018-6-19 17:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用Proteus实现计算器功能的实现:实现加(减)功能。

单片机源程序如下:
  1. #include <reg52.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. sbit rs=P0^0;
  5. sbit rw=P0^1;
  6. sbit e=P0^2;
  7. sbit k0=P1^0;
  8. sbit k1=P1^1;
  9. sbit k2=P1^2;
  10. sbit k3=P1^3;
  11. sbit k4=P1^4;
  12. sbit k5=P1^5;
  13. sbit k6=P1^6;
  14. sbit k7=P1^7;
  15. unsigned char code digit[ ]={"0123456789"};    //定义字符数组显示数字
  16. unsigned char s,m,h,day,month,year,count;
  17. void write_dat(uchar dat);
  18. void write_com(uchar com);
  19. void keyscan();
  20. /**********************
  21. 功能说明:
  22. 显示编码,加上0x30,
  23. 分别为'1','2','3','+',
  24. '4','5','6','-',等
  25. **********************/
  26. uchar code table1[]=
  27. {
  28. 1,2,3,0x2b-0x30,
  29. 4,5,6,0x2d-0x30,
  30. 7,8,9,0x2a-0x30,
  31. 0,0x3d-0x30,0x01-0x30,0x2f-0x30
  32. };

  33. uchar k=0,flag=0,num,fuhao,i;

  34. long a,b,c;


  35. void delay(uint z)
  36. {
  37.     uint x,y;
  38.     for(x=z;x>0;x--)
  39.         for(y=110;y>0;y--);
  40. }
  41. /*****************************************************
  42. 函数功能:指定字符显示的实际地址
  43. 入口参数:x
  44. ***************************************************/
  45. void WriteAddress(unsigned char x)
  46. {
  47.      write_com(x|0x80); //显示位置的确定方法规定为"80H+地址码x"
  48. }
  49. /******************************************************************************
  50. 函数功能:显示小时                          
  51. ******************************************************************************/
  52. void DisplayHour()
  53. {
  54.    unsigned char i,j;
  55.         i=h/10;                //取整运算,求得十位数字
  56.         j=h%10;                //取余运算,求得各位数字
  57.    WriteAddress(0x45);     //写显示地址,将十位数字显示在第2行第0列
  58.          write_dat(digit[i]);   //将十位数字的字符常量写入LCD
  59.      write_dat(digit[j]);   //将个位数字的字符常量写入LCD
  60.      
  61. }
  62. /******************************************************************************
  63. 函数功能:显示分钟                          
  64. ******************************************************************************/
  65. void DisplayMinute()
  66. {
  67.   unsigned char i,j;
  68.    i=m/10;                 //取整运算,求得十位数字
  69.         j=m%10;                //取余运算,求得各位数字
  70.    WriteAddress(0x48);     //写显示地址,将十位数字显示在第2行第3列
  71.          write_dat(digit[i]);   //将十位数字的字符常量写入LCD
  72.          write_dat(digit[j]);   //将个位数字的字符常量写入LCD
  73.      
  74. }
  75. /******************************************************************************
  76. 函数功能:显示秒                        
  77.   ******************************************************************************/
  78. void DisplaySecond()
  79. {
  80.    unsigned char i,j;
  81.           i=s/10;                //取整运算,求得十位数字
  82.         j=s%10;                //取余运算,求得各位数字
  83.    WriteAddress(0x4b);     //写显示地址,将十位数字显示在第2行第6列
  84.          write_dat(digit[i]);   //将十位数字的字符常量写入LCD
  85.     write_dat(digit[j]);   //将个位数字的字符常量写入LCD
  86. }


  87. /******************************************************************************
  88. 函数功能:显示小时                          
  89. ******************************************************************************/
  90. void DisplayYear()
  91. {
  92.    unsigned char i,j;
  93.         i=year/10;                //取整运算,求得十位数字
  94.         j=year%10;                //取余运算,求得各位数字
  95.    WriteAddress(0x07);     //写显示地址,将十位数字显示在第2行第0列
  96.          write_dat(digit[i]);   //将十位数字的字符常量写入LCD
  97.      write_dat(digit[j]);   //将个位数字的字符常量写入LCD
  98.      
  99. }
  100. /******************************************************************************
  101. 函数功能:显示分钟                          
  102. ******************************************************************************/
  103. void DisplayMonth()
  104. {
  105.   unsigned char i,j;
  106.    i=month/10;                 //取整运算,求得十位数字
  107.         j=month%10;                //取余运算,求得各位数字
  108.    WriteAddress(0x0a);     //写显示地址,将十位数字显示在第2行第3列
  109.          write_dat(digit[i]);   //将十位数字的字符常量写入LCD
  110.          write_dat(digit[j]);   //将个位数字的字符常量写入LCD
  111.      
  112. }
  113. /******************************************************************************
  114. 函数功能:显示秒                        
  115.   ******************************************************************************/
  116. void DisplayDay()
  117. {
  118.    unsigned char i,j;
  119.           i=day/10;                //取整运算,求得十位数字
  120.         j=day%10;                //取余运算,求得各位数字
  121.    WriteAddress(0x0d);     //写显示地址,将十位数字显示在第2行第6列
  122.          write_dat(digit[i]);   //将十位数字的字符常量写入LCD
  123.     write_dat(digit[j]);   //将个位数字的字符常量写入LCD
  124. }
  125. void keyscan2()
  126.         {if(k0==0)
  127.            {delay(5);
  128.             if(k0==0)
  129.               {
  130.                   s++;
  131.                if(s==60)
  132.                s=0;
  133.                }
  134.             }
  135.           if(k1==0)
  136.             {delay(5);
  137.              if(k1==0)
  138.                {m++;
  139.                 if(m==60)
  140.                   m=0;
  141.                 }
  142.              }
  143.                   if(k2==0)
  144.             {delay(5);
  145.              if(k2==0)
  146.                {h++;
  147.                 if(h==60)
  148.                  h=0;
  149.                 }
  150.              }
  151.      
  152.                   if(k3==0)
  153.             {delay(5);
  154.              if(k3==0)
  155.                {day++;
  156.                 if(day==30)
  157.                  day=0;
  158.                 }
  159.              }
  160.                   if(k4==0)
  161.             {delay(5);
  162.              if(k4==0)
  163.                {month++;
  164.                 if(month==13)
  165.                   month=0;
  166.                 }
  167.              }
  168.         if(k5==0)
  169.             {delay(5);
  170.              if(k5==0)
  171.                {year++;
  172.                 if(year==99)
  173.                    year=0;
  174.                 }
  175.              }

  176.           }
  177.          
  178. void keyscan()
  179. {
  180.     uchar temp;
  181.     P3=0xfe;
  182.     temp=P3;
  183.     temp=temp&0xf0;
  184.     while(temp!=0xf0)
  185.     {
  186.        delay(5);
  187.        temp=P3;
  188.        temp=temp&0xf0;
  189.        while(temp!=0xf0)
  190.        {
  191.            temp=P3;
  192.            switch(temp)
  193.            {
  194.               case 0xee:num=0;
  195.                 break;   
  196.               case 0xde:num=1;
  197.              break;
  198.               case 0xbe:num=2;
  199.              break;
  200.               case 0x7e:num=3;
  201.              break;
  202.             }   
  203.              while(temp!=0xf0)
  204.                 { temp=P3;
  205.                   temp=temp&0xf0;
  206.            }
  207.            }

  208. /*当按下1,2,3,松手后执行下面这段语句*/
  209.            if(num==0||num==1||num==2)
  210.            {
  211.                
  212.                 if(flag==0)
  213.                    a=a*10+table1[num];//如果没有按符号键,符号前的数值为a
  214.                 else if(flag==1)
  215.                    b=b*10+table1[num];  //如果按了符号键,符号后的数值为b
  216.       
  217.                 if(k==1)    //如果之前按了'='号,再按键时清屏,进行下一次计算
  218.              {
  219.                  k=0;
  220.                     write_com(0x01);
  221.              }
  222.          }
  223.             else if(num==3)   //判断按下'+'
  224.       {
  225.                  flag=1;
  226.                  fuhao=1;
  227.          }
  228.                               
  229.           i=table1[num];    //显示按下的键
  230.           write_dat(0x30+i);
  231.       
  232.        }
  233.     P3=0xfd;
  234.     temp=P3;
  235.     temp=temp&0xf0;
  236.     while(temp!=0xf0)
  237.     {
  238.        delay(5);
  239.        temp=P3;
  240.        temp=temp&0xf0;
  241.        while(temp!=0xf0)
  242.        {
  243.            temp=P3;
  244.            switch(temp)
  245.            {
  246.               case 0xed:num=4;
  247.                 break;   
  248.               case 0xdd:num=5;
  249.              break;
  250.               case 0xbd:num=6;
  251.              break;
  252.               case 0x7d:num=7;
  253.              break;
  254.             }   
  255.              while(temp!=0xf0)
  256.                 { temp=P3;
  257.                  temp=temp&0xf0;
  258.            }
  259.            }
  260.          if(num==4||num==5||num==6) //判断是否按下'4','5','6'
  261.       {
  262.              if(k==1)
  263.              {
  264.                  k=0;
  265.                     write_com(0x01);
  266.              }
  267.              if(flag==0)
  268.                 a=a*10+table1[num];
  269.              else if(flag==1)
  270.                 b=b*10+table1[num];      
  271.       }
  272.          else if(num==7)
  273.       {
  274.              flag=1;
  275.              fuhao=2;   
  276.       }
  277.          i=table1[num];     //显示按下的键
  278.          write_dat(0x30+i);   

  279.        }
  280.     P3=0xfb;
  281.     temp=P3;
  282.     temp=temp&0xf0;
  283.     while(temp!=0xf0)
  284.     {
  285.        delay(5);
  286.        temp=P3;
  287.        temp=temp&0xf0;
  288.        while(temp!=0xf0)
  289.        {
  290.            temp=P3;
  291.            switch(temp)   //
  292.            {
  293.               case 0xeb:num=8;
  294.                 break;   
  295.               case 0xdb:num=9;  
  296.              break;
  297.               case 0xbb:num=10;
  298.              break;
  299.               case 0x7b:num=11;
  300.                 break;            
  301.             }   
  302.              while(temp!=0xf0)
  303.                 { temp=P3;
  304.                  temp=temp&0xf0;
  305.            }
  306.            }
  307.            if(num==8||num==9||num==10)  //判断是否按下'7','8','9'
  308.            {
  309.                if(k==1)
  310.              {
  311.                  k=0;
  312.                     write_com(0x01);
  313.              }
  314.                if(flag==0)
  315.                   a=a*10+table1[num];
  316.                else if(flag==1)
  317.                   b=b*10+table1[num];
  318.            
  319.            }
  320.            else if(num==11)      //判断是否按下'*'
  321.            {
  322.                 flag=1;
  323.              fuhao=3;
  324.            
  325.            }
  326.            i=table1[num];
  327.            write_dat(0x30+i);
  328.       
  329.        }
  330.        P3=0xf7;
  331.     temp=P3;
  332.     temp=temp&0xf0;
  333.     while(temp!=0xf0)
  334.     {
  335.        delay(5);
  336.        temp=P3;
  337.        temp=temp&0xf0;
  338.        while(temp!=0xf0)
  339.        {
  340.            temp=P3;
  341.            switch(temp)
  342.            {
  343.               case 0xe7:num=12;    // 0键
  344.                 break;   
  345.               case 0xd7:num=13;     // '='
  346.              break;
  347.               case 0xb7:num=14;  //清零键
  348.              break;
  349.               case 0x77:num=15;  //'/'
  350.                 break;            
  351.             }   
  352.              while(temp!=0xf0)
  353.                 { temp=P3;
  354.                  temp=temp&0xf0;
  355.                }   
  356.            }
  357.           switch(num)
  358.           {
  359.              case 12:
  360.              {
  361.                   if(k==1)
  362.              {
  363.                  k=0;
  364.                     write_com(0x01);
  365.              }
  366.                  if(flag==0)
  367.                    a=a*10;
  368.                  else if(flag==1)
  369.                    b=b*10;

  370.                    write_dat(0x30);
  371.              }
  372.                    break;
  373.              case 13:          //按=键
  374.            {
  375.                   k=1;
  376.                  if(fuhao==1)    //如果符号键是+,执行+运算
  377.            {
  378.                   
  379.                      write_com(0x80+0x4f);
  380.                      write_com(0x04);
  381.                c=a+b;
  382.                      while(c!=0)     
  383.             {
  384.                         write_dat(0x30+c%10);
  385.                   c=c/10;
  386.             
  387.            
  388.            }
  389.                     write_dat(0x3d);
  390.                  fuhao=0;
  391.                     a=0;b=0;flag=0;
  392.            }
  393.                  if(fuhao==2)
  394.            {
  395.                     write_com(0x80+0x4f);
  396.                     write_com(0x04);
  397.                   if(a>=b)
  398.            {
  399.                    c=a-b;
  400.                       while(c!=0)
  401.              {
  402.                          write_dat(0x30+c%10);
  403.                    c=c/10;
  404.                       }              
  405.             
  406.            }
  407.                     else if(a<b)
  408.            {
  409.                     c=b-a;
  410.                        while(c!=0)
  411.                  {
  412.                            write_dat(0x30+c%10);
  413.                      c=c/10;
  414.                  }
  415.                       write_dat(0x2d);
  416.            }
  417.            
  418.                     write_dat(0x3d);
  419.                    a=0;b=0;flag=0;fuhao=0;
  420.            
  421.            }
  422.                  if(fuhao==3)   //如果符号键是*
  423.            {
  424.                     write_com(0x80+0x4f);
  425.                     write_com(0x04);
  426.                     c=a*b;
  427.                  while(c!=0)
  428.            {
  429.                        write_dat(0x30+c%10);
  430.                     c=c/10;
  431.            }
  432.                     write_dat(0x3d);         
  433.                    a=0;b=0;flag=0;fuhao=0;
  434.            
  435.            }
  436.                  if(fuhao==4)      //如果符号键是/
  437.            {  
  438.                      i=0;
  439.                      write_com(0x80+0x4f);
  440.                      write_com(0x04);
  441.                     c=(long)(((float)a/b)*1000000);  //结果保留6位小数
  442.                  while(c!=0)
  443.            {
  444.                        write_dat(0x30+c%10);
  445.                     c=c/10;
  446.                  i++;

  447.                     if(i==6)        //   显示完六位小数后,显示·
  448.                          write_dat(0x2e);     
  449.            }
  450.                  if(a/b<=0)
  451.                      write_dat(0x30);
  452.                      write_dat(0x3d);
  453.                      a=0;b=0;flag=0;fuhao=0;
  454.            }
  455.            }
  456.               break;
  457.             case 14:
  458.                 { write_com(0x01);
  459.                  a=0;b=0;flag=0;fuhao=0;
  460.              }
  461.                  break;

  462.              case 15:
  463.                   {
  464.                     flag=1;
  465.                  fuhao=4;
  466.                    write_dat(0x30+table1[num]);
  467.       
  468.                    }
  469.                    break;
  470.       
  471.           }

  472.                
  473.        }
  474.          
  475. }
  476. /*******led1602*******/
  477. void write_com(uchar com)
  478. {
  479.    rs=0;//选择写指令
  480.    rw=0;
  481.    P2=com;
  482.    e=1;
  483.    delay(5);//无延时不能正常工作
  484.    e=0;
  485. }
  486. void write_dat(uchar dat)
  487. {
  488.    rs=1;//选择写数据
  489.    rw=0;
  490.    P2=dat;
  491.    e=1;
  492.    delay(5);//无延时不能正常工作
  493.    e=0;
  494. }
  495. void init()  //初始化
  496. {
  497.    delay(15);
  498.    write_com(0x38);
  499.    delay(6);
  500.    write_com(0x38);
  501.    delay(6);
  502.    write_com(0x38);
  503.    write_com(0x38);
  504.    write_com(0x0c); //开显示,关光标
  505.    write_com(0x06);//光标移动 设置
  506.    write_com(0x01);//清屏
  507.    
  508. }   
  509. void geshi()
  510.      {
  511.           WriteAddress(0x00);      
  512.         write_dat('D');
  513.      WriteAddress(0x01);      
  514.     write_dat('a');   
  515.     WriteAddress(0x02);      
  516.     write_dat('t');            //将分号的字符常量写入LCD
  517.          WriteAddress(0x03);      
  518.         write_dat('e');
  519.     WriteAddress(0x04);      
  520.         write_dat(':');
  521. WriteAddress(0x05);      
  522.         write_dat('2');
  523.         WriteAddress(0x06);      
  524.         write_dat('0');
  525.      WriteAddress(0x09);      
  526.         write_dat('-');
  527.      WriteAddress(0x0c);      
  528.         write_dat('-');   
  529.      WriteAddress(0x40);      
  530.         write_dat('T');
  531.      WriteAddress(0x41);      
  532.         write_dat('i');  
  533.     WriteAddress(0x42);      
  534.         write_dat('m');   
  535.         WriteAddress(0x43);        //写地址,将第二个分号显示在第2行第7列
  536.         write_dat('e');            //将分号的字符常量写入LCD
  537.         WriteAddress(0x44);        //写地址,将第二个分号显示在第2行第10列
  538.         write_dat(':');            //将分号的字符常量写入LCD
  539.          WriteAddress(0x47);      
  540.         write_dat(':');
  541.      WriteAddress(0x4a);      
  542.         write_dat(':');   
  543.          }


  544.                     
  545. void main()
  546. {   
  547.      

  548.     init();
  549.         TMOD=0x01;                 //使用定时器T0的模式1
  550.         TH0=(65536-46083)/256;    //定时器T0的高8位设置初值
  551.         TL0=(65536-46083)%256;    //定时器T0的低8位设置初值
  552.         EA=1;                     //开总中断
  553.         ET0=1;                    //定时器T0中断允许
  554.         TR0=1;                    //启动定时器T0
  555.         count=0;                  //中断次数初始化为0
  556.         s=0;                      //秒初始化为0
  557.         m=0;                      //分钟初始化为0
  558.         h=0;                      //小时初始化为0
  559.         year=0;
  560.         month=0;
  561.         day=0;

  562.    while(1)
  563.     {  
  564.          keyscan();
  565.           if(k6==0)
  566.            { k6=0;
  567.         write_com(0x01);
  568.         while(1)
  569.                 {
  570.                 keyscan2();
  571.        geshi();
  572.            delay(5);  
  573.        DisplayHour();
  574.            delay(5);  
  575.        DisplayMinute();
  576.            delay(5);  
  577.        DisplaySecond();
  578.             delay(5);  
  579.         DisplayYear();
  580.                 delay(5);  
  581.        DisplayMonth();
  582.            delay(5);  
  583.        DisplayDay();
  584.                 delay(5);
  585.              if(k7==0)
  586.                 {
  587.                  k6=1;
  588.                  write_com(0x01);
  589.                  break;
  590.                 }
  591.           
  592.            }
  593.           
  594.           }   
  595.           
  596.     }
  597.    
  598. }

  599. /*******************************************************
  600. 函数功能:定时器T0的中断服务函数
  601. ********************************************************/
  602. void Time0(void ) interrupt 1 using 1 //定时器T0的中断编号为1,使用第1组工作寄存器
  603.   {
  604.          count++;                          //每产生1次中断,中断累计次数加1
  605.                  if(count==20)                 //如果中断次数计满20次
  606.                     {
  607.               count=0;                 //中断累计次数清0
  608.                         s++;                   //秒加1                               
  609.                   if(s==60)                    //如果计满60秒
  610.                          {
  611.                           s=0;                     //秒清0
  612.                           m++;                     //分钟加1
  613.                      }
  614.                   if(m==60)                      //如果计满60分
  615.                    {
  616.                            m=0;                    //分钟清0
  617.                            h++;                    //小时加1
  618.                     }
  619.             
  620.                  if(h==24)
  621.                  {
  622.                   h=0;
  623.                  day++;
  624.                  }
  625.                  if(day==30)
  626.                  {
  627.                    day=0;
  628.                    month++;
  629.                  }
  630.                  if(month==13)
  631.                  { month=0;
  632.                   year++;
  633.                  }
  634.                  if(year==99)
  635.                  {
  636.                  year=0;
  637.                  }
  638.            TH0=(65536-46083)/256;          //定时器T0高8位重新赋初值
  639.            TL0=(65536-46083)%256;         //定时器T0低8位重新赋初值               
  640.    }
  641.   }
复制代码

所有资料51hei提供下载:
计算器.rar (3.28 KB, 下载次数: 13)



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表