您的位置:首页 > 其它

【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假装一下)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: