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假装一下)
新闻热点
疑难解答