找回密码
 立即注册

QQ登录

只需一步,快速开始

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

STC89C52单片机+DS1302+数码管显示及按键调时的时钟程序Proteus仿真图

[复制链接]
跳转到指定楼层
楼主
STC89C52单片机+DS1302+数码管显示时钟及按键时+整点报时功能
资料含有程序源代码+及仿真原理图
仿真软件运行和实际焊接电路运行都通过验证。
//注意事项://:仿真时请将程序char H=0,L=1,开发板下载试验请将变量char H=1  ,L=0;
//:请屏蔽此 DS1302初始化 //init_1302(); 函数。
void main()
{
        t0_init();
        t1_init();
        //init_1302();                //仿真时如你需要显示当前实时系统时间,请屏蔽此函数。          
        while(1)
        {
           read_sf();
           ExecuteKeyNum();
        }
        
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)

1》按下设置启动键:分钟闪烁进入分钟调时,再次按下小时闪烁进入小时调时
2》按下参数加或参数减按钮:进行小时后分钟的时间设置
注意:仿真时请将程序里WELA的变量H=0  L=1,开发板试验请将变量H=1  L=0;

单片机源程序如下:
  1. /*********************************************************************************
  2. 描述: 8位共阴数码管时钟,显示88-88-88样式,正常走时的时候,两个“-”0.5秒闪烁一次;
  3.        调时:按KEY1按键第1次分钟位闪烁,再按KEY2一次分钟加1,按KEY3一次分钟减1,长按连加连减;
  4.                          按KEY1按键第2次小时位闪烁,再按KEY2一次小时加1,按KEY3一次小时减1,长按连加连减;
  5.                          按KEY1按键第3次,秒从零开始累加,时钟回到正常走时;
  6.                          对时的时候先调好时、分,分钟要比参考时间的分钟加1分,
  7.                          再看参考时间的秒数到了59再按KEY1按键的第3次,这样对时可以很准的
  8. 仿真 实物都通过.  11.0592MHz晶振,STC89C52RC,两个74HC573锁存器做位选、段选
  9. **********************************************************************************/
  10. #include<reg52.h>
  11. #include<intrins.h>

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

  14. sbit sclk = P2^4;                                                                //1302时钟端口
  15. sbit dio = P2^5;                                                                //1302数据端口
  16. sbit ce = P2^6;
  17.                                                                         //1302使能
  18. sbit wela1 = P2^0;                                                                //位选
  19. sbit wela2 = P2^1;                                                                //位选
  20. sbit wela3 = P2^2;        
  21. sbit wela4 = P2^3;        

  22. sbit buzzer=P3^7;

  23. sbit KEY1=P3^0;                                                                        //按键 设置/确认
  24. sbit KEY2=P3^1;                                                                        //按键 加
  25. sbit KEY3=P3^2;                                                                        //按键 减

  26. uchar snum,fnum;

  27. char shi,fen,miao,shi_alarm=6;

  28. uchar ss,mm;
  29. char H=0,L=1;                                                //用软件仿真时关闭数码管H全部改为0,单片机下载H改为1.
  30. char FunctionKeyNum=0;                                //功能键键值
  31. char FuncTempNum=0;                                        //功能键临时键值
  32. typedef enum KeyState{StateInit,StateAffirm,StateSingle,StateRepeat};        //键值状态值


  33. /***********写时DS1302地址************/
  34. #define write_year  0x8c         //写年的地址
  35. #define write_moon  0x88         //写月的地址
  36. #define write_week  0x8a         //写周的地址
  37. #define write_day   0x86         //写日的地址
  38. #define write_shi  0x84                 //写时的地址
  39. #define write_fen  0x82                 //写分的地址
  40. #define write_miao 0x80                 //写秒的地址
  41. #define write_ram  0xc0                 ////RAM的基地址
  42. /***********读时DS1302地址************/
  43. #define read_year  0x8d                 //读年的地址
  44. #define read_moon  0x89                 //读月的地址
  45. #define read_week 0x8b                 //读周的地址
  46. #define read_day  0x87                 //读日的地址
  47. #define read_shi  0x85                 //读时的地址
  48. #define read_fen  0x83                 //读分的地址
  49. #define read_miao 0x81                 //读秒的地址
  50. #define read_ram  0xc1                 //RAM的基地址
  51.                   // 0     1    2    3    4     5    6    7    8   9
  52. //uchar d[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //共阴不带小数点
  53. //uchar d[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};  //        共阴带小数点
  54. uchar d[]={0Xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};          //共阳极
  55. uchar dd[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};          //共阳极带小数点

  56. void Time_alarm();                 //整点报时子程序

  57. void delayms(uint z)
  58. {
  59.         uint x,y;
  60.         for(x=z;x>0;x--)
  61.                 for(y=120;y>0;y--);
  62. }
  63. /*
  64. void buzzer1()
  65. {
  66. uint i;
  67. for(i=0;i<10;i++)
  68.         {
  69.     buzzer=0;
  70.         delayms(500);
  71.         buzzer=1;
  72.         delayms(500);
  73.         }
  74. }
  75. */
  76. void buzzer2() //发声子程序
  77. {
  78.          
  79.           uint t,tt;
  80.           for(t=0;t<50;t++) //45为蜂鸣器发声频率
  81.           {
  82.           buzzer=!buzzer;
  83.           for(tt=0;tt<50;tt++); //45为蜂鸣器发声频率
  84.           }
  85. }



  86. void t0_init()  //定时50ms一个中断
  87. {
  88.    
  89.   TMOD |= 0X01;
  90.   TH0 = (65536-46080)/256;
  91.   TL0 = (65536-46080)%256;
  92.   EA = 1;
  93.   ET0 = 1;
  94.   TR0 = 1;

  95. }

  96. void t1_init()
  97. {
  98.         TMOD |= 0x10;
  99.         TH1 = 0x500;
  100.         TL1 = 0x00;
  101.         TR1 = 1;        
  102. }

  103. void temer0() interrupt 1
  104. {
  105.   TH0=(65536-46080)/256;
  106.   TL0=(65536-46080)%256;
  107.   ss++;
  108.   mm++;
  109.   if(ss==22)
  110.   {
  111.   ss=0;
  112.   }
  113.   if(mm==10)
  114.   {
  115.    mm=0;
  116.    Time_alarm();   
  117. }
  118. }         





  119. void Display(uchar shi,uchar fen)                          //显示函数
  120. {
  121.         if(FunctionKeyNum==0)
  122.         {
  123.                 snum=30;
  124.                 fnum=30;
  125.         }
  126.         
  127.         if(FunctionKeyNum==1)
  128.         {
  129.                 fnum++;
  130.                 snum=30;
  131.         }
  132.         
  133.         if(FunctionKeyNum==2)
  134.         {
  135.                 snum++;
  136.                 fnum=30;
  137.         }
  138.         
  139.             wela1=H;   //关闭所有数码管
  140.                 wela2=H;   //用软件仿真时关闭数码管H全部改为0,单片机下载H改为1.
  141.                 wela3=H;   //用软件仿真时关闭数码管H全部改为0,单片机下载H改为1.
  142.                 wela4=H;

  143.         
  144.         if(snum>=30)
  145.         {        
  146.                 if((shi/10)<1)         //如果小时十位小于1,
  147.                 {        
  148.                 wela1=L;                 // 小时十位就不显示                  
  149.                 P0=d[0];                           // 小时十位就显示"0"
  150.                 delayms(2);
  151.                 P0=0xff;
  152.                 wela1=H;
  153.         
  154.                 }
  155.         
  156.                 else
  157.                 {
  158.                 wela1=L;
  159.                 P0=d[shi/10];
  160.                 delayms(2);
  161.                 P0=0xff;
  162.                 wela1=H;

  163.                 }
  164.   
  165.         if(miao%2==0)            //if(miao%2==0) 1秒闪烁1次
  166.   //        if(ss>=20)                 //        这里写为ss>=10,闪烁频率可调
  167.                 {                                 
  168.             wela2=L;
  169.                 P0=dd[shi%10];
  170.                 delayms(2);
  171.                 P0=0xff;
  172.                 wela2=H;
  173.               }
  174.                
  175.                 else
  176.                 {
  177.                 wela2=L;
  178.                 P0=d[shi%10];                                                        
  179.                 delayms(2);
  180.                 P0=0xff;
  181.                 wela2=H;
  182.                 }

  183.                 if(snum==60)
  184.                         snum=0;
  185.         }  
  186.                         
  187.    //        if(miao%2==0)         //if(miao%2==0) 1秒闪烁1次
  188.                   if(ss>=20)                 //        这里写为ss>=10,闪烁频率可调
  189.                 {                                 
  190.             wela2=L;
  191.                 P0=d[shi%10];
  192.                 delayms(2);
  193.                 P0=0xff;
  194.                 wela2=H;
  195.               }
  196.                                 
  197.         if(fnum>=30)
  198.         {  
  199.                 wela3=L;
  200.                 P0=d[fen/10];
  201.                 delayms(2);
  202.                 P0=0xff;
  203.                 wela3=H;
  204.                         
  205.                 wela4=L;
  206.                 P0=d[fen%10];
  207.                 delayms(2);
  208.                 P0=0xff;
  209.                 wela4=H;
  210.                
  211.                
  212.                 if(fnum==60)
  213.                         fnum=0;
  214.                                 }         
  215. }


  216. void write_1302(uchar add,dat)                 //写1302函数  
  217. {
  218.         uchar i,temp;
  219.         temp=add;
  220.         ce=0;
  221.         _nop_();
  222.         sclk=0;
  223.         _nop_();
  224.         ce=1;
  225.         _nop_();
  226.         for(i=0;i<8;i++)
  227.         {
  228.                 sclk=0;
  229.                 _nop_();
  230.                 if((temp&0x01)==0x01)
  231.                         dio=1;
  232.                         else
  233.                         dio=0;
  234.                 temp>>=1;
  235.                 sclk=1;
  236.                 _nop_();
  237.         }
  238.         temp=dat;
  239.         for(i=0;i<8;i++)
  240.         {
  241.                 sclk=0;
  242.                 _nop_();
  243.                 if((temp&0x01)==0x01)
  244.                         dio=1;
  245.                         else
  246.                         dio=0;
  247.                 temp>>=1;
  248.                 sclk=1;
  249.                 _nop_();
  250.         }
  251.         ce=0;
  252.         sclk=0;
  253. }
  254. uchar read_1302(uchar add)                                   //读1302函数               
  255. {
  256.         uchar dat,dat1,i,temp;
  257.         temp=add;
  258.         ce=0;
  259.         _nop_();
  260.         sclk=0;
  261.         _nop_();
  262.         ce=1;
  263.         for(i=0;i<8;i++)
  264.         {
  265.                 sclk=0;
  266.                 _nop_();
  267.                 if((temp&0x01)==0x01)
  268.                         dio=1;
  269.                         else
  270.                         dio=0;
  271.                 temp>>=1;
  272.                 sclk=1;
  273.                 _nop_();
  274.         }
  275.         for(i=0;i<8;i++)
  276.         {
  277.                 sclk=0;
  278.                 _nop_();
  279.                 if(dio)
  280.                     dat|=0x80;
  281.                 if(i<7)
  282.                         dat>>=1;
  283.                 sclk=1;
  284.         }
  285.         dat1=dat/16;
  286.         dat=dat%16;
  287.         dat=dat1*10+dat;  
  288.         ce=0;
  289.         sclk=0;
  290.         return dat;
  291. }                        



  292. void init_1302()                                                        //初始化函数 设置时间
  293. {        
  294.         write_1302(0x8e,0x00);                                        //保护取消,可以进行写操作
  295.         write_1302(write_year,0x20);
  296.         write_1302(write_moon,0x12);                        //写入时修改月
  297.         write_1302(write_week,0x30);                        //写入时修改星期
  298.         write_1302(write_day,0x04);                           //写时修改日期
  299.         write_1302(write_miao,0x00);        
  300.         write_1302(write_fen,0x30);
  301.         write_1302(write_shi,0x10);
  302.         write_1302(0x8e,0x80);                                        //保护启动,不能进行写操作
  303. }         

  304. void read_sf()
  305. {
  306.         shi=read_1302(read_shi);
  307.         fen=read_1302(read_fen);
  308.         miao=read_1302(read_miao);
  309.         Display(shi,fen);

  310. }

  311. void KeyScan(void)
  312. {
  313.         static uchar KeyStateTemp1 = 0;                  //按键状态临时存储值1
  314.         static uchar KeyStateTemp2 = 0;                  //按键状态临时存储值2
  315.         static uchar KeyStateTemp3 = 0;                  //按键状态临时存储值3
  316.         static uchar KeyTime = 0;                          //按键延时时间
  317.         bit KeyPressTemp1;                                          //按键是否按下存储值1
  318.         bit KeyPressTemp2;                                          //按键是否按下存储值2
  319.         bit KeyPressTemp3;                                          //按键是否按下存储值3

  320.         KeyPressTemp1 = KEY1;                                  //读取IO口的键值
  321.         switch(KeyStateTemp1)
  322.         {
  323.                 case StateInit:
  324.                         if(!KeyPressTemp1)                                        //KEY1按下
  325.                                 KeyStateTemp1 = StateAffirm;        //按键状态切换到确认态
  326.                 break;
  327.                 case StateAffirm:                                                //确认状态
  328.                         if(!KeyPressTemp1)                                        //按键还在按下
  329.                         {
  330.                                 KeyTime = 0;
  331.                                 KeyStateTemp1 = StateSingle;        //按键状态切换到单击状态
  332.                         }
  333.                         else KeyStateTemp1 = StateInit;                //否则按键抬起,回到初始态
  334.                 break;
  335.                
  336.                 case StateSingle:                                                //单击
  337.                          if(KeyPressTemp1)
  338.                          {
  339.                                 KeyStateTemp1 = StateInit;                 //按键释放
  340.                                 FuncTempNum++;                                         //键值加1
  341.                                 if(FuncTempNum>3)  
  342.                                 FuncTempNum = 0;
  343.                          }

  344.                          else if(++KeyTime>100)
  345.                          {
  346.                                          KeyPressTemp1 = StateRepeat;
  347.                                         KeyTime = 0;
  348.                          }
  349.                 break;
  350.         
  351.                 case StateRepeat:                                                 //连发
  352.                         if(KeyPressTemp1)
  353.                                 KeyStateTemp1 = StateInit;
  354.                         else
  355.                         {
  356.                                 if(++KeyTime > 10)
  357.                                 {
  358.                                         KeyTime = 0;
  359.                                         FuncTempNum++;
  360.                                         if(FuncTempNum>3)  
  361.                                         FuncTempNum = 0;
  362.                                 }
  363.                                 break;
  364.                         }
  365.                 break;
  366.         
  367.                 default :KeyStateTemp1 = KeyStateTemp1 = StateInit; break;
  368.                         
  369.         }


  370. if(FuncTempNum)                                                                //只有功能键被按下后,增加和减小键才有效
  371.         {
  372.                 KeyPressTemp2 = KEY2;                                        //读取I/O口的键值
  373.                 switch(KeyStateTemp2)
  374.                 {        
  375.                         case StateInit:                                                //按键初始状态
  376.                                 if(!KeyPressTemp2)                                //当按键按下,状态切换到确认态
  377.                                         KeyStateTemp2 = StateAffirm;
  378.                                 break;
  379.                         case StateAffirm:                                        //按键确认态
  380.                                 if(!KeyPressTemp2)
  381.                                 {
  382.                                         KeyTime = 0;
  383.                                         KeyStateTemp2 = StateSingle;//切换到单次触发态        
  384.                                 }
  385.                                 else KeyStateTemp2 = StateInit; //按键已抬起,切换到初始态
  386.                                 break;
  387.                         case StateSingle:                                        //按键单发态
  388.                                 if(KeyPressTemp2)                                //按下时间小于1s
  389.                                 {
  390.                                         KeyStateTemp2 = StateInit;  //按键释放,则回到初始态
  391.                                         if(FunctionKeyNum == 1)                //若功能键第一次按下
  392.                                         {
  393.                                         fen++;
  394.                                         fen=fen/10*16+fen%10;                //转为16进制
  395.                                         if(fen==0x60)
  396.                                             fen=0x00;
  397.                                            write_1302(write_fen,fen);        //写入1302
  398. ……………………

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

所有资料51hei附件下载:
STC89C52单片机+DS1302+数码管显示及按键调时的时钟程序.7z (72.88 KB, 下载次数: 57)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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