找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于DS1302的电子时钟制作

  [复制链接]
跳转到指定楼层
楼主

资料下载:
大时钟【原理图】.PDF (119.6 KB, 下载次数: 89)
大时钟【源程序】.zip (75.04 KB, 下载次数: 101)


  1. /*        项目名称:多功能数码管时钟设计
  2.         调试要求:
  3.         1.MCU:STC89C51
  4.         2.晶振:12MHz
  5.         功能:实时时钟+温度计+闹钟+整点报时+正计时器+倒计时器+计数器*/
  6. #include <reg52.h>
  7. #include <intrins.h>
  8. #define uchar unsigned char
  9. #define uint  unsigned int
  10. #define smg_data    P0//定义数码管数据

  11. sbit smg1=P2^4;//位码1声明 时
  12. sbit smg2=P2^5;//位码2声明
  13. sbit smg3=P2^6;//位码3声明 分
  14. sbit smg4=P2^7;//位码4声明
  15. sbit smg5=P1^6;//位码5声明 秒
  16. sbit smg6=P1^7;//位码6声明
  17. sbit gm=P1^3; //黑暗时等于1
  18. sbit k1=P1^2; //按键k1的声明
  19. sbit k2=P1^1; //按键k2的声明
  20. sbit k3=P1^0; //按键k3的声明

  21. sbit bell=P3^7;        //蜂鸣器声明
  22. sbit clk_ds1302=P2^0;//定义控制DS1302的时钟线
  23. sbit io_ds1302=P2^1;//定义控制DS1302的串行数据
  24. sbit rest_ds1302=P2^2;

  25. const uchar tab1[16]={//共阳数码管段码表
  26. 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x86,0x87,0xFF,0xc6,0xbf,0xff};
  27. //0        ,1        ,2        ,3        ,4        ,5        ,6        ,7        ,8        ,9        ,                       
  28. const uchar tab2[16]={//数码管3特殊处理用的段码表
  29. 0xc0,0xf9,0x64,0x70,0x59,0x52,0x42,0xf8,0x40,0x50,0x86,0x87,0xFF,0xc6,0x7f,0xff};
  30.                         //    C      -
  31. bit gm_en=0,zdbs_en=0;//光敏使能信号/整点报时使能信号
  32. uchar gm_time=40; //光敏控制亮度值
  33. char shi,fen,miao,b_shi=7,b_fen=0; //必须是有符号型:数据暂存单元shi/fen/miao,闹铃时间b_shi,b_fen,
  34. uchar hour,minute,second,n=0,a=0,b=0;//从1302读出的实时时间数据hour,minute,second,        b控制字符闪烁
  35. uchar tab23[3];//={0x40,0x59,0x23,0x28,0x11,0x06,0x09};//首次上电时默认的时间
  36. uchar bell_en=0,x=1;//闹钟使能信号,任意键关闭铃声标志位
  37. char zjs_en=0,zjs_shi=0,zjs_fen=0,djs_en=0,djs_shi=60,djs_fen=0,jsq_shi=0,jsq_fen=0;
  38. void key();
  39. void  delay_3us();//3US的延时程序
  40. void  delay_50us(uint t);//延时50*T微妙函数的声明
  41. void  display(uchar shi,fen,miao);//显示子程序
  42. void  set_ds1302();//设置时间
  43. void  get_ds1302();//读取当前时间
  44. void  w_1byte_ds1302(uchar t);//向DS1302写一个字节的数据
  45. uchar r_1byte_ds1302();//从DS1302读一个字节的数据
  46. void init(); //初始化函数

  47. void baojing()//报警函数
  48. {
  49.          uint j=10,i=10;
  50.          bell=0;
  51.          while(i--)display(shi,fen,miao);
  52.          bell=1;
  53.          while(j--)display(shi,fen,miao);
  54. }

  55. /******温度传感器18b20  IO引脚定义********/
  56. sbit DS=P2^3;           //定义DS18B20接口
  57. uchar ly_dis[4];                //定义显示温度的缓冲区
  58. float tt;                        //定义浮点型变量tt存放温度值
  59. uchar temp_en=0;
  60. uchar wendu=0;
  61. uint t=0;

  62. /**********18b20延时子函数 *************/
  63. void delayb(uint count)
  64. {
  65.   uint i;
  66.   while(count)
  67.   {
  68.     i=200;
  69.     while(i>0)
  70.     i--;
  71.     count--;
  72.   }
  73. }

  74. /*********DS18B20初始化************/
  75. void dsreset(void)
  76. {
  77.   uint i;
  78.   DS=0;
  79.   i=103;
  80.   while(i>0)i--;
  81.   DS=1;
  82.   i=4;
  83.   while(i>0)i--;
  84. }

  85. /**********18b20读一位***********/
  86. bit tmpreadbit(void)
  87. {
  88.    uint i;
  89.    bit dat;
  90.    DS=0;
  91.    i++;          //小延时一下
  92.    DS=1;
  93.    i++;i++;
  94.    dat=DS;
  95.    i=8;
  96.    while(i>0)i--;
  97.    return (dat);
  98. }

  99. /**********18b20读一个**********/
  100. uchar tmpread(void)
  101. {
  102.   uchar i,j,dat;
  103.   dat=0;
  104.   for(i=1;i<=8;i++)
  105.   {
  106.     j=tmpreadbit();
  107.     dat=(j<<7)|(dat>>1);   //读出的数据最低位在最前面,这样刚好//一个字节在DAT里
  108.   }
  109.   return(dat);             //将一个字节数据返回
  110. }

  111. /**********18b20写一个字节**********/
  112. void tmpwritebyte(uchar dat)
  113. {
  114.   uint i;
  115.   uchar j;
  116.   bit testb;
  117.   for(j=1;j<=8;j++)
  118.   {
  119.     testb=dat&0x01;
  120.     dat=dat>>1;
  121.     if(testb)     // 写1部分
  122.     {
  123.       DS=0;
  124.       i++;i++;
  125.       DS=1;
  126.       i=8;
  127.           while(i>0)i--;
  128.     }
  129.     else
  130.     {
  131.       DS=0;       //写0部分
  132.       i=8;
  133.           while(i>0)i--;
  134.       DS=1;
  135.       i++;i++;
  136.     }
  137.   }
  138. }

  139. /***********18b20发送温度转换命令*************/
  140. void tmpchange(void)
  141. {
  142.   dsreset();             //初始化DS18B20
  143.   delayb(1);             //延时
  144.   tmpwritebyte(0xcc);  // 跳过序列号命令
  145.   tmpwritebyte(0x44);  //发送温度转换命令
  146. }

  147. /***********获得温度************/
  148. int tmp()
  149. {
  150.   int temp;
  151.   uchar a,b;
  152.   dsreset();
  153.   delayb(1);

  154.   tmpwritebyte(0xcc);  
  155.   tmpwritebyte(0xbe);   //发送读取数据命令

  156.   a=tmpread();          //连续读两个字节数据
  157.   b=tmpread();
  158.   temp=b;
  159.   temp<<=8;
  160.   temp=temp|a;                 //两字节合成一个整型变量。
  161.   return temp;     //返回温度值
  162. }
  163. void dis_temp()
  164. {        
  165.         tmpchange();              //温度转换
  166.         tt=tmp()*0.0625;          //得到真实十进制温度值,因为DS18B20
  167.         wendu=tt;                                                                //可以精确到0.0625度,所以读回数据的最低位代表的是0.0625度。
  168.         if(tt<0)        //判断第一位显示整数还是负号
  169.         tt=0;        
  170.         if((wendu%100/10)<1) //如果温度小于10,不显示十位
  171.         smg1=1;
  172.         else
  173.         {
  174.                 smg_data=tab1[wendu%100/10];//送显示断码  十位
  175.                 smg1=0;
  176.                 delay_50us(gm_time);
  177.                 smg1=1;
  178.         }
  179.         smg_data=tab1[wendu%10];//送显示断码  个位
  180.         smg2=0;
  181.         delay_50us(gm_time);
  182.         smg2=1;
  183.         smg_data=tab1[10];//送显示断码  ℃
  184.         smg3=0;
  185.         delay_50us(gm_time);
  186.         smg3=1;        
  187.         smg4=1;
  188. }
  189. //***********************************************************************
  190. //主程序
  191. void main()
  192. {        
  193.         tmpchange();              //温度转换,为了消除首次显示的85,每次提前转换一次即可解决
  194.     init();
  195.         gm=1;
  196.         while(1)
  197.     {        
  198.                 if(n==0&&temp_en==1)
  199.                 dis_temp();//每15秒切换显示温度一次
  200.                 else
  201.                 {
  202.                         get_ds1302();
  203.                         display(shi,fen,miao);
  204.                         key();
  205.                         if(n==0&&x==1&&bell_en==1&&b_shi==hour&&b_fen==minute)
  206.                         baojing();
  207.                         if(hour==b_shi&&minute==b_fen+1)x=1;
  208.                 }
  209.                 if(gm_en==1)//光敏控制亮度开关
  210.                 {
  211.                         if(gm==1)
  212.                         gm_time=1;
  213.                         else gm_time=40;
  214.                 }
  215.                 else gm_time=40;
  216.                 if(zdbs_en==1&&n==0&&minute==0&&miao==0)//整点报时开关
  217.                 baojing();                                                                 
  218.     }
  219. }

  220. //数码管显示程序
  221. void  display(uchar s,f,m)
  222. {
  223.    if((s/10)<1) smg1=1;
  224.    else
  225.    {
  226.            smg_data=tab1[s/10];//送显示断码  时
  227.            if((n==1||n==3)&&a<5)
  228.            smg1=1;//锁存数据
  229.            else smg1=0;
  230.            delay_50us(gm_time);
  231.            smg1=1;        
  232.    }

  233.    if((n==1||n==3)&&a<5)        smg_data=0x7f; //字符闪烁,小点不闪
  234.    else if(b>=10)                        smg_data=tab1[s%10]-0x80;//小点闪烁,字符不闪
  235.    else                                         smg_data=tab1[s%10];//送显示断码
  236.    smg2=0;
  237.    delay_50us(gm_time);
  238.    smg2=1;

  239.    if((n==2||n==4)&&a<5)         smg_data=0xbf;//b是控制小数点闪烁的,需要闪烁的时候他等于a
  240.    else if(b>=10)                        smg_data=tab2[f/10]&0xbf; //显示小点//送显示断码
  241.    else                                                smg_data=tab2[f/10];//送显示断码         分
  242.    smg3=0;//锁存数据
  243.    delay_50us(gm_time);
  244.    smg3=1;         

  245.    if(bell_en==1)         smg_data=tab1[f%10]-0x80;//送显示断码
  246.    else                         smg_data=tab1[f%10];//送显示断码
  247.    if((n==2||n==4)&&a<5)
  248.    smg4=1;//锁存数据
  249.    else smg4=0;
  250.    delay_50us(gm_time);
  251.    smg4=1;
  252. /**************秒,不需要显示********************/   
  253.    smg_data=tab2[m/10];//送显示断码   秒
  254.    smg5=0;//锁存数据
  255.    delay_50us(40);
  256.    smg5=1;

  257.    smg_data=tab1[m%10];//送显示断码
  258.    smg6=0;//锁存数据
  259.    delay_50us(40);
  260.    smg6=1;
  261. /*********************************************/

  262. }
  263. void key() //按键控制函数
  264. {
  265.         if(k2==0&&k3==0) //k2k3同时按下,切换闹铃开关 并且在按下之后查看闹钟时间松手后恢复时间显示
  266.         {
  267.                 delay_50us(1);
  268.                 if(k2==0&&k3==0)
  269.                 {        
  270.                         shi=b_shi;
  271.                         fen=b_fen;
  272.                         bell_en=!bell_en;
  273.                         baojing();
  274.                         baojing();
  275.                         while(k2==0&&k3==0)display(shi,fen,miao);//等待松手
  276.                         shi=hour;
  277.                         fen=minute;
  278.                 }
  279.         }
  280.         
  281.         if(k1==0&&k3==0) //k1k3同时按下,切换闹铃开关 并且在按下之后查看闹钟时间松手后恢复时间显示
  282.         {
  283.                 delay_50us(1);
  284.                 if(k1==0&&k3==0)
  285.                 {        
  286.                         gm_en=!gm_en;
  287.                         if(gm_en==1)//使能的话报警两声
  288.                         {baojing();baojing();}
  289.                         else baojing();//无效的话报警一声
  290.                         while(k1==0&&k3==0)display(shi,fen,miao);//等待松手
  291.                 }
  292.         }
  293.         if(k1==0&&k2==0) //k1k2同时按下,切换整点报时开关
  294.         {
  295.                 delay_50us(1);
  296.                 if(k1==0&&k2==0)
  297.                 {        
  298.                         zdbs_en=!zdbs_en;
  299.                         if(zdbs_en==1)//使能的话报警两声
  300.                         {baojing();baojing();}
  301.                         else baojing();//无效的话报警一声        
  302.                         while(k1==0&&k2==0)display(shi,fen,miao);//等待松手
  303.                 }
  304.         }
  305.         if(n==0&&(k2==0||k3==0)&&bell_en==1&&b_shi==hour&&b_fen==minute&&x==1)
  306.         { //功能键k1被按下
  307.                 delay_50us(1);//消抖延时
  308.                 if(n==0&&(k2==0||k3==0)&&bell_en==1&&b_shi==hour&&b_fen==minute&&x==1)
  309.                 {        
  310.                         x=0;   //如果处于响零状态,就任意键关闭响铃
  311.                         while(k1==0)display(shi,fen,miao);//等待松手
  312.                 }
  313.         }
  314.         if(k1==0)
  315.         { //功能键k1被按下
  316.                 delay_50us(1);//消抖延时
  317.                 if(k1==0)
  318.                 {        
  319.                         uint i=0;
  320.                         while(k1==0)
  321.                         {
  322.                                 display(shi,fen,miao);//等待松手
  323.                                 i++;
  324.                                 if(i>(2*(70-gm_time))){n=0;baojing();baojing();break;}//长按K1退出
  325.                         }
  326.                         if(bell_en==1&&b_shi==hour&&b_fen==minute&&x==1)x=0;   //如果处于响零状态,就任意键关闭响铃
  327.                         else if(i<=(2*(70-gm_time)))
  328.                         {
  329.                                 n++;//n记录功能键状态
  330.                                 if(n>7)  n=0; //n清零
  331.                                 baojing();        
  332.                         }
  333.                         i=0;                        
  334.                 }
  335.         }

  336.         if(n==0)//状态0,正常显示时间
  337.         {
  338.                 b=a; //b是控制小数点闪烁的
  339.                 shi=hour;
  340.                 fen=minute;
  341.                 miao=second;
  342.         }        
  343.         if(n==1)//状态1:调节时间的“时”
  344.         {
  345.                 b=10;
  346.                 if(k2==0)
  347.                 { //k2被按下
  348.                         uint i=6,j=10;
  349.                         while(i--)display(shi,fen,miao);//长按连续递减                        
  350.                         if(k2==0)
  351.                         {
  352.                                 shi++;//小时加一
  353.                                 if(shi==24)
  354.                                 shi=0;//达到24清零        
  355.                         }
  356.                          while(j--)display(shi,fen,miao);//长按连续递减
  357.                 }
  358.                
  359.                 if(k3==0)
  360.                 {  //k3被按下
  361.                         uint i=6,j=10;
  362.                         while(i--)display(shi,fen,miao);//长按连续递减        
  363.                         if(k3==0)
  364.                         {
  365.                                 shi--; //小时减一
  366.                                 if(shi<0)
  367.                                 shi=23;//小于0,重新复制
  368.                         }
  369.                         while(j--)display(shi,fen,miao);//长按连续递减
  370.                 }               
  371.         }
  372.         if(n==2)//状态2:调节时间的“分”
  373.         {        b=10;
  374.                  if(k2==0)
  375.                 { //k2被按下
  376.                         uint i=6,j=10;
  377.                         while(i--)display(shi,fen,miao);//长按连续递减
  378.                         if(k2==0)
  379.                         {
  380.                                 fen++;//分加一
  381.                                 if(fen==60)
  382.                                 fen=0;//分到达60 分清零        
  383.                         }        
  384.                         while(j--)display(shi,fen,miao);//长按连续递减
  385.                 }
  386.                
  387.                 if(k3==0)
  388.                 {  //k3被按下
  389.                         uint i=6,j=10;
  390.                         while(i--)display(shi,fen,miao);//长按连续递减
  391.                         if(k3==0)
  392.                         {
  393.                                 fen--;//分减一
  394.                                 if(fen<0)
  395.                                 fen=59;//分小于0,分重新赋值59                                          
  396.                         }
  397.                         while(j--)display(shi,fen,miao);//长按连续递减
  398.                 }
  399.                 tab23[2]=shi/10*16+shi%10;
  400.         tab23[1]=fen/10*16+fen%10;
  401.         hour=shi;
  402.         minute=fen;
  403.         second=0;
  404.         tab23[0]=0;
  405.         set_ds1302();//设置DS1302的初始时间               
  406.         }
  407.         
  408.         if(n==3)//状态三:调节闹铃“时”
  409.         {        
  410.                 shi=b_shi;
  411.                 fen=b_fen;
  412.                 b=10;
  413.                 if(k2==0)
  414.                 {  //k2被按下
  415.                         uint i=6,j=10;
  416.                         while(i--)display(shi,fen,miao);//长按连续递减
  417.                         if(k2==0)
  418.                         {
  419.                                 b_shi++;//闹铃时间加一
  420.                                 if(b_shi==24)
  421.                                 b_shi=0;//闹铃时间清零        
  422.                         }
  423.                         while(j--)display(shi,fen,miao);//长按连续递减
  424.                 }
  425.                
  426.                 if(k3==0)
  427.                 {  //k3被按下
  428.                         uint i=6,j=10;
  429.                         while(i--)display(shi,fen,miao);//长按连续递减
  430.                         if(k3==0)
  431.                         {
  432.                                 b_shi--;//闹铃时间减一
  433.                                 if(b_shi<0)
  434.                                 b_shi=23;//闹铃时间        
  435.                         }
  436.                         while(j--)display(shi,fen,miao);//长按连续递减
  437.                 }               
  438.         }

  439.         if(n==4)//状态四 :调节闹铃的”分“
  440.         {        b=10;
  441.         shi=b_shi;
  442.                 fen=b_fen;
  443.                 if(k2==0)
  444.                 {  //k2被按下
  445.                         uint i=6,j=10;
  446.                         while(i--)display(shi,fen,miao);//长按连续递减
  447.                         if(k2==0)
  448.                         {
  449.                                 b_fen++;//闹铃时间分加一
  450.                                 if(b_fen==60)
  451.                                 b_fen=0;//闹铃分到达60 清零        
  452.                         }        
  453.                         while(j--)display(shi,fen,miao);//长按连续递减
  454.                 }
  455.                
  456.                 if(k3==0)
  457.                 {  //k3被按下
  458.                         uint i=6,j=10;
  459.                         while(i--)display(shi,fen,miao);//长按连续递减
  460.                         if(k3==0)
  461.                         {
  462.                                 b_fen--;//闹铃时间分减一
  463.                                 if(b_fen<0)
  464.                                 b_fen=59;//闹铃时间分重新赋值
  465.                         }
  466.                         while(j--)display(shi,fen,miao);//长按连续递减                        
  467.                 }               
  468.         }
  469.         if(n==5)//状态5 :正计时
  470.         {
  471.                 b=10; //显示小点
  472.                 shi=zjs_shi;
  473.                 fen=zjs_fen;
  474.                 if(k2==0)
  475.                 {  //k2被按下
  476.                         delay_50us(1);//消抖延时
  477.                         if(k2==0)
  478.                         {        
  479.                                 zjs_en=!zjs_en;        
  480.                                 baojing();
  481.                                 while(k2==0)display(shi,fen,miao);//等待松手
  482.                         }
  483.                 }
  484.                
  485.                 if(k3==0)
  486.                 {  //k3被按下
  487.                         delay_50us(1);//消抖延时
  488.                         if(k3==0)
  489.                         {
  490.                                 zjs_shi=0;
  491.                                 zjs_fen=0;
  492.                                 baojing();
  493.                                 while(k3==0)display(shi,fen,miao);//等待松手        
  494.                         }
  495.                 }               
  496.         }
  497.         if(n==6)//状态5 :倒计时
  498.         {        b=10; //显示小点
  499.         shi=djs_shi;
  500.                 fen=djs_fen;
  501.                 if(k2==0)
  502.                 {  //k2被按下
  503.                         delay_50us(1);//消抖延时
  504.                         if(k2==0)
  505.                         {        
  506.                                 djs_en=!djs_en;        
  507.                                 baojing();
  508.                                 while(k2==0)display(shi,fen,miao);//等待松手
  509.                         }
  510.                 }
  511.                
  512.                 if(k3==0&&djs_en==0)
  513.                 {  //k3被按下
  514.                         uint i=6,j=10;
  515.                         while(i--)display(shi,fen,miao);//长按连续递减
  516.                         if(k3==0)
  517.                         {
  518.                                 djs_shi--;
  519.                                 if(djs_shi<0)
  520.                                 djs_shi=60;               
  521.                         }
  522.                         while(j--)display(shi,fen,miao);//长按连续递减
  523.                 }
  524.                 if(k3==0&&djs_en==1)
  525.                 {  //k3被按下
  526.                         delay_50us(1);//消抖延时
  527.                         if(k3==0)
  528.                         {
  529.                                 djs_shi=60;
  530.                                 djs_fen=0;
  531.                                 baojing();
  532.                                 while(k3==0)display(shi,fen,miao);//等待松手        
  533.                         }
  534.                 }               
  535.         }
  536.         if(n==7)//状态5 :计数器
  537.         {        
  538.                 b=1; //不显示小点
  539.                 shi=jsq_shi;
  540.                 fen=jsq_fen;
  541.         
  542.                 if(k2==0)
  543.                 {  
  544.                         uint i=6,j=10;
  545.                         while(i--)display(shi,fen,miao);//长按连续递减
  546.                         if(k2==0)
  547.                         {
  548.                                 jsq_fen++;
  549.                                 if(jsq_fen>99)
  550.                                 {
  551.                                         jsq_fen=0;
  552.                                         jsq_shi++;
  553.                                         if(jsq_shi>99)
  554.                                         jsq_shi=0;
  555.                                 }                        
  556.                         }
  557.                         while(j--)display(shi,fen,miao);//长按连续递减
  558.                 }
  559.                 if(k3==0)
  560.                 {  //k3被按下
  561.                         delay_50us(1);//消抖延时
  562.                         if(k3==0)
  563.                         {
  564.                                 jsq_shi=0;
  565.                                 jsq_fen=0;
  566.                                 baojing();
  567.                                 while(k3==0)display(shi,fen,miao);//等待松手        
  568.                         }
  569.                 }               
  570.         }                        
  571. }
  572. void init()        //初始化函数
  573. {
  574.         IE=0X82;//1000 0010
  575.         TMOD=0X01;    //0000 0001选择定时器0的工作方式1        选择定时器1的工作方式1
  576.         TH0=(65536-50000)/256;//初值15536定时50mS
  577.         TL0=(65536-50000)%256;
  578.         TR0=1; //开启定时器0
  579. }

  580. void timer0() interrupt        1  //定时器0中断服务程序,用来设置冒号闪烁频率
  581. {
  582.         TH0=(65536-50000)/256;//进入中断重新赋初值15536
  583.         TL0=(65536-50000)%256;//计数5万次(50毫秒)
  584.         a++; //标志位b,用来确定光标闪烁频率
  585.         t++;
  586.         if(t==300)t=0;
  587.         if(t>260)temp_en=1;
  588.         else temp_en=0;
  589.         
  590.         if(a==20)
  591.         {        
  592.                 a=0;//a=20 时被清零        
  593.                 if(zjs_en==1)        //正计时
  594.                 {
  595.                         zjs_fen++;
  596.                         if(zjs_fen==60)
  597.                         {
  598.                                 zjs_fen=0;
  599.                                 zjs_shi++;
  600.                                 if(zjs_shi==60)
  601.                                 {
  602.                                         zjs_shi=0;        
  603.                                 }
  604.                         }        
  605.                 }
  606.                 /**********倒计时**********/
  607.                 if(djs_en==1)
  608.                 {
  609.                         djs_fen--;
  610.                         if(djs_fen==-1)
  611.                         {
  612.                                 djs_fen=59;
  613.                                 djs_shi--;
  614.                                 if(djs_shi==-1)
  615.                                 {
  616.                                         djs_shi=0;
  617.                                         djs_fen=0;
  618.                                         djs_en=0;//关闭倒计时
  619.                                         baojing();
  620.                                 baojing();
  621.                                 baojing();
  622.                                 }
  623.                         }        
  624.                 }
  625.                 /*************************/
  626.         }
  627. }


  628. //函数名称:void delay_50US(unsigned int t)
  629. //功能: 延时50*t(us)
  630. void delay_50us(uint t)
  631. {
  632.   unsigned char j;
  633.   for(;t>0;t--)
  634.   {
  635.     for(j=19;j>0;j--);
  636.   }
  637. }
  638. //*******************************************************************************

  639. //*******************************************************************************
  640. //3微秒延时程序
  641. void delay_3us()
  642. {
  643.   ;
  644.   ;
  645. }


  646. //;##############################################################################
  647. //;子程序名:w_1byte_ds1302
  648. //;功能:    向DS1302写一个字节的数据
  649. void w_1byte_ds1302(uchar t)
  650. {
  651.   uchar i;
  652.   for(i=0;i<8;i++)
  653.   {
  654.     if(t & 0x01)
  655.      {io_ds1302=1;}
  656.     else
  657.      {io_ds1302=0;}
  658.     clk_ds1302=1;
  659.     delay_3us();
  660.     delay_3us();
  661.     clk_ds1302=0;
  662.     delay_3us();
  663.     delay_3us();
  664.     t>>=1;
  665.   }  
  666. }
  667. //;########################################################################
  668. //;子程序名:r_1byte_ds1302()
  669. //;功能:    从DS1302读一个字节的数据
  670. uchar r_1byte_ds1302()
  671. {
  672.   uchar i,temp11=0;
  673.   io_ds1302=1;//置IO为1,准备读入数据
  674.   for(i=0;i<8;i++)
  675.   {
  676.     temp11>>=1;
  677.     if(io_ds1302) temp11 |= 0x80;
  678.     clk_ds1302=1;
  679.     delay_3us();
  680.     delay_3us();
  681.     clk_ds1302=0;
  682.     delay_3us();
  683.   }
  684.   return(temp11);
  685. }  
  686. //;#################################################################################
  687. //;子程序名:setbds1302
  688. //;功能:   设置DS1302初始时间,并启动计时
  689. void set_ds1302()
  690. {
  691.   uchar i,j;
  692.   rest_ds1302=0;
  693.   delay_3us();
  694.   clk_ds1302=0;
  695.   delay_3us();
  696.   rest_ds1302=1;
  697.   delay_3us();
  698.   w_1byte_ds1302(0x8e);//写控制命令字
  699.   delay_3us();
  700.   w_1byte_ds1302(0x00);//写保护关闭
  701.   clk_ds1302=1;
  702.   delay_3us();
  703.   rest_ds1302=0;
  704.   for(i=0,j=0x80;i<7;i++,j+=2)
  705.   {
  706.     rest_ds1302=0;
  707.     delay_3us();
  708.     clk_ds1302=0;
  709.     delay_3us();
  710.     rest_ds1302=1;
  711.     delay_3us();
  712.     w_1byte_ds1302(j);
  713.     delay_3us();
  714.     w_1byte_ds1302(tab23[i]);
  715.     delay_3us();
  716.     delay_3us();
  717.     clk_ds1302=1;
  718.     delay_3us();
  719.     rest_ds1302=0;
  720.     delay_3us();
  721.     delay_3us();
  722.   }
  723.   rest_ds1302=0;
  724.   delay_3us();
  725.   clk_ds1302=0;
  726.   delay_3us();
  727.   rest_ds1302=1;
  728.   delay_3us();
  729.   w_1byte_ds1302(0x8e);
  730.   delay_3us();
  731.   w_1byte_ds1302(0x80);
  732.   clk_ds1302=1;
  733.   delay_3us();
  734.   rest_ds1302=0;
  735.   delay_3us();
  736. }  
  737. //;#################################################################-------
  738. //;子程序名:get1302
  739. void get_ds1302()
  740. {  uchar hour_count,minute_count,second_count;
  741.    uchar temp11[7],i,j;
  742.    for(i=0;i<7;i++)
  743.    {temp11[i]=0;}
  744.    for(i=0,j=0x81;i<7;i++,j+=2)
  745.    {  
  746.     rest_ds1302=0;
  747.     delay_3us();
  748.     clk_ds1302=0;
  749.     delay_3us();
  750.     rest_ds1302=1;
  751.     delay_3us();
  752.     w_1byte_ds1302(j);
  753.     temp11[i]=r_1byte_ds1302();
  754.     delay_3us();
  755.     clk_ds1302=1;
  756.     delay_3us();
  757.     rest_ds1302=0;
  758.     delay_3us();
  759.   }
  760.   if(temp11[0]!=0xff)
  761.   {second_count=temp11[0];}
  762.   if(temp11[1]!=0xff)// 数据验证
  763.   {minute_count=temp11[1];}
  764.   if(temp11[2]!=0xff)//数据验证
  765.   {hour_count=temp11[2];}
  766.          hour=hour_count/16*10+hour_count%16;
  767.         minute=minute_count/16*10+minute_count%16;
  768.         second=second_count/16*10+second_count%16;
  769.           /*zancun4=hour_count&0xf0;
  770.           zancun4>>=4;
  771.           zancun5=minute_count&0xf0;
  772.           zancun5>>=4;
  773.           zancun6=second_count&0xf0;
  774.           zancun6>>=4;*/
  775. }
复制代码



评分

参与人数 2黑币 +58 收起 理由
slhslhhao + 8 很给力!
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
ID:104838 发表于 2016-12-5 21:21 | 只看该作者
支持下需要,51黑有你更精彩!!!
回复

使用道具 举报

板凳
ID:153199 发表于 2017-1-2 13:57 | 只看该作者
51黑有你更精彩
回复

使用道具 举报

地板
ID:159748 发表于 2017-1-16 23:59 | 只看该作者
下載玩玩感謝你...
回复

使用道具 举报

5#
ID:161488 发表于 2017-1-17 10:42 | 只看该作者
好东西,可以做一做,有没有原件和封装库
回复

使用道具 举报

6#
ID:161822 发表于 2017-1-17 13:16 | 只看该作者

不错,收下了,谢谢!
回复

使用道具 举报

7#
ID:89286 发表于 2017-1-18 22:47 | 只看该作者
thanks for sharing
回复

使用道具 举报

8#
ID:151661 发表于 2017-1-20 23:47 来自手机 | 只看该作者
很厉害。
回复

使用道具 举报

9#
ID:162689 发表于 2017-1-22 10:46 | 只看该作者
六位更好。。。。
回复

使用道具 举报

10#
ID:143822 发表于 2017-1-27 16:48 | 只看该作者
为啥重影
回复

使用道具 举报

11#
ID:158729 发表于 2017-1-28 19:57 | 只看该作者
楼主厉害,感谢分享
回复

使用道具 举报

12#
ID:143822 发表于 2017-1-29 13:53 来自手机 | 只看该作者
第三段,h一直在闪是怎么回事
回复

使用道具 举报

13#
ID:143822 发表于 2017-1-30 06:44 来自手机 | 只看该作者
if((n==2||n==4)&&a<5)         smg_data=0xff;//b是控制小数点闪烁的,需要闪烁的时候他等于a    else if(b>=10)                        smg_data=tab1[f/10]; //显示小点//送显示断码    else                                                smg_data=tab1[f/10];//送显示断码         分    smg3=0;//锁存数据    delay_50us(gm_time);    smg3=1;  
回复

使用道具 举报

14#
ID:141497 发表于 2017-2-1 22:31 | 只看该作者
学习一下,看看你的编程思路
回复

使用道具 举报

15#
ID:148496 发表于 2017-3-4 19:40 | 只看该作者
开玩笑 stc89C51 能装下11k的程序:?
回复

使用道具 举报

16#
ID:166064 发表于 2017-3-28 20:31 | 只看该作者
谢谢分享,正在好一个。
回复

使用道具 举报

17#
ID:258542 发表于 2017-12-7 11:15 | 只看该作者
学习了  最近在也正好在仿照这个
回复

使用道具 举报

18#
ID:99341 发表于 2017-12-9 16:34 | 只看该作者
楼主这个程序有问题,能不能重新发个能用的烧写文件
回复

使用道具 举报

19#
ID:168148 发表于 2017-12-27 18:58 来自手机 | 只看该作者
学习学习!!
回复

使用道具 举报

20#
ID:261637 发表于 2018-1-6 00:49 | 只看该作者
编译不过?RAMSIZE(256)
*** WARNING L15: MULTIPLE CALL TO SEGMENT
    SEGMENT: ?PR?BAOJING?DSZ
    CALLER1: ?C_C51STARTUP
    CALLER2: ?PR?TIMER0?DSZ
*** WARNING L15: MULTIPLE CALL TO SEGMENT
    SEGMENT: ?PR?_DISPLAY?DSZ
    CALLER1: ?C_C51STARTUP
    CALLER2: ?PR?TIMER0?DSZ
******************************************************************************
* RESTRICTED VERSION WITH 0800H BYTE CODE SIZE LIMIT; USED: 0B63H BYTE (142%) *
******************************************************************************
Program Size: data=100.3 xdata=0 code=3805
LINK/LOCATE RUN COMPLETE.  2 WARNING(S),  0 ERROR(S)
*** WARNING L15: MULTIPLE CALL TO SEGMENT
    SEGMENT: ?PR?BAOJING?DSZ
    CALLER1: ?C_C51STARTUP
    CALLER2: ?PR?TIMER0?DSZ
*** WARNING L15: MULTIPLE CALL TO SEGMENT
    SEGMENT: ?PR?_DISPLAY?DSZ
    CALLER1: ?C_C51STARTUP
    CALLER2: ?PR?TIMER0?DSZ
*** FATAL ERROR L250: CODE SIZE LIMIT IN RESTRICTED VERSION EXCEEDED
    MODULE:  C:\KEIL\C51\LIB\C51S.LIB (-----)
    LIMIT:   0800H BYTES
Target not created
回复

使用道具 举报

21#
ID:270854 发表于 2018-1-7 15:05 | 只看该作者
闹铃不会响
回复

使用道具 举报

22#
ID:270854 发表于 2018-1-7 16:02 | 只看该作者
每次断电重启闹钟时间就恢复初始值了,
回复

使用道具 举报

23#
ID:261637 发表于 2018-1-13 23:48 | 只看该作者
分的十位g段一直闪,秋楼主解惑。。谢谢
回复

使用道具 举报

24#
ID:231936 发表于 2018-6-21 16:33 | 只看该作者
我修改一下,在Professional试过能用。
/*        项目名称:多功能数码管时钟设计
        调试要求:
        1.MCU:STC89C51
        2.晶振:12MHz
        功能:实时时钟+温度计+闹钟+整点报时+正计时器+倒计时器+计数器*/
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #define uchar unsigned char
  4. #define uint  unsigned int
  5. #define smg_data    P0//定义数码管数据

  6. sbit smg1=P2^4;//位码1声明 时
  7. sbit smg2=P2^5;//位码2声明
  8. sbit smg3=P2^6;//位码3声明 分
  9. sbit smg4=P2^7;//位码4声明
  10. sbit smg5=P1^6;//位码5声明 秒
  11. sbit smg6=P1^7;//位码6声明
  12. sbit gm=P1^3; //黑暗时等于1
  13. sbit k1=P1^2; //按键k1的声明
  14. sbit k2=P1^1; //按键k2的声明
  15. sbit k3=P1^0; //按键k3的声明

  16. sbit bell=P3^7;        //蜂鸣器声明
  17. sbit clk_ds1302=P2^0;//定义控制DS1302的时钟线
  18. sbit io_ds1302=P2^1;//定义控制DS1302的串行数据
  19. sbit rest_ds1302=P2^2;

  20. const uchar tab1[16]={//共阳数码管段码表
  21. 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x86,0x87,0xFF,0xc6,0xbf,0xff};
  22. //0        ,1        ,2        ,3        ,4        ,5        ,6        ,7        ,8        ,9        ,                       
  23. const uchar tab2[16]={//数码管3特殊处理用的段码表
  24. 0xc0,0xf9,0x64,0x70,0x59,0x52,0x42,0xf8,0x40,0x50,0x86,0x87,0xFF,0xc6,0x7f,0xff};
  25.                         //    C      -
  26. bit gm_en=0,zdbs_en=0;//光敏使能信号/整点报时使能信号
  27. uchar gm_time=40; //光敏控制亮度值
  28. char shi,fen,miao,b_shi=7,b_fen=0; //必须是有符号型:数据暂存单元shi/fen/miao,闹铃时间b_shi,b_fen,
  29. uchar hour,minute,second,n=0,a=0,b=0;//从1302读出的实时时间数据hour,minute,second,        b控制字符闪烁
  30. uchar tab23[3];//={0x40,0x59,0x23,0x28,0x11,0x06,0x09};//首次上电时默认的时间
  31. uchar bell_en=0,x=1;//闹钟使能信号,任意键关闭铃声标志位
  32. char zjs_en=0,zjs_shi=0,zjs_fen=0,djs_en=0,djs_shi=60,djs_fen=0,jsq_shi=0,jsq_fen=0;
  33. void key();
  34. void  delay_3us();//3US的延时程序
  35. void  delay_50us(uint t);//延时50*T微妙函数的声明
  36. void  display(uchar shi,fen,miao);//显示子程序
  37. void  set_ds1302();//设置时间
  38. void  get_ds1302();//读取当前时间
  39. void  w_1byte_ds1302(uchar t);//向DS1302写一个字节的数据
  40. uchar r_1byte_ds1302();//从DS1302读一个字节的数据
  41. void init(); //初始化函数

  42. void baojing()//报警函数
  43. {
  44.          uint j=10,i=10;
  45.          bell=0;
  46.          while(i--)display(shi,fen,miao);
  47.          bell=1;
  48.          while(j--)display(shi,fen,miao);
  49. }

  50. /******温度传感器18b20  IO引脚定义********/
  51. sbit DS=P2^3;           //定义DS18B20接口
  52. uchar ly_dis[4];                //定义显示温度的缓冲区
  53. float tt;                        //定义浮点型变量tt存放温度值
  54. uchar temp_en=0;
  55. uchar wendu=0;
  56. uint t=0;

  57. /**********18b20延时子函数 *************/
  58. void delayb(uint count)
  59. {
  60.   uint i;
  61.   while(count)
  62.   {
  63.     i=200;
  64.     while(i>0)
  65.     i--;
  66.     count--;
  67.   }
  68. }

  69. /*********DS18B20初始化************/
  70. void dsreset(void)
  71. {
  72.   uint i;
  73.   DS=0;
  74.   i=103;
  75.   while(i>0)i--;
  76.   DS=1;
  77.   i=4;
  78.   while(i>0)i--;
  79. }

  80. /**********18b20读一位***********/
  81. bit tmpreadbit(void)
  82. {
  83.    uint i;
  84.    bit dat;
  85.    DS=0;
  86.    i++;          //小延时一下
  87.    DS=1;
  88.    i++;i++;
  89.    dat=DS;
  90.    i=8;
  91.    while(i>0)i--;
  92.    return (dat);
  93. }

  94. /**********18b20读一个**********/
  95. uchar tmpread(void)
  96. {
  97.   uchar i,j,dat;
  98.   dat=0;
  99.   for(i=1;i<=8;i++)
  100.   {
  101.     j=tmpreadbit();
  102.     dat=(j<<7)|(dat>>1);   //读出的数据最低位在最前面,这样刚好//一个字节在DAT里
  103.   }
  104.   return(dat);             //将一个字节数据返回
  105. }

  106. /**********18b20写一个字节**********/
  107. void tmpwritebyte(uchar dat)
  108. {
  109.   uint i;
  110.   uchar j;
  111.   bit testb;
  112.   for(j=1;j<=8;j++)
  113.   {
  114.     testb=dat&0x01;
  115.     dat=dat>>1;
  116.     if(testb)     // 写1部分
  117.     {
  118.       DS=0;
  119.       i++;i++;
  120.       DS=1;
  121.       i=8;
  122.           while(i>0)i--;
  123.     }
  124.     else
  125.     {
  126.       DS=0;       //写0部分
  127.       i=8;
  128.           while(i>0)i--;
  129.       DS=1;
  130.       i++;i++;
  131.     }
  132.   }
  133. }

  134. /***********18b20发送温度转换命令*************/
  135. void tmpchange(void)
  136. {
  137.   dsreset();             //初始化DS18B20
  138.   delayb(1);             //延时
  139.   tmpwritebyte(0xcc);  // 跳过序列号命令
  140.   tmpwritebyte(0x44);  //发送温度转换命令
  141. }

  142. /***********获得温度************/
  143. int tmp()
  144. {
  145.   int temp;
  146.   uchar a,b;
  147.   dsreset();
  148.   delayb(1);

  149.   tmpwritebyte(0xcc);  
  150.   tmpwritebyte(0xbe);   //发送读取数据命令

  151.   a=tmpread();          //连续读两个字节数据
  152.   b=tmpread();
  153.   temp=b;
  154.   temp<<=8;
  155.   temp=temp|a;                 //两字节合成一个整型变量。
  156.   return temp;     //返回温度值
  157. }
  158. void dis_temp()
  159. {        
  160.         tmpchange();              //温度转换
  161.         tt=tmp()*0.0625;          //得到真实十进制温度值,因为DS18B20
  162.         wendu=tt;                                                                //可以精确到0.0625度,所以读回数据的最低位代表的是0.0625度。
  163.         if(tt<0)        //判断第一位显示整数还是负号
  164.         tt=0;        
  165.         if((wendu%100/10)<1) //如果温度小于10,不显示十位
  166.         smg1=1;
  167.         else
  168.         {
  169.                 smg_data=tab1[wendu%100/10];//送显示断码  十位
  170.                 smg1=0;
  171.                 delay_50us(gm_time);
  172.                 smg1=1;
  173.         }
  174.         smg_data=tab1[wendu%10];//送显示断码  个位
  175.         smg2=0;
  176.         delay_50us(gm_time);
  177.         smg2=1;
  178.         smg_data=tab1[13];//送显示断码  ℃
  179.         smg3=0;
  180.         delay_50us(gm_time);
  181.         smg3=1;        
  182.         smg4=1;
  183. }
  184. //***********************************************************************
  185. //主程序
  186. void main()
  187. {        
  188.         tmpchange();              //温度转换,为了消除首次显示的85,每次提前转换一次即可解决
  189.     init();
  190.         gm=1;
  191.         while(1)
  192.     {        
  193.                 if(n==0&&temp_en==1)
  194.                 dis_temp();//每15秒切换显示温度一次
  195.                 else
  196.                 {
  197.                         get_ds1302();
  198.                         display(shi,fen,miao);
  199.                         key();
  200.                         if(n==0&&x==1&&bell_en==1&&b_shi==hour&&b_fen==minute)
  201.                         baojing();
  202.                         if(hour==b_shi&&minute==b_fen+1)x=1;
  203.                 }
  204.                 if(gm_en==1)//光敏控制亮度开关
  205.                 {
  206.                         if(gm==1)
  207.                         gm_time=1;
  208.                         else gm_time=40;
  209.                 }
  210.                 else gm_time=40;
  211.                 if(zdbs_en==1&&n==0&&minute==0&&miao==0)//整点报时开关
  212.                 baojing();                                                                 
  213.     }
  214. }

  215. //数码管显示程序
  216. void  display(uchar s,f,m)
  217. {
  218.    if((s/10)<1) smg1=1;
  219.    else
  220.    {
  221.            smg_data=tab1[s/10];//送显示断码  时
  222.            if((n==1||n==3)&&a<5)
  223.            smg1=1;//锁存数据
  224.            else smg1=0;
  225.            delay_50us(gm_time);
  226.            smg1=1;        
  227.    }

  228.    if((n==1||n==3)&&a<5)        smg_data=0x7f; //字符闪烁,小点不闪
  229.    else if(b>=10)                        smg_data=tab1[s%10]-0x80;//小点闪烁,字符不闪
  230.    else                                         smg_data=tab1[s%10];//送显示断码
  231.    smg2=0;
  232.    delay_50us(gm_time);
  233.    smg2=1;

  234.    if((n==2||n==4)&&a<5)         smg_data=0xbf;//b是控制小数点闪烁的,需要闪烁的时候他等于a
  235.    else if(b>=10)                        smg_data=tab1[f/10]; //显示小点//送显示断码
  236.    else                                       smg_data=tab1[f/10];//送显示断码         分
  237.    smg3=0;//锁存数据
  238.    delay_50us(gm_time);
  239.    smg3=1;         

  240.    if(bell_en==1)         smg_data=tab1[f%10]-0x80;//送显示断码
  241.    else                         smg_data=tab1[f%10];//送显示断码
  242.    if((n==2||n==4)&&a<5)
  243.    smg4=1;//锁存数据
  244.    else smg4=0;
  245.    delay_50us(gm_time);
  246.    smg4=1;
  247. /**************秒,不需要显示********************/   
  248.    smg_data=tab2[m/10];//送显示断码   秒
  249.    smg5=0;//锁存数据
  250.    delay_50us(40);
  251.    smg5=1;

  252.    smg_data=tab1[m%10];//送显示断码
  253.    smg6=0;//锁存数据
  254.    delay_50us(40);
  255.    smg6=1;
  256. /*********************************************/

  257. }
  258. void key() //按键控制函数
  259. {
  260.         if(k2==0&&k3==0) //k2k3同时按下,切换闹铃开关 并且在按下之后查看闹钟时间松手后恢复时间显示
  261.         {
  262.                 delay_50us(1);
  263.                 if(k2==0&&k3==0)
  264.                 {        
  265.                         shi=b_shi;
  266.                         fen=b_fen;
  267.                         bell_en=!bell_en;
  268.                         baojing();
  269.                         baojing();
  270.                         while(k2==0&&k3==0)display(shi,fen,miao);//等待松手
  271.                         shi=hour;
  272.                         fen=minute;
  273.                 }
  274.         }
  275.         
  276.         if(k1==0&&k3==0) //k1k3同时按下,切换闹铃开关 并且在按下之后查看闹钟时间松手后恢复时间显示
  277.         {
  278.                 delay_50us(1);
  279.                 if(k1==0&&k3==0)
  280.                 {        
  281.                         gm_en=!gm_en;
  282.                         if(gm_en==1)//使能的话报警两声
  283.                         {baojing();baojing();}
  284.                         else baojing();//无效的话报警一声
  285.                         while(k1==0&&k3==0)display(shi,fen,miao);//等待松手
  286.                 }
  287.         }
  288.         if(k1==0&&k2==0) //k1k2同时按下,切换整点报时开关
  289.         {
  290.                 delay_50us(1);
  291.                 if(k1==0&&k2==0)
  292.                 {        
  293.                         zdbs_en=!zdbs_en;
  294.                         if(zdbs_en==1)//使能的话报警两声
  295.                         {baojing();baojing();}
  296.                         else baojing();//无效的话报警一声        
  297.                         while(k1==0&&k2==0)display(shi,fen,miao);//等待松手
  298.                 }
  299.         }
  300.         if(n==0&&(k2==0||k3==0)&&bell_en==1&&b_shi==hour&&b_fen==minute&&x==1)
  301.         { //功能键k1被按下
  302.                 delay_50us(1);//消抖延时
  303.                 if(n==0&&(k2==0||k3==0)&&bell_en==1&&b_shi==hour&&b_fen==minute&&x==1)
  304.                 {        
  305.                         x=0;   //如果处于响零状态,就任意键关闭响铃
  306.                         while(k1==0)display(shi,fen,miao);//等待松手
  307.                 }
  308.         }
  309.         if(k1==0)
  310.         { //功能键k1被按下
  311.                 delay_50us(1);//消抖延时
  312.                 if(k1==0)
  313.                 {        
  314.                         uint i=0;
  315.                         while(k1==0)
  316.                         {
  317.                                 display(shi,fen,miao);//等待松手
  318.                                 i++;
  319.                                 if(i>(2*(70-gm_time))){n=0;baojing();baojing();break;}//长按K1退出
  320.                         }
  321.                         if(bell_en==1&&b_shi==hour&&b_fen==minute&&x==1)x=0;   //如果处于响零状态,就任意键关闭响铃
  322.                         else if(i<=(2*(70-gm_time)))
  323.                         {
  324.                                 n++;//n记录功能键状态
  325.                                 if(n>7)  n=0; //n清零
  326.                                 baojing();        
  327.                         }
  328.                         i=0;                        
  329.                 }
  330.         }

  331.         if(n==0)//状态0,正常显示时间
  332.         {
  333.                 b=a; //b是控制小数点闪烁的
  334.                 shi=hour;
  335.                 fen=minute;
  336.                 miao=second;
  337.         }        
  338.         if(n==1)//状态1:调节时间的“时”
  339.         {
  340.                 b=10;
  341.                 if(k2==0)
  342.                 { //k2被按下
  343.                         uint i=6,j=10;
  344.                         while(i--)display(shi,fen,miao);//长按连续递减                        
  345.                         if(k2==0)
  346.                         {
  347.                                 shi++;//小时加一
  348.                                 if(shi==24)
  349.                                 shi=0;//达到24清零        
  350.                         }
  351.                          while(j--)display(shi,fen,miao);//长按连续递减
  352.                 }
  353.                
  354.                 if(k3==0)
  355.                 {  //k3被按下
  356.                         uint i=6,j=10;
  357.                         while(i--)display(shi,fen,miao);//长按连续递减        
  358.                         if(k3==0)
  359.                         {
  360.                                 shi--; //小时减一
  361.                                 if(shi<0)
  362.                                 shi=23;//小于0,重新复制
  363.                         }
  364.                         while(j--)display(shi,fen,miao);//长按连续递减
  365.                 }               
  366.         }
  367.         if(n==2)//状态2:调节时间的“分”
  368.         {        b=10;
  369.                  if(k2==0)
  370.                 { //k2被按下
  371.                         uint i=6,j=10;
  372.                         while(i--)display(shi,fen,miao);//长按连续递减
  373.                         if(k2==0)
  374.                         {
  375.                                 fen++;//分加一
  376.                                 if(fen==60)
  377.                                 fen=0;//分到达60 分清零        
  378.                         }        
  379.                         while(j--)display(shi,fen,miao);//长按连续递减
  380.                 }
  381.                
  382.                 if(k3==0)
  383.                 {  //k3被按下
  384.                         uint i=6,j=10;
  385.                         while(i--)display(shi,fen,miao);//长按连续递减
  386.                         if(k3==0)
  387.                         {
  388.                                 fen--;//分减一
  389.                                 if(fen<0)
  390.                                 fen=59;//分小于0,分重新赋值59                                          
  391.                         }
  392.                         while(j--)display(shi,fen,miao);//长按连续递减
  393.                 }
  394.                 tab23[2]=shi/10*16+shi%10;
  395.         tab23[1]=fen/10*16+fen%10;
  396.         hour=shi;
  397.         minute=fen;
  398.         second=0;
  399.         tab23[0]=0;
  400.         set_ds1302();//设置DS1302的初始时间               
  401.         }
  402.         
  403.         if(n==3)//状态三:调节闹铃“时”
  404.         {        
  405.                 shi=b_shi;
  406.                 fen=b_fen;
  407.                 b=10;
  408.                 if(k2==0)
  409.                 {  //k2被按下
  410.                         uint i=6,j=10;
  411.                         while(i--)display(shi,fen,miao);//长按连续递减
  412.                         if(k2==0)
  413.                         {
  414.                                 b_shi++;//闹铃时间加一
  415.                                 if(b_shi==24)
  416.                                 b_shi=0;//闹铃时间清零        
  417.                         }
  418.                         while(j--)display(shi,fen,miao);//长按连续递减
  419.                 }
  420.                
  421.                 if(k3==0)
  422.                 {  //k3被按下
  423.                         uint i=6,j=10;
  424.                         while(i--)display(shi,fen,miao);//长按连续递减
  425.                         if(k3==0)
  426.                         {
  427.                                 b_shi--;//闹铃时间减一
  428.                                 if(b_shi<0)
  429.                                 b_shi=23;//闹铃时间        
  430.                         }
  431.                         while(j--)display(shi,fen,miao);//长按连续递减
  432.                 }               
  433.         }

  434.         if(n==4)//状态四 :调节闹铃的”分“
  435.         {        b=10;
  436.         shi=b_shi;
  437.                 fen=b_fen;
  438.                 if(k2==0)
  439.                 {  //k2被按下
  440.                         uint i=6,j=10;
  441.                         while(i--)display(shi,fen,miao);//长按连续递减
  442.                         if(k2==0)
  443.                         {
  444.                                 b_fen++;//闹铃时间分加一
  445.                                 if(b_fen==60)
  446.                                 b_fen=0;//闹铃分到达60 清零        
  447.                         }        
  448.                         while(j--)display(shi,fen,miao);//长按连续递减
  449.                 }
  450.                
  451.                 if(k3==0)
  452.                 {  //k3被按下
  453.                         uint i=6,j=10;
  454.                         while(i--)display(shi,fen,miao);//长按连续递减
  455.                         if(k3==0)
  456.                         {
  457.                                 b_fen--;//闹铃时间分减一
  458.                                 if(b_fen<0)
  459.                                 b_fen=59;//闹铃时间分重新赋值
  460.                         }
  461.                         while(j--)display(shi,fen,miao);//长按连续递减                        
  462.                 }               
  463.         }
  464.         if(n==5)//状态5 :正计时
  465.         {
  466.                 b=10; //显示小点
  467.                 shi=zjs_shi;
  468.                 fen=zjs_fen;
  469.                 if(k2==0)
  470.                 {  //k2被按下
  471.                         delay_50us(1);//消抖延时
  472.                         if(k2==0)
  473.                         {        
  474.                                 zjs_en=!zjs_en;        
  475.                                 baojing();
  476.                                 while(k2==0)display(shi,fen,miao);//等待松手
  477.                         }
  478.                 }
  479.                
  480.                 if(k3==0)
  481.                 {  //k3被按下
  482.                         delay_50us(1);//消抖延时
  483.                         if(k3==0)
  484.                         {
  485.                                 zjs_shi=0;
  486.                                 zjs_fen=0;
  487.                                 baojing();
  488.                                 while(k3==0)display(shi,fen,miao);//等待松手        
  489.                         }
  490.                 }               
  491.         }
  492.         if(n==6)//状态5 :倒计时
  493.         {        b=10; //显示小点
  494.         shi=djs_shi;
  495.                 fen=djs_fen;
  496.                 if(k2==0)
  497.                 {  //k2被按下
  498.                         delay_50us(1);//消抖延时
  499.                         if(k2==0)
  500.                         {        
  501.                                 djs_en=!djs_en;        
  502.                                 baojing();
  503.                                 while(k2==0)display(shi,fen,miao);//等待松手
  504.                         }
  505.                 }
  506.                
  507.                 if(k3==0&&djs_en==0)
  508.                 {  //k3被按下
  509.                         uint i=6,j=10;
  510.                         while(i--)display(shi,fen,miao);//长按连续递减
  511.                         if(k3==0)
  512.                         {
  513.                                 djs_shi--;
  514.                                 if(djs_shi<0)
  515.                                 djs_shi=60;               
  516.                         }
  517.                         while(j--)display(shi,fen,miao);//长按连续递减
  518.                 }
  519.                 if(k3==0&&djs_en==1)
  520.                 {  //k3被按下
  521.                         delay_50us(1);//消抖延时
  522.                         if(k3==0)
  523.                         {
  524.                                 djs_shi=60;
  525.                                 djs_fen=0;
  526.                                 baojing();
  527.                                 while(k3==0)display(shi,fen,miao);//等待松手        
  528.                         }
  529.                 }               
  530.         }
  531.         if(n==7)//状态5 :计数器
  532.         {        
  533.                 b=1; //不显示小点
  534.                 shi=jsq_shi;
  535.                 fen=jsq_fen;
  536.         
  537.                 if(k2==0)
  538.                 {  
  539.                         uint i=6,j=10;
  540.                         while(i--)display(shi,fen,miao);//长按连续递减
  541.                         if(k2==0)
  542.                         {
  543.                                 jsq_fen++;
  544.                                 if(jsq_fen>99)
  545.                                 {
  546.                                         jsq_fen=0;
  547.                                         jsq_shi++;
  548.                                         if(jsq_shi>99)
  549.                                         jsq_shi=0;
  550.                                 }                        
  551.                         }
  552.                         while(j--)display(shi,fen,miao);//长按连续递减
  553.                 }
  554.                 if(k3==0)
  555.                 {  //k3被按下
  556.                         delay_50us(1);//消抖延时
  557.                         if(k3==0)
  558.                         {
  559.                                 jsq_shi=0;
  560.                                 jsq_fen=0;
  561.                                 baojing();
  562.                                 while(k3==0)display(shi,fen,miao);//等待松手        
  563.                         }
  564.                 }               
  565.         }                        
  566. }
  567. void init()        //初始化函数
  568. {
  569.         IE=0X82;//1000 0010
  570.         TMOD=0X01;    //0000 0001选择定时器0的工作方式1        选择定时器1的工作方式1
  571.         TH0=(65536-50000)/256;//初值15536定时50mS
  572.         TL0=(65536-50000)%256;
  573.         TR0=1; //开启定时器0
  574. }

  575. void timer0() interrupt        1  //定时器0中断服务程序,用来设置冒号闪烁频率
  576. {
  577.         TH0=(65536-50000)/256;//进入中断重新赋初值15536
  578.         TL0=(65536-50000)%256;//计数5万次(50毫秒)
  579.         a++; //标志位b,用来确定光标闪烁频率
  580.         t++;
  581.         if(t==300)t=0;
  582.         if(t>260)temp_en=1;
  583.         else temp_en=0;
  584.         
  585.         if(a==20)
  586.         {        
  587.                 a=0;//a=20 时被清零        
  588.                 if(zjs_en==1)        //正计时
  589.                 {
  590.                         zjs_fen++;
  591.                         if(zjs_fen==60)
  592.                         {
  593.                                 zjs_fen=0;
  594.                                 zjs_shi++;
  595.                                 if(zjs_shi==60)
  596.                                 {
  597.                                         zjs_shi=0;        
  598.                                 }
  599.                         }        
  600.                 }
  601.                 /**********倒计时**********/
  602.                 if(djs_en==1)
  603.                 {
  604.                         djs_fen--;
  605.                         if(djs_fen==-1)
  606.                         {
  607.                                 djs_fen=59;
  608.                                 djs_shi--;
  609.                                 if(djs_shi==-1)
  610.                                 {
  611.                                         djs_shi=0;
  612.                                         djs_fen=0;
  613.                                         djs_en=0;//关闭倒计时
  614.                                         baojing();
  615.                                 baojing();
  616.                                 baojing();
  617.                                 }
  618.                         }        
  619.                 }
  620.                 /*************************/
  621.         }
  622. }


  623. //函数名称:void delay_50US(unsigned int t)
  624. //功能: 延时50*t(us)
  625. void delay_50us(uint t)
  626. {
  627.   unsigned char j;
  628.   for(;t>0;t--)
  629.   {
  630.     for(j=19;j>0;j--);
  631.   }
  632. }
  633. //*******************************************************************************

  634. //*******************************************************************************
  635. //3微秒延时程序
  636. void delay_3us()
  637. {
  638.   ;
  639.   ;
  640. }


  641. //;##############################################################################
  642. //;子程序名:w_1byte_ds1302
  643. //;功能:    向DS1302写一个字节的数据
  644. void w_1byte_ds1302(uchar t)
  645. {
  646.   uchar i;
  647.   for(i=0;i<8;i++)
  648.   {
  649.     if(t & 0x01)
  650.      {io_ds1302=1;}
  651.     else
  652.      {io_ds1302=0;}
  653.     clk_ds1302=1;
  654.     delay_3us();
  655.     delay_3us();
  656.     clk_ds1302=0;
  657.     delay_3us();
  658.     delay_3us();
  659.     t>>=1;
  660.   }  
  661. }
  662. //;########################################################################
  663. //;子程序名:r_1byte_ds1302()
  664. //;功能:    从DS1302读一个字节的数据
  665. uchar r_1byte_ds1302()
  666. {
  667.   uchar i,temp11=0;
  668.   io_ds1302=1;//置IO为1,准备读入数据
  669.   for(i=0;i<8;i++)
  670.   {
  671.     temp11>>=1;
  672.     if(io_ds1302) temp11 |= 0x80;
  673.     clk_ds1302=1;
  674.     delay_3us();
  675.     delay_3us();
  676.     clk_ds1302=0;
  677.     delay_3us();
  678.   }
  679.   return(temp11);
  680. }  
  681. //;#################################################################################
  682. //;子程序名:setbds1302
  683. //;功能:   设置DS1302初始时间,并启动计时
  684. void set_ds1302()
  685. {
  686.   uchar i,j;
  687.   rest_ds1302=0;
  688.   delay_3us();
  689.   clk_ds1302=0;
  690.   delay_3us();
  691.   rest_ds1302=1;
  692.   delay_3us();
  693.   w_1byte_ds1302(0x8e);//写控制命令字
  694.   delay_3us();
  695.   w_1byte_ds1302(0x00);//写保护关闭
  696.   clk_ds1302=1;
  697.   delay_3us();
  698.   rest_ds1302=0;
  699.   for(i=0,j=0x80;i<7;i++,j+=2)
  700.   {
  701.     rest_ds1302=0;
  702.     delay_3us();
  703.     clk_ds1302=0;
  704.     delay_3us();
  705.     rest_ds1302=1;
  706.     delay_3us();
  707.     w_1byte_ds1302(j);
  708.     delay_3us();
  709.     w_1byte_ds1302(tab23[i]);
  710.     delay_3us();
  711.     delay_3us();
  712.     clk_ds1302=1;
  713.     delay_3us();
  714.     rest_ds1302=0;
  715.     delay_3us();
  716.     delay_3us();
  717.   }
  718.   rest_ds1302=0;
  719.   delay_3us();
  720.   clk_ds1302=0;
  721.   delay_3us();
  722.   rest_ds1302=1;
  723.   delay_3us();
  724.   w_1byte_ds1302(0x8e);
  725.   delay_3us();
  726.   w_1byte_ds1302(0x80);
  727.   clk_ds1302=1;
  728.   delay_3us();
  729.   rest_ds1302=0;
  730.   delay_3us();
  731. }  
  732. //;#################################################################-------
  733. //;子程序名:get1302
  734. void get_ds1302()
  735. {  uchar hour_count,minute_count,second_count;
  736.    uchar temp11[7],i,j;
  737.    for(i=0;i<7;i++)
  738.    {temp11[i]=0;}
  739.    for(i=0,j=0x81;i<7;i++,j+=2)
  740.    {  
  741.     rest_ds1302=0;
  742.     delay_3us();
  743.     clk_ds1302=0;
  744.     delay_3us();
  745.     rest_ds1302=1;
  746.     delay_3us();
  747.     w_1byte_ds1302(j);
  748.     temp11[i]=r_1byte_ds1302();
  749.     delay_3us();
  750.     clk_ds1302=1;
  751.     delay_3us();
  752.     rest_ds1302=0;
  753.     delay_3us();
  754.   }
  755.   if(temp11[0]!=0xff)
  756.   {second_count=temp11[0];}
  757.   if(temp11[1]!=0xff)// 数据验证
  758.   {minute_count=temp11[1];}
  759.   if(temp11[2]!=0xff)//数据验证
  760.   {hour_count=temp11[2];}
  761.          hour=hour_count/16*10+hour_count%16;
  762.         minute=minute_count/16*10+minute_count%16;
  763.         second=second_count/16*10+second_count%16;
  764.           /*zancun4=hour_count&0xf0;
  765.           zancun4>>=4;
  766.           zancun5=minute_count&0xf0;
  767.           zancun5>>=4;
  768.           zancun6=second_count&0xf0;
  769.           zancun6>>=4;*/
  770. }
复制代码
回复

使用道具 举报

25#
ID:488532 发表于 2019-3-18 20:15 | 只看该作者
谢谢楼主的分享,下载下来看看。
回复

使用道具 举报

26#
ID:208271 发表于 2019-3-28 09:58 | 只看该作者
很厉害。写数据到DS1302一直没做成功能,看了楼主的,很快成功了,51有你更精彩。真感谢!
回复

使用道具 举报

27#
ID:324043 发表于 2019-3-29 13:09 来自手机 | 只看该作者
不错,谢谢分享。
回复

使用道具 举报

28#
ID:476064 发表于 2019-4-27 21:37 来自手机 | 只看该作者
有人做出成品了吗? 请教个问题!为什我做出来后时钟芯片备用电池不但没有效果还被掏空了电
回复

使用道具 举报

29#
ID:469510 发表于 2019-5-13 16:00 | 只看该作者
很给力!
回复

使用道具 举报

30#
ID:224006 发表于 2020-3-6 18:00 | 只看该作者
学习了!
回复

使用道具 举报

31#
ID:1119839 发表于 2024-5-8 21:42 | 只看该作者
真的对我帮助很大!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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