找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6072|回复: 4
收起左侧

蓝桥杯任务基于单片机的电子钟

[复制链接]
ID:261418 发表于 2017-12-14 10:30 | 显示全部楼层 |阅读模式
基于单片机的电子钟仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
0.jpg 0.jpg
蓝桥杯任务单片机源程序如下:
  1. #include <regx51.h>
  2. #include <intrins.h>

  3. sfr AUXR = 0x8e;
  4. /*数码管显示字符转换表*/
  5. unsigned char tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40,0x39};
  6. signed char num[] = {10,10,10,10,10,10,10,10};   //数码管显示缓冲区
  7. signed char timeclock[] = {0,0,11,0,0,11,0,0};   //闹钟时间
  8. unsigned char TRH0,TRL0;  //T0重载值的高字节和低字节
  9. bit clock = 0;          //闹钟时间到标志位
  10. bit flag = 0;          //1s闪烁标志位
  11. bit flag200ms = 0;         //200ms定时标志位
  12. bit timesetup = 0;   //时间设置标志位
  13. bit clocksetup = 0;         //闹钟设置标志位
  14. unsigned position = 0;    //设置小时,分钟,秒标志位(‘1’小时,‘2’分钟,‘3’秒)
  15. unsigned char Temp;           //温度值
  16. unsigned char Time[5];          //时间值

  17. void key();  //按键判断执行函数
  18. void Ds1302_Display();          //时间显示函数
  19. void Ds18b20_Display();          //温度显示函数

  20. extern void Ds1302_Init();          //DS1302初始化函数
  21. void Ds1302_Time(unsigned char *time);  //带参数的向DS18B20写时间
  22. extern void Write_Ds1302_Byte(unsigned char temp);          //向DS1302写入数据
  23. extern unsigned char Read_Ds1302 (unsigned char address);          //从DS1302读取数据
  24. extern unsigned char DS18B20_Temp();         //读取DS18B20温度值


  25. /*T0初始化函数 (ms = 中断时间)*/
  26. void Time0_Init(unsigned char ms)
  27. {
  28.         unsigned long num;                //临时变量
  29.         num = 12000000 / 12;     //12分频  定时器计数频率
  30.         num = (num * ms)/1000;          //计算所需的计数值
  31.         num = 65536 - num;                  //计算定时器重载值
  32.         TRH0 = (unsigned char)(num>>8);                //定时器重载值拆分为高低字节
  33.         TRL0 = (unsigned char)num;
  34.         TH0 = TRH0;           //加载T0重载值                 
  35.         TL0 = TRL0;
  36.         AUXR &= 0x7F;         
  37.         TMOD &= 0xf0;          //清零T0的控制位
  38.         TMOD |= 0x01;          //配置T0为模式1        
  39.         EA = 1;                //使能总中断
  40.         ET0 = 1;        //使能T0中断
  41.         TR0 = 1;        //启动T0
  42. }

  43. void main()
  44. {
  45.         unsigned char i,k=0;

  46.         Time0_Init(1);         //初始化T0,定时时间为1ms
  47.         Ds1302_Init();         //初始化DS1302
  48.         while(1)
  49.         {
  50.                 key();        
  51.                 for(i=0;i<8;i++)
  52.                 {
  53.                         if(num[i]==timeclock[i])
  54.                                 k++        ;
  55.                         else
  56.                                 k = 0;
  57.                 }
  58.                 if(k == 8)
  59.                         clock = 1;                                
  60.                
  61.         }        
  62. }
  63. /*DS18B20显示函数*/
  64. void Ds18b20_Display()
  65. {
  66.         unsigned char i;

  67.         if(flag200ms != 0)
  68.         {
  69.                 flag200ms = 0;
  70.                 Temp = DS18B20_Temp();
  71.         
  72.                 for(i=0;i<5;i++)
  73.                 {
  74.                         num[i] = 10;
  75.                 }
  76.         
  77.                 num[5] = Temp / 10;
  78.                 num[6] = Temp % 10;
  79.                 num[7] = 12;
  80.         }
  81. }
  82. /*DS1302显示函数*/
  83. void Ds1302_Display()
  84. {
  85.         static unsigned char i;
  86.         static unsigned char pers = 0xaa;
  87.         

  88.         if(flag200ms != 0)
  89.         {
  90.                 flag200ms = 0;
  91.                 for(i=0;i<3;i++)
  92.                 {
  93.                         Time[i] = Read_Ds1302(i);  //每200ms获取时间
  94.                 }
  95.                 if(pers != Time[0])          //判断时间有没有变化
  96.                 {        
  97.                         num[7] = Time[0] & 0x0f;   //秒
  98.                         num[6] = Time[0] >> 4;
  99.                         num[5] = 11;
  100.                         num[4] = Time[1] & 0x0f;   //分
  101.                         num[3] = Time[1] >> 4;
  102.                         num[2] = 11;
  103.                         num[1] = Time[2] & 0x0f;   //时
  104.                         num[0] = Time[2] >> 4;               

  105.                         pers = Time[0];                //将变化值重新写入判断值
  106.                 }
  107.         }        
  108. }
  109. /*数码管显示函数*/
  110. void Display()           
  111. {
  112.         static unsigned char we = 0;        
  113.         
  114.         P0 = 0x00;                //清除鬼影
  115.         P2 |= 0xff;

  116.         P2 &= ~(1<<we);          //位选择
  117.         if(clocksetup)
  118.                 P0 = tab[timeclock[we]];
  119.         else
  120.                 P0 = tab[num[we]];          //显示数选择        
  121.         
  122.         if(flag)           //进入设置状态
  123.         {
  124.                 switch(position) //判断是那个设置位
  125.                 {
  126.                         case 1:         P2 |= 0xc0; break;         //秒
  127.                         case 2:         P2 |= 0x18; break;         //分
  128.                         case 3:         P2 |= 0x03; break;         //时
  129.                         default : position = 0; timesetup = 0; clocksetup = 0; break;
  130.                 }
  131.         }
  132.                
  133.         if(++we >= 8)  //八个数码管         
  134.                 we = 0;        
  135. }

  136. /*T0中断函数*/                                                           
  137. void Time0_inte() interrupt 1
  138. {
  139.         static unsigned char ms = 0;
  140.         static unsigned char flag1s = 0;
  141.         static unsigned char flag5s = 0;

  142.         TH0 = TRH0;         //加载T0重载值
  143.         TL0 = TRL0;

  144.         Display();        //数码管显示

  145.         if(++ms >= 200)
  146.         {
  147.                 flag200ms = 1;
  148.                 ms = 0;
  149.                 if(flag5s < 5 && clock)         //闹钟5秒时间判断
  150.                 {
  151.                         P1_0 = ~P1_0;
  152.                 }
  153.                 else
  154.                 {
  155.                         clock = 0;
  156.                         P1_0 = 0;
  157.                 }
  158.                 if(++flag1s >= 5)
  159.                 {
  160.                         flag1s = 0;
  161.                         flag = ~flag;
  162.                         if(clock)
  163.                                 flag5s++;
  164.                         else
  165.                                 flag5s = 0;
  166.                 }
  167.         }        
  168. }
  169. //向DS1302写入时间
  170. void TimeWeite()
  171. {
  172.         unsigned char ti[3];  
  173.         //将两个分开的时间合成在一起
  174.         ti[0] = ((num[6]<<4) | num[7]);
  175.         ti[1] = ((num[3]<<4) | num[4]);
  176.         ti[2] = ((num[0]<<4) | num[1]);

  177.         Ds1302_Time(ti);
  178. }

  179. void key()
  180. {
  181.         if((P3_0==0||P3_1==0||P3_2==0||P3_3==0)&&clock==1)        //闹钟响应,进行关闭
  182.         {
  183.                 clock = 0;
  184.                 while(!P3_0);while(!P3_1);
  185.                 while(!P3_2);while(!P3_3);
  186.         }

  187.         if(timesetup!=1 && clocksetup!=1 && P3_0==1)        //按下显示温度值,松开显示时间
  188.         {
  189.                 Ds1302_Display();
  190.         }else if(timesetup!=1 && clocksetup!=1 &&P3_0 == 0)
  191.         {
  192.                 Ds18b20_Display();        
  193.         }
  194.         if(clocksetup !=1 && P3_3 == 0)                //进入时间设置
  195.         {
  196.                 timesetup = 1;
  197.                 position++;
  198.                 if(position == 4)        //向DS1302重新写入时间
  199.                 {
  200.                         TimeWeite();
  201.                 }
  202.                 while(!P3_3);
  203.         }
  204.         if(timesetup !=1 && P3_2 == 0)           //进入闹钟时间设置
  205.         {
  206.                 clocksetup = 1;
  207.                 position++;
  208.                 clock = 0;
  209.                 while(!P3_2);
  210.         }
  211.         if((timesetup==1||clocksetup==1) && P3_0 == 0)        //进入时间设置, 时间+1
  212.         {         
  213.           if(timesetup)                //实时时钟设置
  214.           {
  215.                   if(position == 1)          //秒
  216.                 {
  217.                         if(++num[7] >= 10)
  218.                         {
  219.                                 num[7] = 0;
  220.                                 if(++num[6] >=6)
  221.                                         num[6] = 0;
  222.                         }
  223.                 }else
  224.                 if(position == 2)         //分
  225.                 {
  226.                         if(++num[4] >= 10)
  227.                         {
  228.                                 num[4] = 0;
  229.                                 if(++num[3] >=6)
  230.                                         num[3] = 0;
  231.                         }
  232.                 }else
  233.                 if(position == 3)         //时
  234.                 {
  235.                         if(num[0] == 2)
  236.                         {
  237.                                 if(++num[1] >= 5)
  238.                                 {
  239.                                         num[1] = 0;
  240.                                         num[0] = 0;
  241.                                 }        
  242.                         }else
  243.                         if(++num[1] >= 10)
  244.                         {
  245.                                 num[1] = 0;
  246.                                 if(++num[0] >=3)
  247.                                         num[0] = 0;
  248.                         }
  249.                 }
  250.           }else if(clocksetup)          //闹钟时间设置
  251.           {
  252.                   if(position == 1)          //秒
  253.                 {
  254.                         if(++timeclock[7] >= 10)
  255.                         {
  256.                                 timeclock[7] = 0;
  257.                                 if(++timeclock[6] >=6)
  258.                                         timeclock[6] = 0;
  259.                         }
  260.                 }else
  261.                 if(position == 2)         //分
  262.                 {
  263.                         if(++timeclock[4] >= 10)
  264.                         {
  265.                                 timeclock[4] = 0;
  266.                                 if(++timeclock[3] >=6)
  267.                                         timeclock[3] = 0;
  268.                         }
  269.                 }else
  270.                 if(position == 3)         //时
  271.                 {
  272.                         if(timeclock[0] == 2)
  273.                         {
  274.                                 if(++timeclock[1] >= 4)
  275.                                 {
  276.                                         timeclock[1] = 0;
  277.                                         timeclock[0] = 0;
  278.                                 }        
  279.                         }else
  280.                         if(++timeclock[1] >= 10)
  281.                         {
  282.                                 timeclock[1] = 0;
  283.                                 if(++timeclock[0] >=3)
  284.                                         timeclock[0] = 0;
  285.                         }
  286.                 }        
  287.           }
  288.           while(!P3_0);
  289.         }
  290.         if((timesetup==1||clocksetup==1) && P3_1 == 0)         //进入时间设置, 时间-1
  291.         {        
  292.                 if(timesetup)           //实时时钟设置
  293.           {
  294.                   if(position == 1)        //秒
  295.                 {
  296.                         if(--num[7] < 0)
  297.                         {
  298.                                 num[7] = 9;
  299.                                 if(--num[6] < 0)
  300.                                         num[6] = 5;
  301.                         }
  302.                 }else
  303.                 if(position == 2)        //分
  304.                 {
  305.                         if(--num[4] < 0)
  306.                         {
  307.                                 num[4] = 9;
  308.                                 if(--num[3] < 0)
  309.                                         num[3] = 5;
  310.                         }
  311.                 }else
  312.                 if(position == 3)  //时
  313.                 {
  314.                         if(--num[1] < 0)
  315.                         {
  316.                                 num[1] = 9;
  317.                                 if(--num[0] < 0)
  318.                                 {
  319.                                         num[0] = 2;
  320. ……………………

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

所有资料51hei提供下载:
基于单片机的电子钟.zip (84.07 KB, 下载次数: 115)
回复

使用道具 举报

ID:171060 发表于 2017-12-23 22:05 来自手机 | 显示全部楼层
感谢分享。
回复

使用道具 举报

ID:368508 发表于 2018-7-11 14:18 | 显示全部楼层
感谢大佬!!!!
回复

使用道具 举报

ID:471752 发表于 2019-1-22 17:07 | 显示全部楼层
厉害,谢谢楼主
回复

使用道具 举报

ID:544311 发表于 2020-11-29 16:47 | 显示全部楼层
谢谢大佬的分享,给了我很大帮助。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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