找回密码
 立即注册

QQ登录

只需一步,快速开始

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

分享一个单片机万年历的程序(6个数码管显示)

[复制链接]
跳转到指定楼层
楼主
ID:323712 发表于 2018-5-6 21:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
网上找的大多数都是用液晶显示的,这是用6个数码管显示

单片机源程序如下:
  1.   #include <reg51.h>
  2.   #include <intrins.h>
  3.   #define uchar unsigned char
  4.   #define uchar unsigned char
  5.   #define uint unsigned int
  6.   sbit DS1302_CLK=P3^2;
  7.   sbit DS1302_IO=P3^3;
  8.   sbit DS1302_RST=P3^4;
  9.   sbit ACC0=ACC^0;
  10.   sbit ACC7=ACC^7;
  11.   sbit Tiaoshi=P3^7;  //调试按键
  12.   sbit Inck=P3^6;        //升序按键
  13.   uchar count=0;        //记录按键次数
  14.   uchar temp;
  15.    sfr Wei=0xa0;
  16.    sfr Duan=0x90;
  17.   bit Inck_flag=0x20;        //升序调试标志
  18.   bit flag=0x21;
  19.   char hide_sec;
  20.   char hide_min;
  21.   char hide_hour;
  22.   char hide_day;
  23.   char hide_month;
  24.   char hide_year;
  25.   typedef struct _SYSTEMTIME_
  26. {
  27.     uchar Second;
  28.         uchar Minute;
  29.         uchar Hour;
  30.         uchar Day;
  31.         uchar Month;
  32.         uchar Year;
  33.         uchar TimeStr[12];
  34.   }SYSTEMTIME;                         //定义的时间类型
  35.   SYSTEMTIME CurrentTime;  //结构体名称CurrentTime
  36.   #define AM(X) X
  37.   #define PM(X) (X+12)         //转成24小时制
  38.   #define DS1302_SECOND 0x80  //秒寄存器地址
  39.   #define DS1302_MINUTE 0x82  //分寄存器地址
  40.   #define DS1302_HOUR 0x84         //小时寄存器地址
  41.   #define DS1302_DAY 0x86
  42.    #define DS1302_MONTH 0x88
  43.   #define DS1302_YEAR 0x8c
  44.   void mdelay(unsigned int count)         //延时函数
  45.   {
  46.     uchar i,j;
  47.         for(i=0;i<count;i++)
  48.         {
  49.           for(j=0;j<120;j++)
  50.           ;
  51.         }
  52.   }
  53.   void DS1302InputByte(uchar d)          //向1302中通过ACC输入数值d
  54.   {
  55.     uchar i;
  56.         ACC=d;
  57.         for(i=8;i>0;i--)
  58.         {
  59.           DS1302_IO=ACC0;
  60.           DS1302_CLK=1;          //一个时钟的上升沿输出
  61.           DS1302_CLK=0;
  62.           ACC=ACC>>1;
  63.         }
  64.   }
  65. uchar DS1302OutputByte(void)           //ds1302向单片机发送数据返回值为ACC
  66. {
  67.    uchar i;
  68.    for(i=8;i>0;i--)
  69.    {
  70.      ACC=ACC>>1;
  71.          ACC7=DS1302_IO;
  72.          DS1302_CLK=1;
  73.          DS1302_CLK=0;
  74.         }
  75.         return(ACC);
  76. }
  77. void Write1302(uchar ucAddr,uchar ucDa)   //向ds1302中写入数据地址为Addar,数据为ucDa
  78. {
  79.    DS1302_RST=0;
  80.    DS1302_CLK=0;
  81.    DS1302_RST=1;
  82.    DS1302InputByte(ucAddr);           //先发送地址,命令
  83.    DS1302InputByte(ucDa);           //然后写1Byte数据
  84.    DS1302_CLK=1;
  85.    DS1302_RST=0;
  86.   }
  87.   uchar Read1302(uchar ucAddr)        //读取DS1302某地址的数据
  88.   {
  89.     uchar ucData;
  90.         DS1302_RST=0;
  91.         DS1302_CLK=0;
  92.         DS1302_RST=1;
  93.         DS1302InputByte(ucAddr|0x01);                //输入地址,命令
  94.         ucData=DS1302OutputByte();                        //读1Byte数据
  95.         DS1302_CLK=1;
  96.         DS1302_RST=0;
  97.         return(ucData);
  98.   }
  99.   void DS1302_SetProtect(bit flag1)                //           是否写保护
  100.   {
  101.     if(flag1)
  102.             Write1302(0x8E,0x10);
  103.         else
  104.             Write1302(0x8E,0x00);
  105.   }
  106.   void DS1302_SetTime(uchar Address,uchar Value)     //设置时间函数
  107.   {
  108.       DS1302_SetProtect(0);
  109.           Write1302(Address,((Value/10)<<4|(Value%10)));
  110.   }
  111.   void DS1302_GetTime(SYSTEMTIME *Time)           //将ds1302中读取的数据存入结构体
  112.   {
  113.     uchar ReadValue;
  114.         ReadValue=Read1302(DS1302_SECOND);        //将秒位的数据赋值给ReadValue变量
  115.         Time->Second=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);        //结构体中的数变为十进制数
  116.         ReadValue=Read1302(DS1302_MINUTE); //分位
  117.         Time->Minute=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
  118.         ReadValue=Read1302(DS1302_HOUR);
  119.         Time->Hour=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);


  120.         ReadValue=Read1302(DS1302_DAY);        //将的数据赋值给ReadValue变量
  121.         Time->Day=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);        //结构体中的数变为十进制数
  122.         ReadValue=Read1302(DS1302_MONTH); //
  123.         Time->Month=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
  124.         ReadValue=Read1302(DS1302_YEAR);
  125.         Time->Year=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
  126.   }
  127.   void TimeToStr(SYSTEMTIME *Time)           //数据缓存区
  128.   {
  129.      Time->TimeStr[0]=Time->Hour/10;   //将小时的十位存入TimeStr[0]
  130.          Time->TimeStr[1]=Time->Hour%10;

  131.          Time->TimeStr[2]=Time->Minute/10;
  132.          Time->TimeStr[3]=Time->Minute%10;

  133.          Time->TimeStr[4]=Time->Second/10;
  134.          Time->TimeStr[5]=Time->Second%10;


  135.          Time->TimeStr[6]=Time->Year/10;   //将小时的十位存入TimeStr[0]
  136.          Time->TimeStr[7]=Time->Year%10;

  137.          Time->TimeStr[8]=Time->Month/10;
  138.          Time->TimeStr[9]=Time->Month%10;

  139.          Time->TimeStr[10]=Time->Day/10;
  140.          Time->TimeStr[11]=Time->Day%10;
  141.   }
  142.   void Delay1ms(uint count1)        //延时函数
  143.   {
  144.     uint i,j;
  145.         for(i=0;i<count1;i++)
  146.         for(j=0;j<120;j++);
  147.   }
  148.   void Dis(SYSTEMTIME *Time)  //显示函数
  149.   {
  150.     uchar disbit,shitfb;
  151.         DS1302_GetTime(Time);        //从1302中获取时间并存入结构体Time中
  152.         TimeToStr(Time);          //将结构体中数据缓存至TimeStr[0]
  153.         disbit=1;          //0xfe;        最后一位打开
  154.         for(shitfb=0;shitfb<6;shitfb++)
  155.         {_nop_();     _nop_();          //延时
  156.          Duan=Time->TimeStr[shitfb]; //段选依次输入         TimeStr[0]到TimeStr[5];
  157.          Wei=_crol_(disbit,shitfb);         //位选依次亮起
  158.           Delay1ms(2);
  159.           Wei=0;
  160.          }
  161.    }

  162.     void Dis2(SYSTEMTIME *Time)  //显示函数
  163.   {
  164.     uchar disbit,shitfb;
  165.         DS1302_GetTime(Time);        //从1302中获取时间并存入结构体Time中
  166.         TimeToStr(Time);          //将结构体中数据缓存至TimeStr[0]
  167.         disbit=1;          //0xfe;        最后一位打开
  168.         for(shitfb=6;shitfb<12;shitfb++)
  169.         {_nop_();     _nop_();          //延时
  170.          Duan=Time->TimeStr[shitfb]; //段选依次输入         TimeStr[6]到TimeStr[11];
  171.          Wei=_crol_(disbit,shitfb-6);         //位选依次亮起
  172.           Delay1ms(2);
  173.           Wei=0;
  174.          }
  175.    }

  176.    void Setkey()        //模式选择按键
  177.    {
  178.        Tiaoshi=1;
  179.            if(Tiaoshi==0)         //调试按键按下
  180.            {
  181.               mdelay(8);
  182.                   count=count+1;  //count从0开始计数
  183.                   if(count==7)count=0;
  184.                   while(Tiaoshi==0); //按键松开跳出循环
  185.                 }
  186.         }
  187.    void Inckey()         //升序按键
  188.    {
  189.       Inck=1;
  190.           if(Inck==0)        //升序按键按下
  191.           {   mdelay(8);
  192.               switch(count)         //选择调时模式
  193.                   {case 1:        //调整小时
  194.                    temp=Read1302(DS1302_HOUR);   //读取小时数 将返回的ACC存入temp
  195.                    temp=((temp&0x70)>>4)*10+(temp&0x0f);   //将ACC化为十进制数
  196.                    temp=temp+1;                                         //小时数加1
  197.                    if(temp>=24)temp=0;
  198.                    Inck_flag=1;
  199.                    break;
  200.                    case 2:
  201.                     temp=Read1302(DS1302_MINUTE); //读取分数
  202.                         temp=((temp&0x70)>>4)*10+(temp&0x0f);
  203.                         temp=temp+1;                 //分数加1
  204.                         Inck_flag=1;
  205.                         if(temp>=60)temp=0;
  206.                         break;
  207.                         case 3:
  208.                          temp=Read1302(DS1302_SECOND);         //读取秒数
  209.                          temp=((temp&0x70)>>4)*10+(temp&0x0f);
  210.                          temp=temp+1;                  //秒数加1
  211.                          Inck_flag=1;                   //数据调整后更新标志
  212.                          if(temp>=60)temp=0;
  213.                          break;

  214.                          case 4:        //调整年
  215.                    temp=Read1302(DS1302_YEAR);   //读取年 将返回的ACC存入temp
  216.                    temp=((temp&0x70)>>4)*10+(temp&0x0f);   //将ACC化为十进制数
  217.                    temp=temp+1;                                         //小时数加1
  218.                    if(temp>=99)temp=0;
  219.                    Inck_flag=1;
  220.                    break;
  221.                    case 5:
  222.                     temp=Read1302(DS1302_MONTH); //读取
  223.                         temp=((temp&0x70)>>4)*10+(temp&0x0f);
  224.                         temp=temp+1;                 //
  225.                         Inck_flag=1;
  226.                         if(temp>=12)temp=0;
  227.                         break;
  228.                         case 6:
  229.                          temp=Read1302(DS1302_DAY);         //读取秒数
  230.                          temp=((temp&0x70)>>4)*10+(temp&0x0f);
  231.                          temp=temp+1;                  //秒数加1
  232.                          Inck_flag=1;                   //数据调整后更新标志
  233.                          if(temp>=32)temp=0;
  234.                          break;


  235.                          default: Inck_flag=0;break;
  236.                          }
  237.                          while(Inck==0); //检测松开按键
  238.                         }
  239.         }
  240.    void Keydone()               //按键功能执行
  241.    {   
  242.                   Setkey();                           //扫描模式切换按键
  243.                   switch(count)
  244.                   {case 1:do                                 //count=1,调整时
  245.                        {  Inckey();
  246.                               if(Inck_flag==1)
  247.                                   { temp=(temp/10)<<4|temp%10;
  248.                                     Write1302(0x8e,0x00);   //写入允许
  249.                                         Write1302(0x84,temp);   //写入新的小时数temp
  250.                                         Write1302(0x8e,0x80);   //禁止写入
  251.                                         Inck_flag=0;
  252.                                         }
  253.                                         hide_hour++;
  254.                                         if(hide_hour>3)
  255.                                         hide_hour=0;
  256.                                         Dis(&CurrentTime) ;
  257.                                         }while(count==2);break;
  258.                         case 2:do                                  //count=2,调整分
  259.                           {   hide_hour=0;
  260.                               Inckey();
  261.                                   if(Inck_flag==1)
  262.                                   {   temp=(temp/10)<<4|temp%10;
  263.                                       Write1302(0x8e,0x00); //写入允许
  264.                                           Write1302(0x82,temp); //写入新的分数
  265.                                           Write1302(0x8e,0x80); //禁止写入
  266.                                           Inck_flag=0;
  267.                                           }
  268.                                           hide_min++;
  269.                                           if(hide_min>3)
  270.                                           hide_min=0;
  271.                                           Dis(&CurrentTime);  //程序每循环三次显示一下
  272.                                           }while(count==3);break;
  273.                         case 3:do                                         //调整秒
  274.                                {  hide_min=0;
  275.                                       Inckey();                 //扫描加按钮
  276.                                           if(Inck_flag==1)                 //数据更新,重新写入新的数据
  277.                                           {   temp=(temp/10)<<4|temp%10;
  278.                                               Write1302(0x8e,0x00);             //写入允许
  279.                                                   Write1302(0x80,temp&0x7f);  //写入新的秒数
  280.                                                   Write1302(0x8e,0x80);       //禁止写入
  281.                                                   Inck_flag=0;
  282.                                                 }
  283.                                                 hide_sec++;      //位闪计时
  284.                                                 if(hide_sec>3)
  285.                                                 hide_sec=0;
  286.                                                 Dis(&CurrentTime);
  287.                                                 }while(count==4);break;


  288.                                                 case 4:do                                 //count=1,调整
  289.                        {  Inckey();
  290.                               if(Inck_flag==1)
  291.                                   { temp=(temp/10)<<4|temp%10;
  292.                                     Write1302(0x8e,0x00);   //写入允许
  293.                                         Write1302(0x8c,temp);   //写入新的
  294.                                         Write1302(0x8e,0x80);   //禁止写入
  295.                                         Inck_flag=0;
  296.                                         }
  297.                                         hide_year++;
  298.                                         if(hide_year>3)
  299.                                         hide_year=0;
  300.                                         Dis2(&CurrentTime) ;
  301.                                         }while(count==5);break;
  302.                         case 5:do                                  //count=5
  303.                           {   hide_year=0;
  304.                               Inckey();
  305.                                   if(Inck_flag==1)
  306.                                   {   temp=(temp/10)<<4|temp%10;
  307.                                       Write1302(0x8e,0x00); //写入允许
  308.                                           Write1302(0x88,temp); //写入新的
  309.                                           Write1302(0x8e,0x80); //禁止写入
  310.                                           Inck_flag=0;
  311.                                           }
  312.                                           hide_month++;
  313.                                           if(hide_month>3)
  314.                                           hide_month=0;
  315.                                           Dis2(&CurrentTime);  //程序每循环三次显示一下
  316.                                           }while(count==6);break;
  317.                         case 6:do                                         //调整
  318.                                {  hide_month=0;
  319.                                       Inckey();                 //扫描加按钮
  320.                                           if(Inck_flag==1)                 //数据更新,重新写入新的数据
  321.                                           {   temp=(temp/10)<<4|temp%10;
  322.                                               Write1302(0x8e,0x00);             //写入允许
  323.                                                   Write1302(0x86,temp);  //写入新的
  324.                                                   Write1302(0x8e,0x80);       //禁止写入
  325.                                                   Inck_flag=0;
  326.                                                 }
  327.                                                 hide_day++;      //位闪计时
  328.                                                 if(hide_day>3)
  329.                                                 hide_day=0;
  330.                                                 Dis2(&CurrentTime);
  331.                                                 }while(count==7);break;

  332.                         case 7:
  333.                         count=0;hide_sec=0;        hide_day=0;
  334.                         break;
  335.                         default: break;
  336.                         }
  337.                 }
  338.                 main()
  339.                 {   Inck_flag=0;
  340.                     while(1)
  341.                         {
  342.                                 if(count<4)
  343.                                 {
  344.                                 Dis(&CurrentTime);
  345.                            Setkey();
  346.                            if(count!=0)//(F0==1)
  347.                            Keydone();
  348.                            } //进入调整模式

  349.                                    if(count>=4)
  350.                                 {
  351.                                 Dis2(&CurrentTime);
  352.                            Setkey();
  353.                            if(count!=0)//(F0==1)
  354.                            Keydone();
  355.                            } //进入调整模式

  356.                            }
  357.                         }
复制代码

所有资料51hei提供下载:
wanniali.rar (39.63 KB, 下载次数: 32)


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

使用道具 举报

沙发
ID:455189 发表于 2018-12-26 10:49 | 只看该作者
谢谢楼主,lznb
回复

使用道具 举报

板凳
ID:542652 发表于 2019-5-20 11:42 | 只看该作者
我想问怎么接线
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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