时间就像光一样,匆匆一撇却已远去,离去的时光怕是连光也望尘莫及。
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.下载代码: - #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; //ó|′e±ê־λ
- sbit SDA = P0^6; //Ä£ÄaI2Cêy¾Y′«ËíλSDA
- sbit SCL = P0^7; //Ä£ÄaI2Cê±Öó¿ØÖÆλ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Âë×a»»ÎaByte
- {
- uchar temp;
- temp = val & 0x0f;
- val >>= 4;
- val &= 0x0f;
- val *= 10;
- temp += val;
- return temp;
- }
- uchar HEX2BCD(uchar val) //BÂë×a»»ÎaBCDÂë
- {
- 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());
- }
- /********************************************************************
- * Ãû3Æ : delay_140us()
- * 1|Äü : Ñóê±
- * êäèë : void
- * êä3ö : ÎT
- **************************************************************/
- void delay_140us()
- {
- int i;
- for(i = 0; i < 20; i++)
- _nop_();
- }
- /********************************************************************
- * Ãû3Æ : void ModifyTime(uchar hou,uchar min,uchar sec)
- * 1|Äü : DT¸Ä걼䣨諣©
- * êäèë : void
- * êä3ö : ÎT
- **************************************************************/
- 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); //éèÖÃÃë
- }
- /********************************************************************
- * Ãû3Æ : void ModifyTime(uchar hou,uchar min,uchar sec)
- * 1|Äü : DT¸Ä걼䣨걣©
- * êäèë : void
- * êä3ö : ÎT
- **************************************************************/
- void ModifyHour(hour)
- {
- uchar temp = HEX2BCD(hour);
- write_byte(DS3231_HOUR, temp); //éèÖÃê±
- }
- /********************************************************************
- * Ãû3Æ : void Modifymin(minute)
- * 1|Äü : DT¸Ä걼䣨·Ö£©
- * êäèë : void
- * êä3ö : ÎT
- **************************************************************/
- void ModifyMinute(minute)
- {
- uchar temp = HEX2BCD(minute);
- write_byte(DS3231_MINUTE, temp); //éèÖ÷Ö
- }
- /********************************************************************
- * Ãû3Æ : void ModifyTime(uchar hou,uchar min,uchar sec)
- * 1|Äü : DT¸Ä걼䣨Ã룩
- * êäèë : void
- * êä3ö : ÎT
- **************************************************************/
- void ModifySecond(second)
- {
- uchar temp = HEX2BCD(second);
- write_byte(DS3231_SECOND, temp); //éèÖÃÃë
- }
- /********************************************************************
- * Ãû3Æ : void init()
- * 1|Äü : 3ìDò3õê¼»ˉ
- * êäèë : void
- * êä3ö : ÎT
- **************************************************************/
- void init()
- {
- TMOD = 0x02;
- TH0 = 0x06;
- TL0 = 0x06;
- TR0 = 1;
- ET0 = 1;
- EA = 1;
- }
- /********************************************************************
- * Ãû3Æ : void setZero()
- * 1|Äü : è«2¿Çåá㣬ËùóDμƶ¼2»áá
- * êäèë : void
- * êä3ö : ÎT
- **************************************************************/
- 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;
- }
- /********************************************************************
- * Ãû3Æ : void light(uint number, uint level)
- * 1|Äü : Ö¸¶¨μÆáá
- * êäèë : uint number, uint level
- * êä3ö : ÎT
- **************************************************************/
- 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;
- }
- }
- /********************************************************************
- * Ãû3Æ : void computer_and_display_time()
- * 1|Äü : ÏÔê¾ê±¼ä
- * êäèë : void
- * êä3ö : ÎT
- **************************************************************/
- 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;
- }
- /********************************************************************
- * Ãû3Æ : timer0()
- * 1|Äü : PWMμ÷ÕûÕ¼¿Õ±è,0~10, áá¶èμY¼õ
- * êäèë : void
- * êä3ö : ÎT
- **************************************************************/
- 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;
- }
- /***********************************************************
- *****
- ***** Ö÷oˉêy
- *****
- ***********************************************************/
- void main()
- {
- init();
- setZero();
- // ModifyHour(16);
- // ModifyMinute(24);
- while(1)
- {
- compute_and_display_time();
- }
- }
复制代码
5.焊接:(从代码里可以看出怎么接线,所以就不再废话了。)
拆了个旧风扇,搞定外壳。有没有外壳其实无所谓。
6.半成品:
7.成品图:(没有工具制作合适的外壳所以只能PS假装一下)
|