找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2561|回复: 3
收起左侧

基于51单片机计算器仿真C语言程序设计

[复制链接]
ID:699194 发表于 2021-6-18 17:26 | 显示全部楼层 |阅读模式
这个设计是本人今天搞定出来的特意分享给大家学习学习数码管显示+矩阵键盘的使用,怕新手不会接线,我在里面加了个仿真proteus,可以方便大家一目明了

功能:计算器可以  加减乘除,4为数码管显示数值
本设计绝对可以用,真实可用(希望能帮到大家)
一起加油哈
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei.png

单片机源程序如下:
  1. # include<STC12C5A60S2.h>//单片机型号头文件
  2. # define uchar unsigned char
  3. # define uint32 unsigned long int
  4. # define sint32 signed long int
  5. # define vtime        3000   //定时3ms,一帧8*3=24ms,频率=40Hz
  6. //共阴数码管段码表
  7. uchar code distable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0X00,0x40,0x31};
  8. //位选码表
  9. uchar  code numi[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
  10. //显示缓存
  11. uchar V_ram[]={0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10};
  12. uchar        error=0,wi=0,dot1=0,dot2=0,dot=0xff;  //位选循环变量
  13. uint32        num1=0,num2=0,num=0,sum=0;
  14. void dispsum();
  15. void delay(uchar);
  16. uchar scan_key();
  17. main()                                                 //m1:m0  00=标准;   01=推挽;   10=输入;   11=开漏输出
  18. {
  19.         uchar        ni,nj,fn='+',key_V=0,dotp=0,j,k,i=0;
  20.         uint32        temp=0;
  21.         //m1:m0  00=标准;   01=推挽;   10=输入;   11=开漏输出
  22.         P1M1 = 0X0f;
  23.         P1M0 = 0XF0;        //设定低4位为输入,高4位为输出
  24.         P0M1 = 0X00;
  25.         P0M0 = 0Xff;
  26.         P2M1 = 0X00;
  27.         P2M0 = 0Xff; //设定P0,P2推挽输出
  28.           TMOD = 0X01; //设定定时器0为16位计数方式
  29.           TH0 = (65536-vtime )/256;
  30.           TL0 = (65536-vtime )%256; //赋定时器0初值
  31.           ET0 = 1;  //开定时器0中断
  32.           EA = 1;          //开总中断
  33.            TR0 = 1;  //启动定时器0计数
  34.         //sum=123456;

  35.         while(1)
  36.           {
  37.                 key_V=scan_key();
  38.                 //dispsum();
  39.                 if(key_V)
  40.                 {
  41.                         //有键按下
  42.                         key_V--;
  43.                         switch(key_V)
  44.                         {
  45.                            case 0:
  46.                            case 1:
  47.                            case 2:
  48.                            case 3:
  49.                            case 4:
  50.                            case 5:
  51.                            case 6:
  52.                            case 7:
  53.                            case 8:
  54.                            case 9:
  55.                                            if((num+i)==0)       
  56.                                         {        //如果是第一个数字输入,则清黑屏
  57.                                                 dot=0xff; //关闭小数点
  58.                                                 for(j=0;j<8;j++)
  59.                                                          V_ram[j]=0x10;         //清黑屏
  60.                                         }
  61.                                    num=num*10+key_V;  //键盘输入的数字转化为十进制的数值
  62.                                         if(i==8)  //如果显示缓冲满了
  63.                                         {
  64.                                                 i=7;
  65.                                                 for(j=0;j<7;j++)
  66.                                                          V_ram[j]=V_ram[j+1];//显示缓存串行移位
  67.                                         }
  68.                                         V_ram[i]=key_V;          //键值放入显示缓存
  69.                                         i++;
  70.                                         break;

  71.                                 case 10:  //dot          小数点符号
  72.                                         dotp=i;                  //记录下小数点位置
  73.                                         dot=dotp-1;  //显示小数点
  74.                                         break;

  75.                                 case 11:   //+         加法符号
  76.                                         for(j=0;j<8;j++)
  77.                                                  V_ram[j]=0x10;         //清黑屏
  78.                                         num1=num;                         //获取从键盘输入的第一个数值
  79.                                         if(dotp==0)
  80.                                         {
  81.                                                 dot1=0;
  82.                                         }
  83.                                         else
  84.                                         {
  85.                                                 dot1=i-dotp;
  86.                                         }
  87.                                         ni=i;
  88.                                         dotp=0;
  89.                                         dot=0xff;
  90.                                         num=0;
  91.                                         fn='+';
  92.                                         i=0;
  93.                                         break;

  94.                                 case 12:   //-           减法符号
  95.                                         for(j=0;j<8;j++)
  96.                                                  V_ram[j]=0x10;          //清黑屏
  97.                                         num1=num;                          //获取从键盘输入的第一个数值
  98.                                         if(dotp==0)
  99.                                         {
  100.                                                 dot1=0;
  101.                                         }
  102.                                         else
  103.                                         {
  104.                                                 dot1=i-dotp;
  105.                                         }
  106.                                         ni=i;
  107.                                         dotp=0;
  108.                                         dot=0xff;
  109.                                         num=0;
  110.                                         fn='-';
  111.                                         i=0;
  112.                                         break;

  113.                                 case 13:   //*                  乘法符号
  114.                                         for(j=0;j<8;j++)
  115.                                                  V_ram[j]=0x10;           //清黑屏
  116.                                         num1=num;                           //获取从键盘输入的第一个数值
  117.                                         if(dotp==0)
  118.                                         {
  119.                                                 dot1=0;
  120.                                         }
  121.                                         else
  122.                                         {
  123.                                                 dot1=i-dotp;
  124.                                         }
  125.                                         ni=i;
  126.                                         dotp=0;
  127.                                         dot=0xff;
  128.                                         num=0;
  129.                                         fn='*';
  130.                                         i=0;
  131.                                         break;

  132.                                 case 14:   // /                         除法符号
  133.                                         for(j=0;j<8;j++)
  134.                                                  V_ram[j]=0x10;                //清黑屏
  135.                                         num1=num;                           //获取从键盘输入的第一个数值
  136.                                         if(dotp==0)
  137.                                         {
  138.                                                 dot1=0;
  139.                                         }
  140.                                         else
  141.                                         {
  142.                                                 dot1=i-dotp;
  143.                                         }
  144.                                         ni=i;
  145.                                         dotp=0;
  146.                                         dot=0xff;
  147.                                         num=0;
  148.                                         fn='/';
  149.                                         i=0;
  150.                                         break;

  151.                                 case 15:   //=                  等于符号
  152.                                         if(dotp==0)                   //计算第二个运算数的小数位数
  153.                                         {
  154.                                                 dot2=0;
  155.                                         }
  156.                                         else
  157.                                         {
  158.                                                 dot2=i-dotp;
  159.                                         }
  160.                                         dotp=0;
  161.                                         nj=i;
  162.                                         temp=1;
  163.                                         if(fn!='*')
  164.                                         {        if(dot1>dot2)                //第一个运算数与第二个运算进行对齐
  165.                                                 {
  166.                                                         for(j=dot1-dot2;j>0;j--)
  167.                                                         {
  168.                                                                         //if(num>0x19999999)error=1;
  169.                                                                         num=num*10;
  170.                                                                         nj++;
  171.                                                                         if(nj>9)
  172.                                                                         {
  173.                                                                                 j--;
  174.                                                                                 for(k=j;k>0;k--)
  175.                                                                                         num1=num1/10;
  176.                                                                                         dot1=dot1-j;
  177.                                                                                 break;
  178.                                                                         }

  179.                                                         }
  180.                                                 }
  181.                                                 else
  182.                                                 {
  183.                                                         for(j=dot2-dot1;j>0;j--)
  184.                                                         {
  185.                                                                         //if(num1>0x19999999)error=1;
  186.                                                                         num1=num1*10;
  187.                                                                         ni++;
  188.                                                                         if(ni>9)
  189.                                                                         {
  190.                                                                                 j--;
  191.                                                                                 for(k=j;k>0;k--)
  192.                                                                                         num=num/10;
  193.                                                                                         dot2=dot2-j;
  194.                                                                                 break;
  195.                                                                         }
  196.                                                         }
  197.                                                 }
  198.                                         }
  199.                                         //准备好后,进行运算
  200.                                         if(fn=='+')         //做加法运算
  201.                                         {
  202.                                                 sum=num+num1;
  203.                                                 if(sum<(num|num1))error=1;
  204.                                                 dispsum();           //显示对齐后的运算结果
  205.                                                 if(dot2>dot1)        //显示实际小数点的位置
  206.                                                         dot=dot-dot2;
  207.                                                 else
  208.                                                         dot=dot-dot1;
  209.                                                 i=0;         //计算结束,初始化关键变量
  210.                                                 num1=0;
  211.                                                 num=0;
  212.                                                 break;
  213.                                         }

  214.                                         if(fn=='-')          //做减法运算
  215.                                         {

  216.                                                 if(num1<num)         //判断结果是负还是正
  217.                                                 {
  218.                                                         sum=num-num1;
  219.                                                 }
  220.                                                 else
  221.                                                         sum=num1-num;
  222.                                                 dispsum();          //显示对齐后的运算结果
  223.                                                 if(num>num1)  //是负数则第一位显示“-”,其它位顺序往后显示
  224.                                                 {
  225.                                                         for(j=7;j>0;j--)
  226.                                                                  V_ram[j]=V_ram[j-1]; //顺序往后显示
  227.                                                         V_ram[0]=0x11;        //第一位显示“-”
  228.                                                         dot++;          //小数点也顺延一位
  229.                                                 }
  230.                                                 if(dot2>dot1)         //显示实际小数点的位置
  231.                                                         dot=dot-dot2;
  232.                                                 else
  233.                                                         dot=dot-dot1;

  234.                                                 i=0;        //计算结束,初始化关键变量
  235.                                                 num1=0;
  236.                                                 num=0;
  237.                                                 break;
  238.                                         }
  239.                                         if(fn=='*')           //做乘法运算
  240.                                         {
  241.                                                 sum=num1*num;
  242.                                                 if((ni+nj)>10)error=1;
  243.                                                 dispsum();        //显示对齐后的运算结果
  244.                                                 //if(dot2>dot1)  //显示实际小数点的位置
  245.                                                         dot=dot-dot2-dot1;
  246.                                                 //else
  247.                                                 //        dot=dot-dot1-dot1;
  248.                                                 i=0;         //计算结束,初始化关键变量
  249.                                                 num1=0;
  250.                                                 num=0;
  251.                                                 break;
  252.                                         }
  253.                                         if(fn=='/')                //做除法运算
  254.                                         {
  255.                                                 sum=num1/num;
  256.                                                 dispsum();         //显示对齐后的运算结果,对于除法,就是实际结果
  257.                                                 temp=num1%num; //显示小数部分
  258.                                                   for(j=dot;j<7;j++)
  259.                                                   {
  260.                                                         temp=temp*10;
  261.                                                         V_ram[j+1]=temp/num;
  262.                                                         temp=temp%num;
  263.                                                         if(temp==0)break;
  264.                                                 }
  265.                                                 i=0;        //计算结束,初始化关键变量
  266.                                                 num1=0;
  267.                                                 num=0;
  268.                                                 break;
  269.                                         }
  270.                                         break;
  271.                                                
  272.                                    default:
  273.                                         break;   
  274.                         }
  275.                    delay(200);//延时去抖
  276.                 }
  277.                
  278.            }

  279. }

  280. void t0_isp() interrupt 1
  281. {
  282.         uchar dm,wx;
  283.           TH0 = (65536-vtime )/256;
  284.           TL0 = (65536-vtime )%256; //赋定时器0初值
  285.           dm=distable[V_ram[wi]];        //取显示段码
  286.         wx=numi[wi];                           //取位选码
  287.         P2=0x00;                           //关显示
  288.         //P0=dm;                                   //段码赋给P0口
  289.         if(dot==wi)
  290.         {
  291.                 P0=dm|0x80;                  //点亮位选的那个数码管+小数点
  292.         }
  293.         else
  294.         {
  295.                 P0=dm;                                   //点亮位选的那个数码管
  296.         }
  297.         P2=wx;
  298.         wi++;
  299.         if(wi==8)wi=0;
  300. }
  301. /////////////////////////////////////
  302. uchar         scan_key()
  303. {
  304.                 uchar        i,j,vlume=0,temp[4]={0xef,0xdf,0xbf,0x7f};
  305.                 for(j=0;j<4;j++)
  306.                 {
  307.                         P1=temp[j];
  308.                         i=P1|0xf0;
  309.                         if(i != 0xff) //判断按键
  310.                         {        //有键按下
  311.                                 i=~i;
  312.                                 if(i==4)i=3;
  313.                                 if(i==8)i=4;
  314.                                 i--;  // 计算按键所在行号(0--3)
  315.                                 vlume=i*4+j+1;        //计算键值
  316.                                 //delay(200);//延时去抖
  317.                         }
  318.                 }
  319.                 return        vlume;
  320. }
  321. ////////////////////////////////////////  
  322. void delay(uchar k )
  323. {
  324.         uchar x,y,z;
  325.         for(x=k;x>0;x--)
  326.         for(y=20;y>0;y--)
  327.         for(z=250;z>0;z--);
  328. }
  329. ////////////////////////////////////////
  330. void        dispsum()
  331. ……………………

  332. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
51单片机计算器 数码管显示.zip (149.9 KB, 下载次数: 38)

评分

参与人数 1黑币 +70 收起 理由
admin + 70 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:942472 发表于 2021-6-22 15:28 | 显示全部楼层
用不了大哥
回复

使用道具 举报

ID:328014 发表于 2021-6-22 17:54 | 显示全部楼层

程序编译没有错误 你是不是没有头文件:http://www.51hei.com/bbs/dpj-36960-1.html

不过楼主的程序 估计是按键没有消抖,按键得快速按下 不然结果不正确
回复

使用道具 举报

ID:699194 发表于 2021-6-28 19:06 | 显示全部楼层
51hei团团 发表于 2021-6-22 17:54
程序编译没有错误 你是不是没有头文件:http://www.51hei.com/bbs/dpj-36960-1.html

不过楼主的程序 估 ...

可以加个延时,去消抖就好了
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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