设为首页收藏本站

极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 555|回复: 8

【51单片机】时光钟 - 一寸光阴一寸光

  [复制链接]
发表于 2017-2-28 15:09:34 | 显示全部楼层 |阅读模式
时间就像光一样,匆匆一撇却已远去,离去的时光怕是连光也望尘莫及。

1.概要:有别于传统石英钟,内部不使用任何机械结构,而是全部使用电子电路。通过单片机控制发光二极管所形成的光束来指示时间。因为指针全部使用光束代替,所以在深夜也能看得很清楚,也因此可以当作“壁灯”使用。

2.原理:51单片机作为主控芯片,从DS3231时钟得到时间数据,再通过74ls38译码器输出低电平控制60个Led灯的开关。Led发光二极管安装于全透明的聚光杯中,形成的光束作为指针,通过单片机的PWM控制Led的形成长短不一的光束来区分时针、分针和秒针。HC06作为通信芯片,可连接手机的蓝牙实现对本时钟时间的修改,以及指定Led灯的亮灭(作为壁灯使用时),或者显示一些预设的动画效果,比如流水灯等。

PS:楼主由于工具所限(自己在家无聊时做的,纯手工请不要嫌弃),这里只使用12个Led做了个原型,没加蓝牙模块,只实现最核心的时间功能。

3.材料:
1. STC89C52RC
2. DS3231时钟模块
3. 12个高亮5mmLED
4. 3.7v锂电池
5. TP4056锂电池充电模块
6. 奶茶店的透明吸管(套在Led上聚光可形成光束,选择适合自己Led 的吸管即可)

PS:根据自己的喜好选择led的颜色即可,但是注意不同波长的led形成的光束有别,有些会比较不明显。

4.下载代码:

  1. #include <reg52.h>
  2. #include <intrins.h>  
  3. #define uchar unsigned char
  4. #define uint unsigned int

  5. #define DS3231_WriteAddress 0xD0   
  6. #define DS3231_ReadAddress  0xD1   
  7. #define DS3231_SECOND       0x00   
  8. #define DS3231_MINUTE       0x01   
  9. #define DS3231_HOUR         0x02   
  10. #define DS3231_WEEK         0x03   
  11. #define DS3231_DAY          0x04   
  12. #define DS3231_MONTH        0x05   
  13. #define DS3231_YEAR         0x06   

  14. bit  ack;         //ó|′e±ê־λ
  15. sbit SDA = P0^6;     //Ä£ÄaI2Cêy¾Y′«ËíλSDA        
  16. sbit SCL = P0^7;     //Ä£ÄaI2Cê±Öó¿ØÖÆλSCL

  17. sbit c1 = P2^6;   //Ã룬¸öλ
  18. sbit c2 = P2^5;   //·Ö£¬¸öλ
  19. sbit c3 = P2^7;   //Ã룬¸öλ
  20. sbit c4 = P2^3;   //Ã룬¸öλ
  21. sbit c5 = P2^1;   //Ã룬ê®Î»
  22. sbit c6 = P2^0;   //Ã룬¸öλ
  23. sbit c7 = P3^7;   //Ã룬¸öλ
  24. sbit c8 = P3^6;   //Ã룬¸öλ
  25. sbit c9 = P3^2;   //Ã룬ê®Î»
  26. sbit c10 = P1^5;   //·Ö£¬ê®Î»
  27. sbit c11 = P1^3;   //ê±£¬¸öλ
  28. sbit c12 = P1^2;   //ê±£¬ê®Î»

  29. unsigned int flag1, flag2, flag3, flag4, flag5, flag6, flag7, flag8, flag9, flag10, flag11, flag12;
  30. unsigned char hour, minute, second;
  31. unsigned char lastHour = 24, lastMinute = 60, lastSecond = 60;

  32. void TM1637_start();  
  33. void TM1637_stop();  
  34. void TM1637_write1Bit(unsigned char mBit);  
  35. void TM1637_write1Byte(unsigned char mByte);  
  36. void TM1637_writeCammand(unsigned char mData);  
  37. void TM1637_writeData(unsigned char addr, unsigned char mData);  
  38. void time_set(char hour, char min);  
  39. void time_display();  
  40. void timer0_init();  
  41.   
  42. void setZero();
  43. void delay_140us();  
  44. void delayus(uint us);  

  45. uchar BCD2HEX(uchar val)    //BCDÂë×a»»ÎaByte
  46. {
  47.     uchar temp;
  48.     temp = val & 0x0f;
  49.     val >>= 4;
  50.     val &= 0x0f;
  51.     val *= 10;
  52.     temp += val;
  53.     return temp;
  54. }

  55. uchar HEX2BCD(uchar val)    //BÂë×a»»ÎaBCDÂë
  56. {
  57.      return (((val % 100) / 10) << 4) | (val % 10);
  58. }

  59. void delayus(uint us)
  60. {
  61.     while(us--);
  62. }

  63. void Start_I2C()
  64. {
  65.     SDA = 1;                 
  66.     delayus(1);
  67.     SCL = 1;
  68.     delayus(5);            

  69.     SDA = 0;            
  70.     delayus(5);         

  71.     SCL = 0;               
  72.     delayus(2);
  73. }

  74. void Stop_I2C()
  75. {
  76.     SDA = 0;                 
  77.     delayus(1);            
  78.     SCL = 1;                 
  79.     delayus(5);

  80.     SDA = 1;                 
  81.     delayus(4);
  82. }

  83. void SendByte(uchar c)
  84. {
  85.     uchar BitCnt;

  86.     for(BitCnt = 0;BitCnt < 8;BitCnt++)      
  87.     {
  88.         if((c << BitCnt) & 0x80)
  89.             SDA = 1;                     
  90.         else
  91.             SDA = 0;               
  92.           delayus(1);
  93.           SCL = 1;                           
  94.           delayus(5);                     
  95.           SCL = 0;
  96.     }

  97.     delayus(2);
  98.     SDA = 1;                              
  99.     delayus(2);  
  100.     SCL = 1;
  101.     delayus(3);
  102.     if(SDA == 1)
  103.                         ack = 0;   
  104.     else
  105.                         ack = 1;                             
  106.     SCL = 0;
  107.     delayus(2);
  108. }

  109. uchar RcvByte()
  110. {
  111.    uchar retc;
  112.    uchar BitCnt;

  113.    retc = 0;
  114.    SDA = 1;
  115.    for(BitCnt = 0;BitCnt < 8;BitCnt++)
  116.    {
  117.         delayus(1);  
  118.         SCL = 0;                     
  119.         delayus(5);           
  120.         SCL = 1;
  121.         delayus(3);
  122.         retc = retc << 1;
  123.         if(SDA == 1)
  124.             retc = retc + 1;           
  125.         delayus(2);
  126.    }
  127.    SCL = 0;
  128.    delayus(2);
  129.    return(retc);
  130. }

  131. void Ack_I2C(bit a)
  132. {
  133.     if(a == 0)
  134.                         SDA = 0;            
  135.     else
  136.                         SDA = 1;
  137.                
  138.     delayus(3);     
  139.     SCL = 1;
  140.     delayus(5);           
  141.     SCL = 0;         
  142.     delayus(2);   
  143. }


  144. uchar write_byte(uchar addr, uchar write_data)
  145. {
  146.     Start_I2C();
  147.     SendByte(DS3231_WriteAddress);
  148.     if (ack == 0)
  149.                         return 0;

  150.     SendByte(addr);   
  151.     if (ack == 0)
  152.                         return 0;

  153.     SendByte(write_data);
  154.     if (ack == 0)
  155.                         return 0;

  156.     Stop_I2C();
  157.     delayus(10);
  158.                         return 1;
  159. }


  160. uchar read_current()
  161. {
  162.     uchar read_data;
  163.     Start_I2C();
  164.     SendByte(DS3231_ReadAddress);
  165.     if(ack == 0)
  166.                         return(0);

  167.     read_data = RcvByte();
  168.     Ack_I2C(1);
  169.     Stop_I2C();
  170.                
  171.     return read_data;
  172. }


  173. uchar read_random(uchar random_addr)
  174. {
  175.     Start_I2C();
  176.     SendByte(DS3231_WriteAddress);
  177.     if(ack == 0)
  178.                         return(0);

  179.     SendByte(random_addr);
  180.     if(ack == 0)
  181.                         return(0);

  182.     return(read_current());
  183. }

  184. /********************************************************************
  185. * Ãû3Æ : delay_140us()
  186. * 1|Äü : Ñóê±
  187. * êäèë : void
  188. * êä3ö : ÎT
  189. **************************************************************/  
  190. void delay_140us()  
  191. {  
  192.     int i;
  193.     for(i = 0; i < 20; i++)  
  194.       _nop_();  
  195. }  
  196. /********************************************************************
  197. * Ãû3Æ : void ModifyTime(uchar hou,uchar min,uchar sec)
  198. * 1|Äü : DT¸Ä걼䣨諣©
  199. * êäèë : void
  200. * êä3ö : ÎT
  201. **************************************************************/
  202. void ModifyTime(uchar hou, uchar min,uchar sec)
  203. {
  204.     uchar temp = 0;

  205.     temp = HEX2BCD(hou);
  206.     write_byte(DS3231_HOUR, temp);   //éèÖÃê±

  207.     temp = HEX2BCD(min);
  208.     write_byte(DS3231_MINUTE, temp); //éèÖ÷Ö

  209.     temp = HEX2BCD(sec);
  210.     write_byte(DS3231_SECOND, temp); //éèÖÃÃë
  211. }
  212. /********************************************************************
  213. * Ãû3Æ : void ModifyTime(uchar hou,uchar min,uchar sec)
  214. * 1|Äü : DT¸Ä걼䣨걣©
  215. * êäèë : void
  216. * êä3ö : ÎT
  217. **************************************************************/
  218. void ModifyHour(hour)
  219. {
  220.           uchar temp = HEX2BCD(hour);
  221.     write_byte(DS3231_HOUR, temp);   //éèÖÃê±
  222. }
  223. /********************************************************************
  224. * Ãû3Æ : void Modifymin(minute)
  225. * 1|Äü : DT¸Ä걼䣨·Ö£©
  226. * êäèë : void
  227. * êä3ö : ÎT
  228. **************************************************************/
  229. void ModifyMinute(minute)
  230. {   
  231.           uchar temp = HEX2BCD(minute);
  232.     write_byte(DS3231_MINUTE, temp); //éèÖ÷֠ 
  233. }
  234. /********************************************************************
  235. * Ãû3Æ : void ModifyTime(uchar hou,uchar min,uchar sec)
  236. * 1|Äü : DT¸Ä걼䣨Ã룩
  237. * êäèë : void
  238. * êä3ö : ÎT
  239. **************************************************************/
  240. void ModifySecond(second)
  241. {
  242.           uchar temp = HEX2BCD(second);
  243.     write_byte(DS3231_SECOND, temp); //éèÖÃÃë
  244. }
  245. /********************************************************************
  246. * Ãû3Æ : void init()
  247. * 1|Äü : 3ìDò3õê¼»ˉ
  248. * êäèë : void
  249. * êä3ö : ÎT
  250. **************************************************************/  
  251. void init()
  252. {
  253.                 TMOD = 0x02;
  254.                 TH0 = 0x06;
  255.                 TL0 = 0x06;
  256.                 TR0 = 1;
  257.                 ET0 = 1;
  258.                 EA = 1;
  259. }
  260. /********************************************************************
  261. * Ãû3Æ : void setZero()
  262. * 1|Äü : è«2¿Çåá㣬ËùóDμƶ¼2»áá
  263. * êäèë : void
  264. * êä3ö : ÎT
  265. **************************************************************/  
  266. void setZero()
  267. {
  268.         flag1 = 0;
  269.         flag2 = 0;
  270.         flag3 = 0;
  271.         flag4 = 0;
  272.         flag5 = 0;
  273.         flag6 = 0;
  274.         flag7 = 0;
  275.         flag8 = 0;
  276.         flag9 = 0;
  277.         flag10 = 0;
  278.         flag11 = 0;
  279.         flag12 = 0;
  280. }
  281. /********************************************************************
  282. * Ãû3Æ : void light(uint number, uint level)
  283. * 1|Äü : Ö¸¶¨μÆáá
  284. * êäèë : uint number, uint level
  285. * êä3ö : ÎT
  286. **************************************************************/  
  287. void light(uint number, uint level)
  288. {
  289.                 switch(number)
  290.                 {
  291.                         case 0:
  292.                                         flag12 = level;
  293.                         break;
  294.                         case 1:
  295.                                         flag1 = level;
  296.                         break;
  297.                         case 2:
  298.                                         flag2 = level;
  299.                         break;
  300.                         case 3:
  301.                                         flag3 = level;
  302.                         break;
  303.                         case 4:
  304.                                         flag4 = level;
  305.                         break;
  306.                         case 5:
  307.                                         flag5 = level;
  308.                         break;
  309.                         case 6:
  310.                                         flag6 = level;
  311.                         break;
  312.                         case 7:
  313.                                         flag7 = level;
  314.                         break;
  315.                         case 8:
  316.                                         flag8 = level;
  317.                         break;
  318.                         case 9:
  319.                                         flag9 = level;
  320.                         break;
  321.                         case 10:
  322.                                         flag10 = level;
  323.                         break;
  324.                         case 11:
  325.                                         flag11 = level;
  326.                         break;
  327.                         default:break;
  328.                 }
  329. }
  330. /********************************************************************
  331. * Ãû3Æ : void computer_and_display_time()
  332. * 1|Äü : ÏÔê¾ê±¼ä
  333. * êäèë : void
  334. * êä3ö : ÎT
  335. **************************************************************/  
  336. void compute_and_display_time()
  337. {
  338.                 //¼ÆËãê±¼ä
  339.     uchar Htemp1, Htemp2, Mtemp1, Mtemp2, Stemp1, Stemp2;
  340.     Htemp1 = read_random(DS3231_HOUR);    //»ñè¡ê±
  341.     Htemp1&=0x3f;                  
  342.     Htemp2 = BCD2HEX(Htemp1);
  343.        
  344.     Mtemp1 = read_random(DS3231_MINUTE);  //»ñè¡·Ö
  345.     Mtemp2 = BCD2HEX(Mtemp1);
  346.                        
  347.           Stemp1 = read_random(DS3231_SECOND);  //»ñè¡Ãë
  348.     Stemp2 = BCD2HEX(Stemp1);
  349.        
  350.                 hour = Htemp2 % 12;
  351.                 minute = Mtemp2 / 5;
  352.                 second = Stemp2 / 5;

  353.                 //update hour
  354.                 if(hour != lastHour){
  355.                         light(hour, 40);
  356.                 }
  357.                 //update minute
  358.                 if(minute != lastMinute){
  359.                         if(minute != hour)
  360.                                 light(minute, 30);
  361.                 }
  362.                 //update second
  363.                 if(second != lastSecond){
  364.                         if(second != hour && second != minute)
  365.                                 light(second, 1);
  366.                 }
  367.                 if(lastHour != hour && lastHour != minute && lastHour != second)
  368.                         light(lastHour, 0);
  369.                 if(lastMinute != hour && lastMinute != minute && lastMinute != second)
  370.                         light(lastMinute, 0);
  371.                 if(lastSecond != hour && lastSecond != minute && lastSecond != second)
  372.                         light(lastSecond, 0);
  373.                
  374.                 lastHour = hour;
  375.                 lastMinute = minute;
  376.                 lastSecond = second;
  377. }
  378. /********************************************************************
  379. * Ãû3Æ : timer0()
  380. * 1|Äü : PWMμ÷ÕûÕ¼¿Õ±è,0~10, áá¶èμY¼õ
  381. * êäèë : void
  382. * êä3ö : ÎT
  383. **************************************************************/  
  384. void timer0() interrupt 1
  385. {
  386.         static unsigned int count;
  387.         count++;
  388.         if(count == 50)
  389.         {
  390.                 count = 0;
  391.                 c1 = 1;
  392.                 c2 = 1;
  393.                 c3 = 1;
  394.                 c4 = 1;
  395.                 c5 = 1;
  396.                 c6 = 1;
  397.                 c7 = 1;
  398.                 c8 = 1;
  399.                 c9 = 1;
  400.                 c10 = 1;
  401.                 c11 = 1;
  402.                 c12 = 1;
  403.         }

  404.         if(flag12 != 0 && flag12 == count)
  405.                 c12 = 0;
  406.         else if(flag1 != 0 && flag1 == count)
  407.                 c1 = 0;
  408.         else if(flag2 != 0 && flag2 == count)
  409.                 c2 = 0;
  410.         else if(flag3 != 0 && flag3 == count)
  411.                 c3 = 0;
  412.         else if(flag4 != 0 && flag4 == count)
  413.                 c4 = 0;
  414.         else if(flag5 != 0 && flag5 == count)
  415.                 c5 = 0;
  416.         else if(flag6 != 0 && flag6 == count)
  417.                 c6 = 0;
  418.         else if(flag7 != 0 && flag7 == count)
  419.                 c7 = 0;
  420.         else if(flag8 != 0 && flag8 == count)
  421.                 c8 = 0;
  422.         else if(flag9 != 0 && flag9 == count)
  423.                 c9 = 0;
  424.         else if(flag10 != 0 && flag10 == count)
  425.                 c10 = 0;
  426.         else if(flag11 != 0 && flag11 == count)
  427.                 c11 = 0;
  428. }
  429. /***********************************************************
  430. *****
  431. ***** Ö÷oˉêy
  432. *****
  433. ***********************************************************/
  434. void main()
  435. {
  436.         init();
  437.         setZero();
  438. //        ModifyHour(16);
  439. //        ModifyMinute(24);
  440.         while(1)
  441.         {
  442.                         compute_and_display_time();
  443.         }
  444. }
复制代码


5.焊接:(从代码里可以看出怎么接线,所以就不再废话了。)





拆了个旧风扇,搞定外壳。有没有外壳其实无所谓。




6.半成品:


7.成品图:(没有工具制作合适的外壳所以只能PS假装一下)


回复

使用道具 举报

发表于 2017-2-28 15:31:54 | 显示全部楼层
讚 讚 讚 , 頂一個
回复 支持 反对

使用道具 举报

发表于 2017-3-1 09:29:05 | 显示全部楼层
很有创意,谢谢分享!
回复 支持 反对

使用道具 举报

发表于 2017-3-1 17:28:49 | 显示全部楼层
666666666666666
回复 支持 反对

使用道具 举报

发表于 2017-3-2 21:25:22 | 显示全部楼层
很有想象力
回复 支持 反对

使用道具 举报

发表于 5 天前 | 显示全部楼层
厉害了,楼主好人
回复 支持 反对

使用道具 举报

高级模式  
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊 ( 浙ICP备09023225号  

GMT+8, 2017-4-26 15:49 , Processed in 0.251416 second(s), 11 queries , File On.

Powered by Discuz! X3.3 Licensed

© 2001-2017 Comsenz Inc.

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