找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机计算器源程序(矩阵键盘+数码管显示)原理图与Proteus仿真 代码注释很详细

[复制链接]
跳转到指定楼层
楼主
矩阵键盘+数码管显示组成的一个简易计算器单片机项目
下面是单片机计算器的proteus仿真原理图(工程文件可到本帖附件中下载):


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

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

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

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

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

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

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

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

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

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

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

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

  280. }

  281. void t0_isp() interrupt 1
  282. {
  283.         uchar dm,wx;
  284.           TH0 = (65536-vtime )/256;
  285.           TL0 = (65536-vtime )%256; //赋定时器0初值
  286.           dm=distable[V_ram[wi]];        //取显示段码
  287.          wx=numi[wi];                           //取位选码
  288.         P2=0x00;                           //关显示
  289.         //P0=dm;                                   //段码赋给P0口
  290.         if(dot==wi)
  291.         {
  292.                 P0=dm|0x80;                  //点亮位选的那个数码管+小数点
  293.         }
  294.         else
  295.         {
  296.                 P0=dm;                                   //点亮位选的那个数码管
  297.         }
  298.         P2=wx;
  299.         wi++;
  300.         if(wi==8)wi=0;
  301. }
  302. /////////////////////////////////////
  303. uchar         scan_key()
  304. {
  305.                 uchar        i,j,vlume=0,temp[4]={0xef,0xdf,0xbf,0x7f};
  306.                 for(j=0;j<4;j++)
  307.                 {
  308.                         P1=temp[j];
  309.                         i=P1|0xf0;
  310.                         if(i != 0xff) //判断按键
  311.                         {        //有键按下
  312.                                 i=~i;
  313.                                 if(i==4)i=3;
  314.                                 if(i==8)i=4;
  315.                                 i--;  // 计算按键所在行号(0--3)
  316.                                 vlume=i*4+j+1;        //计算键值
  317.                                 //delay(200);//延时去抖
  318.                         }
  319.                 }
  320.                 return        vlume;
  321. }
  322. ////////////////////////////////////////  
  323. void delay(uchar k )
  324. {
  325.         uchar x,y,z;
  326.         for(x=k;x>0;x--)
  327.         for(y=20;y>0;y--)
  328.         for(z=250;z>0;z--);
  329. }
  330. ////////////////////////////////////////
  331. void        dispsum()
  332. {
  333.         uchar        temp[10]=0,k,j;
  334.         uint32        temp1;
  335.         if(error==1)
  336.         {
  337.                 V_ram[0]=0x0e;
  338.                 V_ram[1]=0x12;
  339.                 for(j=2;j<8;j++)
  340.                         V_ram[j]=0x10;                //清黑屏
  341.                 dot=0xff;
  342.                 error=0;
  343.                 num=0;
  344.                 return;
  345.         }
  346.         temp1=sum;
  347.         for(k=0;k<10;k++)
  348.         {
  349.                
  350.                 temp[k]=temp1%10;  // sum的个位开始放入temp数组,最多可放10位
  351.                 temp1=temp1/10;           //
  352.                 if(temp1==0)
  353.                 {        // 如果商为零
  354.                         dot=k;                 //当前位小数点点亮
  355.                         for(j=0;j<8;j++)
  356.                         {
  357.                                 if(k==0xff)
  358.                                 {
  359.                                         V_ram[j]=0x10;        // 清黑屏
  360.                                 }
  361.                                 else
  362.                                 {
  363.                                         V_ram[j]=temp[k];        // 把sum中的数从高位依次放入显示缓存
  364.                                         k--;


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

最后给大家分享一些我们老师给的一些经典的单片机程序源码, 一共有十多个.都有详细的注释,然大家快速的理解每一行代码的意思。而且有proteus仿真原理图。大家可以直接验证程序的对错.


本系列所有源码打包下载地址(含proteus仿真工程文件和源程序):
http://www.51hei.com/bbs/dpj-82474-1.html

本例程下载:
计算器.rar (100.85 KB, 下载次数: 88)

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

使用道具 举报

沙发
ID:525751 发表于 2019-5-2 21:27 | 只看该作者
感谢分享 好东西啊
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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