找回密码
 立即注册

QQ登录

只需一步,快速开始

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

发一个DS1302的单片机实时时钟仿真与源码,希望能帮到初学者

  [复制链接]
跳转到指定楼层
楼主
描述:
1、8位共阴数码管显示实时时钟88-88-88样式,两‘-’1秒闪烁1次
2、STC89C52 @ 11.0592MHz晶振,两片74HC573做段选、位选
3、调时的时候,key2键短按加1,长按连加;key3键短按减一,长按连减;按键消抖不用delay。
4、在调时状态超过3秒再没有按键按下,回到走时状态
5、加备用电池,掉电走时        ,仿真 实物都通过。

仿真图:


单片机源程序:
  1. /*********************************************************************************
  2. 描述:
  3. 1、8位共阴数码管显示实时时钟88-88-88样式,两‘-’1秒闪烁1次
  4. 2、STC89C52 @ 11.0592MHz晶振,两片74HC573做段选、位选
  5. 3、调时的时候,key2键短按加1,长按连加;key3键短按减一,长按连减;按键消抖不用delay。
  6. 4、在调时状态超过3秒再没有按键按下,回到走时状态
  7. 5、加备用电池,掉电走时        ,仿真 实物都通过。
  8. **********************************************************************************/
  9. #include<reg52.h>
  10. #include<intrins.h>

  11. #define uchar unsigned char
  12. #define uint unsigned int

  13. /***********写时分秒地址************/
  14. #define write_shi  0x84
  15. #define write_fen  0x82
  16. #define write_miao 0x80
  17. #define write_ram  0xc0
  18. /***********读时分秒地址************/
  19. #define read_shi  0x85
  20. #define read_fen  0x83
  21. #define read_miao 0x81
  22. #define read_ram  0xc1

  23. sbit sclk = P1^0;           //控制数据时钟
  24. sbit dio = P1^1;           //数据口
  25. sbit ce = P1^2;                   //使能端、复位端
  26. sbit wela = P2^7;           //位选
  27. sbit dula = P2^6;           //段选

  28. sbit key1=P3^0;                        //按键 选择
  29. sbit key2=P3^1;                        //按键 加
  30. sbit key3=P3^2;                        //按键 减

  31. uint ms;                                //调时自动走时计时变量
  32. uchar knum=0,snum,fnum,ss;        //定义 key1按下次数变量,时分调时闪烁变量,两‘-’闪烁计时变量
  33. char shi,fen,miao;                //定义时分秒变量

  34. bit f1,f2,f3;                        //定义自动走时标志
  35.                                   // 0     1    2    3    4     5    6    7    8   9        不显  -
  36. uchar code d[]={ 0x3F,0x06,0x5B,0x4F,0x66, 0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40}; //共阴不带小数点段码

  37. void delay(uint z)          //ms延时函数
  38. {
  39.         uint x,y;
  40.         for(x=z;x>0;x--)
  41.                 for(y=120;y>0;y--);
  42. }

  43. void t0_init()  //定时器初始化函数
  44. {
  45.    
  46.         TMOD |= 0X11;                         //定时器0、1都为模式1, 16位计数模式
  47.         TH0=(65536-46080)/256;   //50ms初值  @11.0529MHz
  48.         TL0=(65536-46080)%256;
  49.         TH1=(65536-921)/256;         //1ms初值  @11.0529MHz
  50.         TL1=(65536-921)%256;
  51.         
  52.         EA=1;                                         //开总中断
  53.         ET0=1;                                         //开定时器T0中断
  54.         TR0=1;                                         //启动T0
  55.         ET1=1;                                         //开定时器T1中断
  56. //  TR1=1;

  57. }


  58. void display(uchar shi,uchar fen,uchar miao) //显示函数
  59. {
  60.         if(knum==0)           //正常走时
  61.         {
  62.                 snum=30;
  63.                 fnum=30;
  64.         }
  65.         
  66.         if(knum==1)           //调时,分位闪烁
  67.         {
  68.                 fnum++;
  69.                 snum=30;
  70.         }
  71.         
  72.         if(knum==2)          //调时,时位闪烁
  73.         {
  74.                 snum++;
  75.                 fnum=30;
  76.         }
  77.         
  78.         
  79.         if(snum>=30)
  80.         {        
  81.                 if((shi/10)<1)         //如果小时十位小于1,
  82.                 {
  83.                         wela=1;
  84.                         P0=0xfe;                //第1位
  85.                         wela=0;
  86.         
  87.                         dula = 1;
  88.                         P0=d[10];           //共阴数码管段码送全0 小时十位就不显示
  89.                         dula = 0;
  90.                 }
  91.                
  92.                 else
  93.                 {
  94.                         wela=1;
  95.                         P0=0xfe;          //第1位
  96.                         wela=0;
  97.         
  98.                         dula=1;
  99.                         P0=d[shi/10];
  100.                         dula=0;
  101.                         P0=0xff;
  102.                         delay(2);
  103.                 }

  104.                 wela=1;
  105.                 P0=0xfd;           //第2位
  106.                 wela=0;

  107.                 dula=1;
  108.                 P0=d[shi%10];                        
  109.                 dula=0;                                       
  110.                 P0=0xff;
  111.                 delay(2);
  112.         
  113.                 if(snum==60)
  114.                         snum=0;
  115.         }               


  116.         //        if(miao%2==0)         //if(miao%2==0) 1秒闪烁1次
  117.         if(ss>=10)                 //        这里写为ss>=10,闪烁频率可调
  118.         {                                 
  119.             wela=1;
  120.                 P0=0xfb;                //第3位
  121.                 wela=0;
  122.         
  123.                 dula=1;
  124.                 P0=d[11];          //第三位数码管显示“— ”
  125.                 dula=0;
  126.                 P0=0xff;
  127.                 delay(2);
  128.         }
  129.         
  130.         else
  131.         {
  132.                 wela=1;
  133.                 P0=0xfb;     //第3位
  134.                 wela=0;
  135.         
  136.                 dula=1;
  137.                 P0=d[10];         //第三位数码管不显示
  138.                 dula=0;
  139.                 P0=0xff;
  140.                 delay(2);        
  141.         }
  142.         
  143.         
  144.         if(fnum>=30)
  145.         {
  146.                 wela=1;
  147.                 P0=0xf7;         //第4位
  148.                 wela=0;

  149.                 dula=1;
  150.                 P0=d[fen/10];
  151.                 dula=0;
  152.                 P0=0xff;
  153.                 delay(2);
  154.                
  155.                
  156.                 wela=1;
  157.                 P0=0xef;         //第5位
  158.                 wela=0;

  159.                 dula=1;
  160.                 P0=d[fen%10];
  161.                 dula=0;
  162.                 P0=0xff;
  163.                 delay(2);
  164.         
  165.                
  166.                 if(fnum==60)
  167.                         fnum=0;
  168.         }
  169.                
  170.         //        if(miao%2==0)         //if(miao%2==0) 1秒闪烁1次
  171.         if(ss>=10)                 //if(ss>=10)闪烁频率可调
  172.         {
  173.                 wela=1;
  174.                 P0=0xdf;          //第6位
  175.                 wela=0;
  176.                 dula=1;
  177.                 P0=d[11];          //第六位数码管显示“— ”
  178.                 dula=0;
  179.                 P0=0xff;
  180.                 delay(2);
  181.         }
  182.         
  183.         else
  184.         {
  185.                 wela=1;
  186.                 P0=0xdf;                   //第6位
  187.                 wela=0;
  188.                 dula=1;
  189.                 P0=d[10];                  //第六位数码管不显示
  190.                 dula=0;
  191.                 P0=0xff;
  192.                 delay(2);
  193.         }
  194.         
  195.         
  196.         wela=1;
  197.         P0=0xbf;                        //第7位
  198.         wela=0;
  199.         
  200.         dula=1;
  201.         P0=d[miao/10];                //秒十位
  202.         dula=0;
  203.         P0=0xff;
  204.         delay(2);
  205.         
  206.         
  207.         wela=1;
  208.         P0=0x7f;                         //第8位
  209.         wela=0;
  210.         
  211.         dula=1;
  212.         P0=d[miao%10];                //秒个位
  213.         dula=0;
  214.         P0=0xff;
  215.         delay(2);               
  216. }  

  217. void write_1302(uchar add,dat)//写1302函数  
  218. {
  219.         uchar i,temp;
  220.         temp=add;
  221.         ce=0;
  222.         _nop_();
  223.         sclk=0;
  224.         _nop_();
  225.         ce=1;
  226.         _nop_();
  227.         for(i=0;i<8;i++)
  228.         {
  229.                 sclk=0;
  230.                 _nop_();
  231.                 if((temp&0x01)==0x01)
  232.                         dio=1;
  233.                         else
  234.                         dio=0;
  235.                 temp>>=1;
  236.                 sclk=1;
  237.                 _nop_();
  238.         }
  239.         temp=dat;
  240.         for(i=0;i<8;i++)
  241.         {
  242.                 sclk=0;
  243.                 _nop_();
  244.                 if((temp&0x01)==0x01)
  245.                         dio=1;
  246.                         else
  247.                         dio=0;
  248.                 temp>>=1;
  249.                 sclk=1;
  250.                 _nop_();
  251.         }
  252.         ce=0;
  253.         sclk=0;
  254. }

  255. uchar read_1302(uchar add)        //读1302函数
  256. {
  257.         uchar dat,dat1,i,temp;
  258.         temp=add;
  259.         ce=0;
  260.         _nop_();
  261.         sclk=0;
  262.         _nop_();
  263.         ce=1;
  264.         for(i=0;i<8;i++)
  265.         {
  266.                 sclk=0;
  267.                 _nop_();
  268.                 if((temp&0x01)==0x01)
  269.                         dio=1;
  270.                         else
  271.                         dio=0;
  272.                 temp>>=1;
  273.                 sclk=1;
  274.                 _nop_();
  275.         }
  276.         for(i=0;i<8;i++)
  277.         {
  278.                 sclk=0;
  279.                 _nop_();
  280.                 if(dio)
  281.                     dat|=0x80;
  282.                 if(i<7)
  283.                         dat>>=1;
  284.                 sclk=1;
  285.         }
  286.         dat1=dat/16;
  287.         dat=dat%16;
  288.         dat=dat1*10+dat;  
  289.         ce=0;
  290.         sclk=0;
  291.         return dat;
  292. }                        


  293. void init_1302()                                                        //自动初始化函数
  294. {        
  295.         if(read_1302(read_ram) != 0xaa)                        //如果初始化标志RAM的值不是0xaa,才初始化
  296.         {
  297.                 write_1302(0x8e,0x00);                                //保护取消,可以进行写操作
  298.                 write_1302(write_miao,0x57);                //写秒57
  299.                 write_1302(write_fen,0x55);                        //写分55
  300.                 write_1302(write_shi,0x15);                        //写时15
  301.                 write_1302(write_ram,0xaa);                        //写入初始化标志RAM(第00个RAM位置)
  302.                 write_1302(0x8e,0x80);                                //保护启动,不能进行写操作
  303.         }
  304. }         

  305. void read_sf()        //读时分秒并显示
  306. {
  307.         shi=read_1302(read_shi);
  308.         fen=read_1302(read_fen);
  309.         miao=read_1302(read_miao);
  310.         display(shi,fen,miao);
  311. }


  312. void keyscan()                        //按键扫描函数
  313. {        
  314.         static uchar count;          //这里要定义为静态变量
  315.         
  316.         if(key1==0)                          //按键按下
  317.         {        
  318.                 TR1=1;
  319.                 count++;                          //消抖,也是连加一次的间隔时间
  320.                 f1=1;
  321.                 if(key1==0 && count>10)//按键按下,计数变量加到12,
  322.                 {
  323.                         ms=0;                           //自启动计时变量清零
  324.                         while(!key1)           //这里不需要连加,就加一句松手检测
  325.                         display(shi,fen,miao);
  326.                         count=0;
  327.                         TR0=0;                           //关闭T0定时器,数码管两‘-’停止闪烁
  328.                         knum++;                           
  329.                         if(knum==1)                                                  
  330.                         {
  331.                                  write_1302(0x8e,0x00);                  //DS1302写保护取消
  332.                                  write_1302(write_miao,0x80); //写秒80,时钟停止走时;
  333.                         }
  334.                         
  335.                         if(knum==3)                                                   //调时完毕,时钟启动
  336.                         {
  337.                                 TR0=1;                                                //启动T0定时器,数码管两‘-’开始闪烁
  338.                                 knum=0;
  339.                                 write_1302(write_miao,0x00); //写秒0,时钟启动走时
  340.                                 write_1302(0x8e,0x80);                 //保护启动
  341.                         }
  342.                 }
  343.         }


  344.         if(knum==1)                                                                //分钟调节
  345.         {
  346.                 if(key2==0)                                                        //加
  347.                 {
  348.                         f2=1;
  349.                         count++;
  350.                         if(key2==0 && count>12)//短按加1,长按连加
  351.                         {
  352.                                 ms=0;                           //自启动计时变量清零
  353.                                 count=0;
  354.                                 fen++;
  355.                                 fen=fen/10*16+fen%10;                //转为16进制
  356.                                 if(fen==0x60)
  357.                                         fen=0x00;
  358.                                 write_1302(write_fen,fen);        //写入1302
  359.                         }
  360.                 }
  361.                
  362.                 if(key3==0)                                                   //减
  363.                 {
  364.                         f3=1;
  365.                         count++;
  366.                         if(key3==0 && count>12)//短按减1,长按连减
  367.                         {
  368.                                 ms=0;                           //自启动计时变量清零
  369.                                 count=0;
  370.                                 fen--;
  371.                                 fen=fen/10*16+fen%10;                //转为16进制
  372.                                 if(fen==-1)
  373.                                         fen=0x59;
  374.                                 write_1302(write_fen,fen);
  375.                         }
  376.                 }
  377.         }
  378.         
  379.         
  380.         if(knum==2)                                                          //小时调节
  381.         {
  382.                 if(key2==0)
  383.                 {        
  384.                         f2=1;
  385.                         count++;
  386.                         if(key2==0 && count>12 )//短按加1,长按连加
  387.                         {
  388.                                 ms=0;                                //自启动计时变量清零
  389.                                 count=0;
  390.                                 shi++;
  391.                                 shi=shi/10*16+shi%10;//转为16进制
  392.                                 if(shi==0x24)
  393.                                         shi=0x00;
  394.                                 write_1302(write_shi,shi);
  395.                         }
  396.                 }
  397.                
  398.                
  399.                 if(key3==0)
  400.                 {
  401.                         f3=1;
  402.                         count++;
  403.                         if(key3==0 && count>12 )//短按减1,长按连减
  404.                         {        
  405.                                 ms=0;                                //自启动计时变量清零
  406.                                 count=0;
  407.                                 shi--;
  408.                                 shi=shi/10*16+shi%10;//转为16进制
  409.                                 if(shi==-1)
  410.                                         shi=0x23;
  411.                                 write_1302(write_shi,shi);
  412.                         }
  413.                 }
  414.         }

  415.         /*按键超过3秒没有动作,时钟回到走时状态*/

  416.         if(f1==1 || f2==1 || f3==1)
  417.         {
  418.                 if(ms>3000)          //时间超过3秒
  419.                 {
  420.                         TR1=0;          //关闭T1
  421.                         ms=0;          //自启动计时变量清零
  422.                         knum=0;          //key1按键次数清零
  423.                         TR0=1;          //启动T0,数码管两‘-’开始闪烁
  424.                         write_1302(write_miao,0x00); //写秒0,时钟启动走时
  425.                         write_1302(0x8e,0x80);                 //保护启动
  426.                 }
  427.         
  428.         }
  429. }           

  430. /*主函数*/
  431. void main()
  432. {//        uchar i;
  433.         t0_init();
  434.         init_1302();                          
  435.         while(1)
  436.         {
  437.            //        for(i=0;i<4;i++)        
  438.         //        display(shi,fen,miao);
  439.             read_sf();
  440.             keyscan();
  441.         }
  442. }

  443. /*中断函数*/
  444. void temer1() interrupt 1
  445. {
  446.         TH0=(65536-46080)/256;
  447.         TL0=(65536-46080)%256;
  448.         ss++;
  449.         if(ss==20)
  450.                 ss=0;
  451. }         

  452. void temer2() interrupt 3
  453. {
  454.         TH1=(65536-921)/256;
  455.         TL1=(65536-921)%256;
  456.         ms++;
  457. }



复制代码

附件里面有完整的源码,仿真文件,hex文件
下载:
DS1302数码管时钟.rar (122.87 KB, 下载次数: 59)

评分

参与人数 4黑币 +64 收起 理由
linziol + 1 币少但有价值!
深蓝远景 + 8 共享资料的黑币奖励!
Gary_yuan + 5
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
ID:66429 发表于 2018-1-31 18:14 | 只看该作者
电路图分辨率有点低,有些引脚数字看不清
回复

使用道具 举报

板凳
ID:140489 发表于 2018-1-31 22:06 | 只看该作者
更正: DS1302初始化函数要按下面这样写,掉电后再上电才不会初始化时间

void init_1302()                                                        //自动初始化函数
{        
        if(read_1302(0x81)&0x80)        //读出秒数据,再跟80h(0x80)与运算看结果,结果是0则不需要初始化1302;是80h就要初始化!
                {
                write_1302(0x8e,0x00);                                //保护取消,可以进行写操作
                write_1302(write_miao,0x57);                //写秒57
                write_1302(write_fen,0x55);                        //写分55
                write_1302(write_shi,0x15);                        //写时15
                write_1302(0x8e,0x80);                                //保护启动,不能进行写操作
        }
}         
回复

使用道具 举报

地板
ID:140489 发表于 2018-1-31 22:07 | 只看该作者
xmd1972 发表于 2018-1-31 18:14
电路图分辨率有点低,有些引脚数字看不清

附件里有仿真文件的,仿真里面的电路很清晰的

评分

参与人数 1黑币 +10 收起 理由
xmd1972 + 10 很给力!

查看全部评分

回复

使用道具 举报

5#
ID:140489 发表于 2018-2-11 21:43 | 只看该作者
程序重新优化了一下,原来附件里面的程序有bug,就是第一次程序烧进去,要按设置键3次时钟才会走时,下面的程序已修改好了
  1. /*********************************************************************************
  2. 描述:
  3. 1、8位共阴数码管显示实时时钟88-88-88样式,两‘-’1秒闪烁1次
  4. 2、STC89C52 @ 11.0592MHz晶振,两片74HC573做段选、位选
  5. 3、按key1键选择调节位,按第一次,分位闪烁,按第2次,时位闪烁,按第3次,回到正常走时;
  6.    调时的时候,key2键短按加1,长按连加;key3键短按减一,长按连减;按键消抖不用delay。
  7. 4、在调时状态超过3秒再没有按键按下,回到正常走时状态(这功能不太实用,可以取消)
  8. 5、加备用电池,掉电走时
  9. 6、对时的时候先调好时、分,分钟要比参考时间的分钟加1分,
  10.    再看参考时间的秒数到了59再按KEY1按键的第3次,这样对时可以很准的。
  11.    仿真 实物都通过。
  12. **********************************************************************************/
  13. #include<reg52.h>
  14. #include<intrins.h>

  15. #define uchar unsigned char
  16. #define uint unsigned int

  17. /***********写时分秒地址************/
  18. #define write_shi  0x84
  19. #define write_fen  0x82
  20. #define write_miao 0x80
  21. //#define write_ram  0xc0
  22. /***********读时分秒地址************/
  23. #define read_shi  0x85
  24. #define read_fen  0x83
  25. #define read_miao 0x81
  26. //#define read_ram  0xc1

  27. sbit TSCLK = P1^0;//时钟线 接到P10上用杜邦线
  28. sbit TIO   = P1^1;//数据线,接到P11上
  29. sbit TRST  = P1^2;//使能端,接到P12上

  30. sbit wela = P2^7;           //位选
  31. sbit dula = P2^6;           //段选

  32. sbit key1=P3^0;             //按键 选择
  33. sbit key2=P3^1;             //按键 加
  34. sbit key3=P3^2;             //按键 减

  35. uint ms;                                //调时自动走时计时变量
  36. uchar knum=0,snum,fnum,ss;        //定义 key1按下次数变量,时分调时闪烁变量,两‘-’闪烁计时变量
  37. char shi,fen,miao;                //定义时分秒变量

  38. bit f1,f2,f3;                     //定义自动走时标志
  39.                 // 0     1    2    3    4     5    6    7    8   9   不显  -
  40. uchar code d[]={ 0x3F,0x06,0x5B,0x4F,0x66, 0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40}; //共阴不带小数点段码

  41. void delay(uint z)          //ms延时函数
  42. {
  43.         uint x,y;
  44.         for(x=z;x>0;x--)
  45.                 for(y=120;y>0;y--);
  46. }

  47. void t0_init()  //定时器初始化函数
  48. {
  49.    
  50.         TMOD |= 0X11;            //定时器0、1都为模式1, 16位计数模式
  51.         TH0=(65536-46080)/256;   //50ms初值  @11.0529MHz
  52.         TL0=(65536-46080)%256;
  53.         TH1=(65536-921)/256;         //1ms初值  @11.0529MHz
  54.         TL1=(65536-921)%256;
  55.         
  56.         EA=1;                   //开总中断
  57.         ET0=1;                  //开定时器T0中断
  58.         TR0=1;                  //启动T0
  59.         ET1=1;                  //开定时器T1中断
  60. //  TR1=1;

  61. }


  62. void display(uchar shi,uchar fen,uchar miao) //显示函数
  63. {
  64.         if(knum==0)           //正常走时
  65.         {
  66.                 snum=30;
  67.                 fnum=30;
  68.         }
  69.         
  70.         if(knum==1)           //调时,分位闪烁
  71.         {
  72.                 fnum++;
  73.                 snum=30;
  74.         }
  75.         
  76.         if(knum==2)          //调时,时位闪烁
  77.         {
  78.                 snum++;
  79.                 fnum=30;
  80.         }
  81.         
  82.         
  83.         if(snum>=30)
  84.         {        
  85.                 if((shi/10)<1)         //如果小时十位小于1,
  86.                 {
  87.                     wela=1;
  88.                     P0=0xfe;                //第1位
  89.                     wela=0;
  90.                                     P0=0x00;
  91.                     dula = 1;
  92.                     P0=d[10];           //共阴数码管段码送全0 小时十位就不显示
  93.                     dula = 0;
  94.                 }
  95.                
  96.                 else
  97.                
  98.                                 if((shi/10)>0)
  99.                                 {
  100.                     wela=1;
  101.                     P0=0xfe;          //第1位
  102.                     wela=0;
  103.                                     P0=0x00;
  104.                     dula=1;
  105.                     P0=d[shi/10];
  106.                     dula=0;
  107.                                         P0=0xff;
  108.                     delay(3);
  109.                 }

  110.                 wela=1;
  111.                 P0=0xfd;           //第2位
  112.                 wela=0;
  113.                                 P0=0x00;
  114.                 dula=1;
  115.                 P0=d[shi%10];                        
  116.                 dula=0;
  117.                                 P0=0xff;                                       
  118.                 delay(3);
  119.         
  120.                 if(snum==60)
  121.                         snum=0;
  122.         }               


  123.         //        if(miao%2==0)         //if(miao%2==0) 1秒闪烁1次
  124.         if(ss>=10)                 //        这里写为ss>=10,闪烁频率可调
  125.         {                                 
  126.             wela=1;
  127.             P0=0xfb;                //第3位
  128.             wela=0;
  129.                     P0=0x00;
  130.             dula=1;
  131.             P0=d[11];          //第三位数码管显示“— ”
  132.             dula=0;
  133.                         P0=0xff;
  134.             delay(3);
  135.         }
  136.         
  137.         else
  138.         {
  139.             wela=1;
  140.             P0=0xfb;     //第3位
  141.             wela=0;
  142.                     P0=0x00;
  143.             dula=1;
  144.             P0=d[10];         //第三位数码管不显示
  145.             dula=0;
  146.                         P0=0xff;
  147.             delay(3);        
  148.         }
  149.         
  150.         
  151.         if(fnum>=30)
  152.         {
  153.             wela=1;
  154.             P0=0xf7;         //第4位
  155.             wela=0;
  156.                         P0=0x00;
  157.             dula=1;
  158.             P0=d[fen/10];
  159.             dula=0;
  160.                         P0=0xff;
  161.             delay(3);
  162.             
  163.             
  164.             wela=1;
  165.             P0=0xef;         //第5位
  166.             wela=0;
  167.                         P0=0x00;
  168.             dula=1;
  169.             P0=d[fen%10];
  170.             dula=0;
  171.                         P0=0xff;
  172.             delay(3);
  173.    
  174.             
  175.             if(fnum==60)
  176.                     fnum=0;
  177.         }
  178.                
  179.         //        if(miao%2==0)         //if(miao%2==0) 1秒闪烁1次
  180.         if(ss>=10)                 //if(ss>=10)闪烁频率可调
  181.         {
  182.                 wela=1;
  183.                 P0=0xdf;          //第6位
  184.                 wela=0;
  185.                                 P0=0x00;
  186.                 dula=1;
  187.                 P0=d[11];          //第六位数码管显示“— ”
  188.                 dula=0;
  189.                                 P0=0xff;
  190.                 delay(3);
  191.         }
  192.         
  193.         else
  194.         {
  195.             wela=1;
  196.             P0=0xdf;                   //第6位
  197.             wela=0;
  198.                         P0=0x00;
  199.             dula=1;
  200.             P0=d[10];                  //第六位数码管不显示
  201.             dula=0;
  202.             delay(3);
  203.         }
  204.         
  205.         
  206.         wela=1;
  207.         P0=0xbf;                        //第7位
  208.         wela=0;
  209.         P0=0x00;
  210.         dula=1;
  211.         P0=d[miao/10];                //秒十位
  212.         dula=0;
  213.                 P0=0xff;
  214.         delay(3);
  215.         
  216.         
  217.         wela=1;
  218.         P0=0x7f;                         //第8位
  219.         wela=0;
  220.         P0=0x00;
  221.         dula=1;
  222.         P0=d[miao%10];                //秒个位
  223.         dula=0;
  224.                 P0=0xff;
  225.         delay(3);               
  226. }  


  227. //写DS1302数据
  228. void Write_DS1302_DAT(uchar cmd, uchar dat)
  229. {
  230.         uchar i;
  231.         TRST = 0; //拉低使能端
  232.         TSCLK = 0;//拉低数据总线
  233.         TRST = 1; //拉高使能端,产生上升沿开始写数据
  234.         for(i = 0; i < 8; i++)//每次写1位,写8次
  235.         {
  236.                 TSCLK = 0;                  //拉低时钟总线
  237.                 TIO = cmd & 0x01; //写1位数据,从最低位开始写
  238.                 TSCLK = 1;                  //拉高时钟总线,产生上升沿数据被DS1302读走
  239.                 cmd >>=1;                  //右移一位
  240.         }
  241.         for(i = 0; i < 8; i++)//每次写1位,写8次
  242.         {
  243.                 TSCLK = 0;                  //拉低时钟总线
  244.                 TIO = dat & 0x01; //写1位数据,从最低位开始写
  245.                 TSCLK = 1;                  //拉高时钟总线,产生上升沿数据被DS1302读走
  246.                 dat >>= 1;                  //右移一位
  247.         }
  248. }
  249. //读DS1302数据
  250. uchar Read_DS1302_DAT(uchar cmd)
  251. {
  252.         uchar i, dat;
  253.         TRST = 0;  //拉低使能端
  254.         TSCLK = 0; //拉低数据总线
  255.         TRST = 1;  //拉高使能端,产生上升沿开始写数据
  256.         for(i = 0; i < 8; i++)//每次写1位,写8次
  257.         {
  258.                 TSCLK = 0;                 //拉低时钟总线
  259.                 TIO = cmd & 0x01;//写1位数据,从最低位开始写
  260.                 TSCLK = 1;                 //拉高时钟总线,产生上升沿数据被DS1302读走
  261.                 cmd >>=1;                 //右移一位
  262.         }
  263.         for(i = 0; i < 8; i++)//每次读1位,读8次
  264.         {
  265.                 TSCLK = 0;                  //拉低时钟总线,产生下降沿,DS1302把数据放到TIO上
  266.                 dat >>= 1;                  //右移一位
  267.                 if(TIO)        dat |= 0x80;//读取数据,从最低位开始
  268.                 TSCLK = 1;                        //拉高时钟总线,以备下一次产生下降沿
  269.         }
  270.         return dat;        //返回读出数据
  271. }

  272. //数据转BCD码
  273. uchar Dat_Chg_BCD(uchar dat)
  274. {
  275.         uchar dat1, dat2;
  276.         dat1 = dat / 10;
  277.         dat2 = dat % 10;
  278.         dat2 = dat2 + dat1 * 16;
  279.         return dat2;
  280. }

  281. //BCD码转换为数据
  282. uchar BCD_Chg_Dat(uchar dat)
  283. {
  284.         uchar dat1, dat2;
  285.         dat1 = dat / 16;
  286.         dat2 = dat % 16;
  287.         dat2 = dat2 + dat1 * 10;
  288.         return dat2;
  289. }



  290. void init_1302()                //初始化函数 设置时间
  291. {                                                //加备用电池,掉电走时

  292.         if((Read_DS1302_DAT(0x81)& 0x80) != 0)        //读出秒数据,再跟80h(0x80)与运算看结果,结果是0则不需要初始化1302;是80h就要初始化!
  293.         {
  294.                 Write_DS1302_DAT(0x8e, 0);//清除写保护
  295.                 Write_DS1302_DAT(write_miao, Dat_Chg_BCD(58));//58秒(并且进行BCD码转换)
  296.                 Write_DS1302_DAT(write_fen, Dat_Chg_BCD(10));//10分
  297.                 Write_DS1302_DAT(write_shi, Dat_Chg_BCD(9));//9时
  298.                 Write_DS1302_DAT(0x8e, 0x80);//开写保护
  299.         }

  300. }         


  301. void read_sf()
  302. {

  303.         miao = BCD_Chg_Dat(Read_DS1302_DAT(read_miao));//读秒寄存器(并且进行BCD码转换)
  304.         fen        = BCD_Chg_Dat(Read_DS1302_DAT(read_fen));//读分寄存器
  305.         shi = BCD_Chg_Dat(Read_DS1302_DAT(read_shi));//读时寄存器
  306.         display(shi,fen,miao);
  307. }


  308. void keyscan()                        //按键扫描函数
  309. {        
  310.         static uchar count;          //这里要定义为静态变量
  311.         
  312.         if(key1==0)                          //按键按下
  313.         {        
  314.                 TR1=1;
  315.                 count++;                          //消抖,也是连加一次的间隔时间
  316.                 f1=1;
  317.                 if(key1==0 && count>10)//按键按下,计数变量加到12,
  318.                 {
  319.                         ms=0;                           //自启动计时变量清零
  320.                         while(!key1)           //这里不需要连加,就加一句松手检测
  321.                         display(shi,fen,miao);
  322.                         count=0;
  323.                         TR0=0;                           //关闭T0定时器,数码管两‘-’停止闪烁
  324.                         knum++;                           
  325.                         if(knum==1)                                                  
  326.                         {
  327.                              Write_DS1302_DAT(0x8e,0x00);                  //DS1302写保护取消
  328.                              Write_DS1302_DAT(write_miao,0x80); //写秒80,时钟停止走时;
  329.                         }
  330.                         
  331.                         if(knum==3)                                                   //调时完毕,时钟启动
  332.                         {
  333.                             TR0=1;                                                //启动T0定时器,数码管两‘-’开始闪烁
  334.                             knum=0;
  335.                             Write_DS1302_DAT(write_miao,0x00); //写秒0,时钟启动走时
  336.                             Write_DS1302_DAT(0x8e,0x80);                 //保护启动
  337.                         }
  338.                 }
  339.         }


  340.         if(knum==1)                                                                //分钟调节
  341.         {
  342.                 if(key2==0)                                                        //加
  343.                 {
  344.                         f2=1;
  345.                         count++;
  346.                         if(key2==0 && count>12)//短按加1,长按连加
  347.                         {
  348.                             ms=0;                           //自启动计时变量清零
  349.                             count=0;
  350.                             fen++;
  351.                             fen=fen/10*16+fen%10;                //转为16进制
  352.                             if(fen==0x60)
  353.                                     fen=0x00;
  354.                             Write_DS1302_DAT(write_fen,fen);        //写入1302
  355.                         }
  356.                 }
  357.                
  358.                 if(key3==0)                                                   //减
  359.                 {
  360.                         f3=1;
  361.                         count++;
  362.                         if(key3==0 && count>12)//短按减1,长按连减
  363.                         {
  364.                             ms=0;                           //自启动计时变量清零
  365.                             count=0;
  366.                             fen--;
  367.                             fen=fen/10*16+fen%10;                //转为16进制
  368.                             if(fen==-1)
  369.                                     fen=0x59;
  370.                             Write_DS1302_DAT(write_fen,fen);
  371.                         }
  372.                 }
  373.         }
  374.         
  375.         
  376.         if(knum==2)                                                          //小时调节
  377.         {
  378.                 if(key2==0)
  379.                 {        
  380.                         f2=1;
  381.                         count++;
  382.                         if(key2==0 && count>12 )//短按加1,长按连加
  383.                         {
  384.                             ms=0;                                //自启动计时变量清零
  385.                             count=0;
  386.                             shi++;
  387.                             shi=shi/10*16+shi%10;//转为16进制
  388.                             if(shi==0x24)
  389.                                     shi=0x00;
  390.                             Write_DS1302_DAT(write_shi,shi);
  391.                         }
  392.                 }
  393.                
  394.                
  395.                 if(key3==0)
  396.                 {
  397.                         f3=1;
  398.                         count++;
  399.                         if(key3==0 && count>12 )//短按减1,长按连减
  400.                         {        
  401.                             ms=0;                                //自启动计时变量清零
  402.                             count=0;
  403.                             shi--;
  404.                             shi=shi/10*16+shi%10;//转为16进制
  405.                             if(shi==-1)
  406.                                     shi=0x23;
  407.                             Write_DS1302_DAT(write_shi,shi);
  408.                         }
  409.                 }
  410.         }

  411. /*按键超过3秒没有动作,时钟回到走时状态*///这段加上,秒调不精确,因为超过3秒没有按键按下,秒就清0开始走时了。

  412. /*        if(f1==1 || f2==1 || f3==1)
  413.         {
  414.                 if(ms>3000)          //时间超过3秒
  415.                 {
  416.                     TR1=0;          //关闭T1
  417.                     ms=0;          //自启动计时变量清零
  418.                     knum=0;          //key1按键次数清零
  419.                     TR0=1;          //启动T0,数码管两‘-’开始闪烁
  420.                     Write_DS1302_DAT(write_miao,0x00); //写秒0,时钟启动走时
  421.                     Write_DS1302_DAT(0x8e,0x80);                 //保护启动
  422.                 }
  423.         
  424.         }  */
  425. }           

  426. /*主函数*/
  427. void main()
  428. {
  429.         t0_init();
  430.         init_1302();                          
  431.         while(1)
  432.         {
  433.             read_sf();
  434.             keyscan();
  435.         }
  436. }

  437. /*中断函数*/
  438. void temer1() interrupt 1
  439. {
  440.         TH0=(65536-46080)/256;
  441.         TL0=(65536-46080)%256;
  442.         ss++;
  443.         if(ss==20)
  444.                 ss=0;
  445. }         

  446. void temer2() interrupt 3
  447. {
  448.         TH1=(65536-921)/256;
  449.         TL1=(65536-921)%256;
  450.         ms++;
  451. }
复制代码
回复

使用道具 举报

6#
ID:288444 发表于 2018-4-15 11:36 来自手机 | 只看该作者
照你改的怎么编译说write_miao.fen.shi未定义
回复

使用道具 举报

7#
ID:437276 发表于 2018-12-3 17:14 | 只看该作者
write_miao.fen.shi未定义求楼主回复
回复

使用道具 举报

8#
ID:140489 发表于 2019-3-6 09:52 | 只看该作者
上面的代码全部复制,编译通过的,
compiling 111.c...
linking...
Program Size: data=19.3 xdata=0 code=1236
creating hex file from "111"...
"111" - 0 Error(s), 0 Warning(s).
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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