【51单片机】时光钟 - 一寸光阴一寸光
2017-02-28 15:09
190 查看
**时间就像光一样,匆匆一撇却已远去,离去的时光怕是连光也望尘莫及。**
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. 奶茶店的透明吸管
PS:根据自己的喜好选择led的颜色即可,但是注意不同波长的led形成的光束有别,有些会比较不明显。
4.51单片机程序:
#include <reg52.h> #include <intrins.h> #define uchar unsigned char #define uint unsigned int #define DS3231_WriteAddress 0xD0 #define DS3231_ReadAddress 0xD1 #define DS3231_SECOND 0x00 #define DS3231_MINUTE 0x01 #define DS3231_HOUR 0x02 #define DS3231_WEEK 0x03 #define DS3231_DAY 0x04 #define DS3231_MONTH 0x05 #define DS3231_YEAR 0x06 bit ack; //Ó¦´ð±ê־λ sbit SDA = P0^6; //Ä£ÄâI2CÊý¾Ý´«ËÍλSDA sbit SCL = P0^7; //Ä£ÄâI2CʱÖÓ¿ØÖÆλSCL sbit c1 = P2^6; //Ã룬¸öλ sbit c2 = P2^5; //·Ö£¬¸öλ sbit c3 = P2^7; //Ã룬¸öλ sbit c4 = P2^3; //Ã룬¸öλ sbit c5 = P2^1; //Ã룬ʮλ sbit c6 = P2^0; //Ã룬¸öλ sbit c7 = P3^7; //Ã룬¸öλ sbit c8 = P3^6; //Ã룬¸öλ sbit c9 = P3^2; //Ã룬ʮλ sbit c10 = P1^5; //·Ö£¬Ê®Î» sbit c11 = P1^3; //ʱ£¬¸öλ sbit c12 = P1^2; //ʱ£¬Ê®Î» unsigned int flag1, flag2, flag3, flag4, flag5, flag6, flag7, flag8, flag9, flag10, flag11, flag12; unsigned char hour, minute, second; unsigned char lastHour = 24, lastMinute = 60, lastSecond = 60; void TM1637_start(); void TM1637_stop(); void TM1637_write1Bit(unsigned char mBit); void TM1637_write1Byte(unsigned char mByte); void TM1637_writeCammand(unsigned char mData); void TM1637_writeData(unsigned char addr, unsigned char mData); void time_set(char hour, char min); void time_display(); void timer0_init(); void setZero(); void delay_140us(); void delayus(uint us); uchar BCD2HEX(uchar val) //BCDÂëת»»ÎªByte { uchar temp; temp = val & 0x0f; val >>= 4; val &= 0x0f; val *= 10; temp += val; return temp; } uchar HEX2BCD(uchar val) //BÂëת»»ÎªBCDÂë { return (((val % 100) / 10) << 4) | (val % 10); } void delayus(uint us) { while(us--); } void Start_I2C() { SDA = 1; delayus(1); SCL = 1; delayus(5); SDA = 0; delayus(5); SCL = 0; delayus(2); } void Stop_I2C() { SDA = 0; delayus(1); SCL = 1; delayus(5); SDA = 1; delayus(4); } void SendByte(uchar c) { uchar BitCnt; for(BitCnt = 0;BitCnt < 8;BitCnt++) { if((c << BitCnt) & 0x80) SDA = 1; else SDA = 0; delayus(1); SCL = 1; delayus(5); SCL = 0; } delayus(2); SDA = 1; delayus(2); SCL = 1; delayus(3); if(SDA == 1) ack = 0; else ack = 1; SCL = 0; delayus(2); } uchar RcvByte() { uchar retc; uchar BitCnt; retc = 0; SDA = 1; for(BitCnt = 0;BitCnt < 8;BitCnt++) { delayus(1); SCL = 0; delayus(5); SCL = 1; delayus(3); retc = retc << 1; if(SDA == 1) retc = retc + 1; delayus(2); } SCL = 0; delayus(2); return(retc); } void Ack_I2C(bit a) { if(a == 0) SDA = 0; else SDA = 1; delayus(3); SCL = 1; delayus(5); SCL = 0; delayus(2); } uchar write_byte(uchar addr, uchar write_data) { Start_I2C(); SendByte(DS3231_WriteAddress); if (ack == 0) return 0; SendByte(addr); if (ack == 0) return 0; SendByte(write_data); if (ack == 0) return 0; Stop_I2C(); delayus(10); return 1; } uchar read_current() { uchar read_data; Start_I2C(); SendByte(DS3231_ReadAddress); if(ack == 0) return(0); read_data = RcvByte(); Ack_I2C(1); Stop_I2C(); return read_data; } uchar read_random(uchar random_addr) { Start_I2C(); SendByte(DS3231_WriteAddress); if(ack == 0) return(0); SendByte(random_addr); if(ack == 0) return(0); return(read_current()); } /******************************************************************** * Ãû³Æ : delay_140us() * ¹¦ÄÜ : ÑÓʱ * ÊäÈë : void * Êä³ö : ÎÞ **************************************************************/ void delay_140us() { int i; for(i = 0; i < 20; i++) _nop_(); } /******************************************************************** * Ãû³Æ : void ModifyTime(uchar hou,uchar min,uchar sec) * ¹¦ÄÜ : ÐÞ¸Äʱ¼ä£¨È«£© * ÊäÈë : void * Êä³ö : ÎÞ **************************************************************/ void ModifyTime(uchar hou, uchar min,uchar sec) { uchar temp = 0; temp = HEX2BCD(hou); write_byte(DS3231_HOUR, temp); //ÉèÖÃʱ temp = HEX2BCD(min); write_byte(DS3231_MINUTE, temp); //ÉèÖÃ·Ö temp = HEX2BCD(sec); write_byte(DS3231_SECOND, temp); //ÉèÖÃÃë } /******************************************************************** * Ãû³Æ : void ModifyTime(uchar hou,uchar min,uchar sec) * ¹¦ÄÜ : ÐÞ¸Äʱ¼ä£¨Ê±£© * ÊäÈë : void * Êä³ö : ÎÞ **************************************************************/ void ModifyHour(hour) { uchar temp = HEX2BCD(hour); write_byte(DS3231_HOUR, temp); //ÉèÖÃʱ } /******************************************************************** * Ãû³Æ : void Modifymin(minute) * ¹¦ÄÜ : ÐÞ¸Äʱ¼ä£¨·Ö£© * ÊäÈë : void * Êä³ö : ÎÞ **************************************************************/ void ModifyMinute(minute) { uchar temp = HEX2BCD(minute); write_byte(DS3231_MINUTE, temp); //ÉèÖÃ·Ö } /******************************************************************** * Ãû³Æ : void ModifyTime(uchar hou,uchar min,uchar sec) * ¹¦ÄÜ : ÐÞ¸Äʱ¼ä£¨Ã룩 * ÊäÈë : void * Êä³ö : ÎÞ **************************************************************/ void ModifySecond(second) { uchar temp = HEX2BCD(second); write_byte(DS3231_SECOND, temp); //ÉèÖÃÃë } /******************************************************************** * Ãû³Æ : void init() * ¹¦ÄÜ : ³ÌÐò³õʼ»¯ * ÊäÈë : void * Êä³ö : ÎÞ **************************************************************/ void init() { TMOD = 0x02; TH0 = 0x06; TL0 = 0x06; TR0 = 1; ET0 = 1; EA = 1; } /******************************************************************** * Ãû³Æ : void setZero() * ¹¦ÄÜ : È«²¿ÇåÁ㣬ËùÓеƶ¼²»ÁÁ * ÊäÈë : void * Êä³ö : ÎÞ **************************************************************/ void setZero() { flag1 = 0; flag2 = 0; flag3 = 0; flag4 = 0; flag5 = 0; flag6 = 0; flag7 = 0; flag8 = 0; flag9 = 0; flag10 = 0; flag11 = 0; flag12 = 0; } /******************************************************************** * Ãû³Æ : void light(uint number, uint level) * ¹¦ÄÜ : Ö¸¶¨µÆÁÁ * ÊäÈë : uint number, uint level * Êä³ö : ÎÞ **************************************************************/ void light(uint number, uint level) { switch(number) { case 0: flag12 = level; break; case 1: flag1 = level; break; case 2: flag2 = level; break; case 3: flag3 = level; break; case 4: flag4 = level; break; case 5: flag5 = level; break; case 6: flag6 = level; break; case 7: flag7 = level; break; case 8: flag8 = level; break; case 9: flag9 = level; break; case 10: flag10 = level; break; case 11: flag11 = level; break; default:break; } } /******************************************************************** * Ãû³Æ : void computer_and_display_time() * ¹¦ÄÜ : ÏÔʾʱ¼ä * ÊäÈë : void * Êä³ö : ÎÞ **************************************************************/ void compute_and_display_time() { //¼ÆËãʱ¼ä uchar Htemp1, Htemp2, Mtemp1, Mtemp2, Stemp1, Stemp2; Htemp1 = read_random(DS3231_HOUR); //»ñȡʱ Htemp1&=0x3f; Htemp2 = BCD2HEX(Htemp1); Mtemp1 = read_random(DS3231_MINUTE); //»ñÈ¡·Ö Mtemp2 = BCD2HEX(Mtemp1); Stemp1 = read_random(DS3231_SECOND); //»ñÈ¡Ãë Stemp2 = BCD2HEX(Stemp1); hour = Htemp2 % 12; minute = Mtemp2 / 5; second = Stemp2 / 5; //update hour if(hour != lastHour){ light(hour, 40); } //update minute if(minute != lastMinute){ if(minute != hour) light(minute, 30); } //update second if(second != lastSecond){ if(second != hour && second != minute) light(second, 1); } if(lastHour != hour && lastHour != minute && lastHour != second) light(lastHour, 0); if(lastMinute != hour && lastMinute != minute && lastMinute != second) light(lastMinute, 0); if(lastSecond != hour && lastSecond != minute && lastSecond != second) light(lastSecond, 0); lastHour = hour; lastMinute = minute; lastSecond = second; } /******************************************************************** * Ãû³Æ : timer0() * ¹¦ÄÜ : PWMµ÷ÕûÕ¼¿Õ±È,0~10, ÁÁ¶ÈµÝ¼õ * ÊäÈë : void * Êä³ö : ÎÞ **************************************************************/ void timer0() interrupt 1 { static unsigned int count; count++; if(count == 50) { count = 0; c1 = 1; c2 = 1; c3 = 1; c4 = 1; c5 = 1; c6 = 1; c7 = 1; c8 = 1; c9 = 1; c10 = 1; c11 = 1; c12 = 1; } if(flag12 != 0 && flag12 == count) c12 = 0; else if(flag1 != 0 && flag1 == count) c1 = 0; else if(flag2 != 0 && flag2 == count) c2 = 0; else if(flag3 != 0 && flag3 == count) c3 = 0; else if(flag4 != 0 && flag4 == count) c4 = 0; else if(flag5 != 0 && flag5 == count) c5 = 0; else if(flag6 != 0 && flag6 == count) c6 = 0; else if(flag7 != 0 && flag7 == count) c7 = 0; else if(flag8 != 0 && flag8 == count) c8 = 0; else if(flag9 != 0 && flag9 == count) c9 = 0; else if(flag10 != 0 && flag10 == count) c10 = 0; else if(flag11 != 0 && flag11 == count) c11 = 0; } /*********************************************************** ***** ***** Ö÷º¯Êý ***** ***********************************************************/ void main() { init(); setZero(); // ModifyHour(16); // ModifyMinute(24); while(1) { compute_and_display_time(); } }
5.焊接:(从代码里可以看出怎么接线,所以就不再赘述了。)
拆了个旧风扇,搞定外壳。有没有外壳其实无所谓。
6.半成品:
7.成品图:(没有工具制作合适的外壳所以只能PS假装一下)