找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3274|回复: 2
收起左侧

60个LED旋转显示的实时时钟程序调试还有有一点问题,大家一起来看看怎么解决吧

[复制链接]
ID:87316 发表于 2016-1-16 00:26 | 显示全部楼层 |阅读模式
定时二极管的循环显示间隔快于1S,无法使其保持和秒数同步,定时器中断设置不好。。程序如下,也有工程文件,一起来看看吧

test5.zip

65.92 KB, 下载次数: 20

程序

回复

使用道具 举报

ID:87316 发表于 2016-1-16 00:27 | 显示全部楼层
  1. #include<reg52.h>
  2. #include "ds18b20.h"
  3. #define uchar unsigned char
  4. #define uint unsigned int//蜂鸣器位定义
  5. sbit beep = P3^3 ;//DS1302相关操作线定义
  6. sbit RST = P1^1 ;
  7. sbit SCK = P1^2 ;
  8. sbit SDA = P1^3 ;  //按键定义,key1切换键,key2加,key3减,key4闹钟,年月日周
  9. sbit key1 = P1^4 ;
  10. sbit key2 = P1^5 ;
  11. sbit key3 = P1^6 ;
  12. sbit key4 = P1^7 ;
  13. sbit key5=P1^0;
  14. sbit rs=P3^6;
  15. sbit clk=P3^7;
  16. uchar i,j,mod,ledzz,flag,dot=3;flag1=1 ;//控制定时器动态扫描数码管的第几位,j是定时读取时间。mod是对key1按下次数计数。flag切换闹钟,日期,和周.flag1为闹钟标志位
  17. //uchar code write_addr[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分时日月周年 写地址
  18. //uchar code read_addr[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};  //秒分时日月周年 读地址
  19. //共阳数码管码表,表示0-9和-。-表示时分秒的间隔.
  20. uchar bit_code[]={
  21.   0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//数码管位选
  22. uchar code LED[11] =
  23. {
  24.     0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,
  25. };
  26. uchar disbuf[8] =
  27. {
  28.     0x62,0xa2,0xf7,0x7a,0x28,0xf7,0x7e,0x7e
  29. };//定义时间日期的结构类型
  30. struct time
  31. {
  32.     uchar second ;
  33.     uchar minute ;
  34.     uchar hour ;
  35.    // uchar week ;
  36.     uchar day ;
  37.     uchar month ;
  38.     uchar year ;
  39. }
  40. current_time ;
  41. #define ctime current_time//定义闹钟的时分秒变量
  42. uchar asec,amin,ahour ;
  43. void delay(uint ms)
  44. {
  45.     uchar i ;
  46.     while(ms--)
  47.     for(i=135;i>0;i--);
  48. }//滴一声,用来按键伴音
  49. void di()
  50. {
  51.     uchar i ;
  52.     for(i=0;i<40;i++)
  53.     {
  54.         beep = 0 ;
  55.         delay(1) ;
  56.         beep = 1 ;
  57.         delay(1) ;
  58.     }
  59. }
  60. //滴滴,连续响两下。用来闹钟提醒。
  61. void didi()
  62. {
  63.     uchar i ;
  64.     for(i = 2; i>0; i--)
  65.     {
  66.         di();
  67.         delay(140);
  68.     }
  69. }//DS1302的写驱动,传入参数为一个地址和数据
  70. void write(uchar addr,uchar dat)
  71. {
  72.     uchar i ;
  73.     RST = 0 ;
  74.     SCK = 0 ;
  75.     RST = 1 ;
  76.     for(i=0;i<8;i++)
  77.     {
  78.         SCK = 0 ;
  79.         SDA = (bit)(addr&0x01) ;
  80.         addr >>=1 ;
  81.         SCK = 1 ;
  82.     }
  83.     for(i=0;i<8;i++)
  84.     {
  85.         SCK = 0 ;
  86.         SDA = (bit)(dat&0x01);           //下降沿写入,上升沿读入
  87.         dat >>= 1 ;
  88.         SCK = 1 ;
  89.     }
  90.     RST = 0 ;
  91. }

  92. //DS1302的读驱动,传入参数为一个地址,返回参数为读到的数据
  93. uchar read(uchar addr)
  94. {
  95.     uchar i,dat ;
  96.     RST = 0 ;
  97.     SCK = 0 ;
  98.     RST = 1 ;
  99.     for(i=0;i<8;i++)
  100.     {
  101.         SCK = 0 ;
  102.         SDA =(bit)(addr&0x01);
  103.         addr>>=1 ;
  104.         SCK = 1 ;
  105.     }
  106.     for(i=0;i<8;i++)
  107.     {
  108.         SCK=0 ;
  109.         dat>>=1 ;
  110.         if(SDA)
  111.         dat|=0x80 ;
  112.         SCK=1 ;
  113.     }
  114.    
  115.     RST=0 ;
  116.     dat=(dat/16*10)+(dat&0x0f);
  117.     return dat ;
  118. }
  119. //读取DS1302的时间和日期
  120. void read_time()
  121. {
  122.     ctime.second = read(0x81);
  123.     ctime.minute = read(0x83);
  124.     ctime.hour   = read(0x85);
  125.     ctime.day    = read(0x87);
  126.     ctime.month  = read(0x89);
  127.     //ctime.week   = read(0x8b);
  128.     ctime.year   = read(0x8d);
  129. }
  130. //设定时间和日期
  131. void set_time()
  132. {
  133.     if(!flag)
  134.     {
  135.         write(0x8e,0x00);
  136.         write(0x80,((ctime.second/10)<<4|(ctime.second%10)));
  137.         write(0x82,((ctime.minute/10)<<4|(ctime.minute%10)));
  138.         write(0x84,((ctime.hour/10)<<4|(ctime.hour%10)));
  139.         write(0x8e,0x80);
  140.     }
  141.     else
  142.     {
  143.         write(0x8e,0x00);
  144.         write(0x86,((ctime.day/10)<<4|(ctime.day%10)));
  145.         write(0x88,((ctime.month/10)<<4|(ctime.month%10)));
  146.         //write(0x8a,((ctime.week/10)<<4|(ctime.week%10)));
  147.         write(0x8c,((ctime.year/10)<<4|(ctime.year%10)));
  148.         write(0x8e,0x80);
  149.     }
  150.     flag1=1 ;
  151. }
  152. //刷新显示缓冲区
  153. void refbuf()
  154. {
  155.     switch(flag)
  156.     {
  157.         case 1 :
  158.         disbuf[0] = LED[ctime.day%10];
  159.         disbuf[1] = LED[ctime.day/10];
  160.         disbuf[2] = 0xbf ;                 //10111111 -
  161.         disbuf[3] = LED[ctime.month%10];
  162.         disbuf[4] = LED[ctime.month/10];
  163.         disbuf[5] = 0xbf ;
  164.         disbuf[6] = LED[ctime.year%10];
  165.         disbuf[7] = LED[ctime.year/10];
  166.         break ;
  167.         /*case 2 :
  168.         disbuf[0] = 0xbf ;
  169.         disbuf[1] = 0xbf ;
  170.         disbuf[2] = 0xbf ;
  171.         disbuf[3] = 0xbf ;
  172.         disbuf[4] = LED[ctime.week] ;
  173.         disbuf[5] = 0xbf ;
  174.         disbuf[6] = 0xbf ;
  175.         disbuf[7] = 0xbf ;
  176.         break ;*/
  177.         case 2 :
  178.         disbuf[0] = LED[asec%10];
  179.         disbuf[1] = LED[asec/10];
  180.         disbuf[2] = 0xbf;
  181.         disbuf[3] = LED[amin%10];
  182.         disbuf[4] = LED[amin/10];
  183.         disbuf[5] = 0xbf;
  184.         disbuf[6] = LED[ahour%10];
  185.         disbuf[7] = LED[ahour/10];
  186.         break ;
  187.         default :
  188.         disbuf[0] = LED[ctime.second%10];
  189.         disbuf[1] = LED[ctime.second/10];
  190.         disbuf[2] = 0xbf;
  191.         disbuf[3] = LED[ctime.minute%10];
  192.         disbuf[4] = LED[ctime.minute/10];
  193.         disbuf[5] = 0xbf;
  194.         disbuf[6] = LED[ctime.hour%10];
  195.         disbuf[7] = LED[ctime.hour/10];
  196.     }
  197. }
  198. //键盘扫描
  199. void keyscan()
  200. {
  201.     if(key1 == 0)
  202.     {
  203.         delay(5);
  204.         if(key1 == 0)
  205.         {
  206.             while(!key1); //key1用来调节时间和日期、闹钟
  207.             mod++;//mod标示调节时间的时候对应的闪烁位,mod=1秒位或天或闹钟的秒,mod=2是分位,mod=3是小时位
  208.             di();//退出调节功能,返回正常显示
  209.             if(mod == 4)
  210.             {
  211.                 set_time();
  212.                 mod = 0 ;
  213.             }
  214.         }
  215.     } //调节加1
  216.     if(key2==0)
  217.     {
  218.         delay(5);
  219.         if(key2==0)
  220.         {
  221.             while(!key2);
  222.             di();
  223.             switch(mod)
  224.             {
  225.                 case 1 :
  226.                 ctime.second++;
  227.                 if(ctime.second==60)
  228.                 ctime.second=0 ;
  229.                 break ;
  230.                 case 2 :
  231.                 ctime.minute++;
  232.                 if(ctime.minute==60)
  233.                 ctime.minute=0 ;
  234.                 break ;
  235.                 case 3 :
  236.                 ctime.hour++;
  237.                 if(ctime.hour==24)
  238.                 ctime.hour=0 ;
  239.                 break ;
  240.             } //flag=0时默认调节时分秒,=1时调节年月日,=2时调节周,=3时调节闹钟,=4时就返回正常显示,flag又key4来控制。
  241.             if(flag==1)
  242.             {
  243.                 switch(mod)
  244.                 {
  245.                     case 1 :
  246.                     ctime.day++;
  247.                     if(ctime.day==32)
  248.                     ctime.day=0 ;
  249.                     break ;
  250.                     case 2 :
  251.                     ctime.month++;
  252.                     if(ctime.month==13)
  253.                     ctime.month=0 ;
  254.                     break ;
  255.                     case 3 :
  256.                     ctime.year++;
  257.                     if(ctime.year==100)
  258.                     ctime.year=0 ;
  259.                     break ;
  260.                 }
  261.             }
  262.            /* if(flag==2)
  263.             {
  264.                 if(mod==1)
  265.                 {
  266.                     ctime.week++;
  267.                     if(ctime.week==8)
  268.                     ctime.week=1 ;
  269.                 }
  270.             }*/
  271.             if(flag==2)
  272.             {
  273.                 switch(mod)
  274.                 {
  275.                     case 1 :
  276.                     asec++;
  277.                     if(asec==60)
  278.                     asec=0 ;
  279.                     break ;
  280.                     case 2 :
  281.                     amin++;
  282.                     if(amin==60)
  283.                     amin=0 ;
  284.                     break ;
  285.                     case 3 :
  286.                     ahour++;
  287.                     if(ahour==24)
  288.                     ahour=0 ;
  289.                     break ;
  290.                 }
  291.             }
  292.         }
  293.     }//调节减1,功能与key2相似。
  294.     if(key3==0)
  295.     {
  296.         delay(5);
  297.         if(key3==0)
  298.         {
  299.             while(!key3);
  300.             di();
  301.             switch(mod)
  302.             {
  303.                 case 1 :
  304.                 if(ctime.second==0)
  305.                 ctime.second=60 ;
  306.                 ctime.second--;
  307.                 break ;
  308.                 case 2 :
  309.                 if(ctime.minute==0)
  310.                 ctime.minute=60 ;
  311.                 ctime.minute--;
  312.                 break ;
  313.                 case 3 :
  314.                 if(ctime.hour==0)
  315.                 ctime.hour=24 ;
  316.                 ctime.hour--;
  317.                 break ;
  318.             }
  319.             if(flag==1)
  320.             {
  321.                 switch(mod)
  322.                 {
  323.                     case 1 :
  324.                     if(ctime.day==0)
  325.                     ctime.day=32 ;
  326.                     ctime.day--;
  327.                     break ;
  328.                     case 2 :
  329.                     if(ctime.month==0)
  330.                     ctime.month=13 ;
  331.                     ctime.month--;
  332.                     break ;
  333.                     case 3 :
  334.                     if(ctime.year==0)
  335.                     ctime.year=100 ;
  336.                     ctime.year--;
  337.                     break ;
  338.                 }
  339.             }
  340.            /* if(flag==2)
  341.             {
  342.                 if(mod==1)
  343.                 {
  344.                     if(ctime.week==1)
  345.                     ctime.week=8 ;
  346.                     ctime.week--;
  347.                 }
  348.             }  */
  349.             if(flag==2)
  350.             {
  351.                 switch(mod)
  352.                 {
  353.                     case 1 :
  354.                     if(asec==0)
  355.                     asec=60 ;
  356.                     asec--;
  357.                     break ;
  358.                     case 2 :
  359.                     if(amin==0)
  360.                     amin=60 ;
  361.                     amin--;
  362.                     break ;
  363.                     case 3 :
  364.                     if(ahour==0)
  365.                     ahour=24 ;
  366.                     ahour--;
  367.                     break ;
  368.                 }
  369.             }
  370.         }
  371.     }
  372.     if(key4==0)
  373.     {
  374.         delay(5);
  375.         if(key4==0)
  376.         {
  377.             while(!key4);
  378.             di();
  379.             flag++;
  380.             if(flag==3)
  381.             {
  382.                 flag=0 ;
  383.                 flag1=1 ;                                           //KEY4按一次显示日期,按2次显示闹钟
  384.             }
  385.         }
  386.     }
  387.         if(key5==0)
  388.     {
  389.         delay(5);
  390.         if(key5==0)
  391.         {
  392.             while(!key5);
  393.             di();
  394.                         TR0=0;
  395.                         //TR1=1;
  396.                         ds1820rst();
  397.                         while(key5)
  398.                         {      //初始化显示
  399.                             read_temp();    //读取温度
  400.                             ds1820disp();
  401.                        
  402.                         }   //显示
  403.                         //if(k==2)
  404.                         while(!key5);
  405.                         TR0=1;
  406.                        
  407.         //                EA=1;               
  408.        
  409.                 }
  410.         }
  411. }
  412. //初始化,定时器定时3ms用来动态扫描数码管显示
  413. void init()
  414. {
  415.     TMOD = 0X11 ;
  416.           EA   = 1 ;
  417.     TH0=(65536-3000)/256 ;
  418.     TL0=(65536-3000)%256 ;
  419.         TL1=0X18;
  420.         TH1=0XFC;
  421.         ET1=1;
  422.         PT0=1;

  423.         ET0  = 1 ;
  424.     TR0  = 1 ;
  425.   

  426.    
  427. /* write(0x8e,0x00);   //第一次写DS1302芯片,不然开始显示乱码,只需要初始化一次就行了,以后就屏蔽掉
  428.      write(0x80,0X10);
  429.      write(0x82,0X10);
  430.      write(0x84,0X10);
  431.      write(0x86,0x23);
  432.      write(0x88,0x07);
  433.      write(0x8a,0x06);
  434.      write(0x8c,0x11);
  435.      write(0x8e,0x80); */
  436.     read_time();
  437.     //每次初始化的时候都读取时钟芯片的时间,用来显示。
  438. }

  439. void main()
  440. {  
  441.     init();
  442.     while(1)
  443.     {
  444.         keyscan();
  445.         //闹钟判断,默认响1min,同时按下key2和key3关掉闹钟
  446.         if(amin==ctime.minute&&ahour==ctime.hour&&flag1)
  447.         {
  448.             didi();
  449.             if((key2==0)&&(key3==0))
  450.             {
  451.                 delay(5);
  452.                 if((key2==0)&&(key3==0))
  453.                 flag1=0 ;
  454.             }
  455.         }
  456.     }
  457. }
  458. void time0() interrupt 1
  459. {
  460.         static unsigned char count;
  461.     TH0=(65536-3000)/256 ;
  462.     TL0=(65536-3000)%256 ;
  463.     if(i==8)
  464.     {
  465.         i=0 ;
  466.         j++;
  467.     }
  468.         /****************************/
  469.          count++;
  470.         switch(dot)
  471.         {case 3:
  472.                 dot=2;
  473.                 ledzz=0;
  474.                 rs=1;
  475.                 rs=0;
  476.                 for(;ledzz!=ctime.second;)
  477.                 {
  478.                         clk=0;
  479.                         clk=1;
  480.                         ledzz++;
  481.                 }
  482.                 ET1=1;break;
  483.         //case 2:
  484.                 default:;
  485.         }

  486.         /**************************/
  487.     //实现调节是闪烁的效果
  488.     if(mod|flag)
  489.     {
  490.         if(j==10)
  491.         {
  492.             switch(mod)
  493.             {
  494.                 case 1 :
  495.                 disbuf[0]=0xff ;
  496.                 disbuf[1]=0xff ;
  497.                 break ;
  498.                 case 2 :
  499.                 disbuf[3]=0xff ;
  500.                 disbuf[4]=0xff ;
  501.                 break ;
  502.                 case 3 :
  503.                 disbuf[6]=0xff ;
  504.                 disbuf[7]=0xff ;
  505.                 break ;
  506.             }
  507.         }
  508.     }
  509.         if(count==10)  //到了0.5秒
  510.         {  

  511. /**************************/
  512.           ledzz++;
  513.           if(ledzz==60)  //点完第59个后,复位下一个则第60个被点亮
  514.                 {
  515.                         ledzz=0;
  516.                         rs=1;
  517.                         rs=0;
  518.                 }
  519.           if(ledzz!=ctime.second)
  520.           {           ledzz=0;
  521.                         rs=1;
  522.                         rs=0;
  523.                     while(ledzz!=ctime.second)
  524.                 {
  525.                         clk=0;
  526.                         clk=1;
  527.                         ledzz++;
  528.                 }
  529.           }
  530. /*****************************/


  531.                 clk=1;  //LED亮
  532.                 di();
  533.                 clk=0;//LED灭,下一个点亮
  534.                                
  535.                        
  536.         }
  537.         /*if(count==20)  //到了一步
  538.         {
  539.                 count=0; //秒指针清零
  540.                 //ctime.second++;
  541.                 di();
  542.         /* for(i=0;i<8;i++)                              //对数码管进行动态扫描
  543.    {
  544.     P2=(0x80>>i);
  545.         P0=disbuf[i];
  546.         delay(5);
  547.    }   */
  548.     P2=(0x80>>i);                       
  549.     P0=disbuf[i];
  550.     i++;
  551.     //3msx8x20,大约480ms从DS1302芯片读取一下时间
  552.     if(j==20)
  553.     {
  554.         j=0 ;
  555.         refbuf();
  556.         if(mod==0)
  557.         read_time();
  558.                
  559.     }
  560.         //TR1=1;
  561.         }
  562. //}
  563. /********************T1*****/
  564. void Timer1ISR(void) interrupt 3                //定时器1中断 定时1ms用于捉个点亮的时间间隔
  565. {
  566.         static unsigned char count;
  567.          
  568.          TL1=0X18;
  569.          TH1=0XFC;
  570.          count++;
  571.          if(count<62)
  572.          {       
  573.                  clk=0;
  574.                 clk=1;
  575.                 ledzz++;
  576.                 if(ledzz==60)  //点完第59个后,复位下一个则第60个被点亮
  577.                 {
  578.                         ledzz=0;
  579.                         rs=1;
  580.                         rs=0;
  581.                 }

  582.          }
  583.          else
  584.          {
  585.                  count=0;
  586.                 TR1=0;
  587.          }
  588. }

  589. /***************************/
复制代码
回复

使用道具 举报

ID:87316 发表于 2016-1-16 00:28 | 显示全部楼层
还有温度的代码没复制上来,,有没有大神帮忙看一下
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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