功能描述:
1、 按键调时间, 设置闹钟
2、 带备用电池(断电继续走时)
3、 阳历、 农历节日提醒; 可显示上午、 中午、 晚上、 午夜、 深夜等时间段
4、 温湿度实时显示(可替换其他传感器数据显示)
5、 功能扩展: 语音播报万年历、 温湿度等。(此项功能为扩展功能)
☆已作出的实物优酷视频演示地址:
http://v.youku.com/v_show/id_XMTU0MjI4OTExNg==.html
[1]GPS 自动授时系统 语音报时/播报温湿度
实现功能:
1.可设置授时模式为自动授时和手动更新
2.可脱离 GPS 数据利用本地时钟芯片准确走时
3.可设置静音模式、 整点报时和自动语音播报温湿度及其混合模式等四种语音工作模式
4.可以切换显示本地时间和温湿度数据和 GPS 卫星时间数据和定位数据
5.经过分析 GPS 数据, 利用算法缩短了解析时间在秒级时间内就能获取到 GPS 时间数据(正常情况下, 完成定位需要几分钟以上)
6.(亮点) 利用算法自动计算星期参数和农历参数, 程序内部算法输入任何阳历日期数据即可得到准确的
星期数据和农历数据
7.利用 12864 串口工作模式, 节省了 8 个 IO
8.可进行功能定制
☆已作出的实物优酷视频演示地址:
http://v.youku.com/v_show/id_XMjY4OTkyNjk4NA==.html
步骤如下:lcd电子钟如何调时间
1、修改时间和日期
按下设置移动按钮,钟面年份开始闪烁,再按设置移动按钮,月份开始闪烁;再按设置移动按钮,日期开始闪烁;再按设置移动按钮,小时开始闪烁,按下修改按钮,可向上增加时间;再按设置移动按钮,分钟数字开始闪烁,按下修改按钮,可向上增加分钟。
2、完成调整后,按下退出按钮,就进入正常显示
各种电子钟设置方法基本相似,有五个按钮的,修改有上调、下调两个按钮。万年历显示信息分上下两部分,屏幕上半部分固定显示时间,下半部分轮流显示日期、星期、温度、农历日期以及24节气。信息轮流显示的时间间隔固定为5秒,不可调整。万年历配备两组闹钟。系统有备用电池,在断电的情况下依然可以保证正确计时,保持时间视电池电量而定,通常短时间断电不会出现时间丢失的情况。
3、电子钟日历调整
如果是万年历那种,侧面有四个按键,从上到下叫ABCD,先按住A一会儿,表盘年月日星期等开始闪动。哪个闪动,按B就是往上加数字,按C就是往下减,以此类推都可以调整了,调整完不动它,过一会恢复正常走时了!
4、电子钟时间调整
先按一下“调整”按钮,数字开始闪动。想调哪一个数就多按几次,按到的这个数就会闪动。再用“上调”、或者“下调”来调整。在正常的显示下,按一下“闹钟”按钮,会在“开”和“关”之间转换。按一下“喇叭”按钮,会在“开”和“关”的功能切换。最后按复位。
5、先按一下“设置”键
进入时间设置状态,同时年份“闪烁”,可按“上调”或“流水(下调)”键修改年份,修改好后按“设置”键将闪烁位移到公历“月”,按“上调”或“流水(下调)”键修改月份;用同样的方法可对日、时、分、秒进行设置;星期、农历月、日将自动跟随公历的变化而变化。
6、再按“设置”或“退出”
退出时间设置,回到正常时间状态。
7、查看说明书
众所周知,说明书是每个物品必有的一个最全面的教科书,如果还有不理解的可以参考说明书上的内容。
#include<reg52.h>#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit dq=P3^7 //////18b20
sbit lcden=P2^7////lcd
sbit rs=P2^6
sbit wr=P2^5
sbit sck=P3^6 ////1302
sbit sda=P3^4
sbit rst=P3^5
sbit a=P1^0
sbit b=P1^1
sbit c=P1^2
sbit d=P1^3
sbit kj=P1^4
sbit beep=P1^5
uchar ritime
uchar startflag
uchar ridate[33]
uchar bitnum
uchar rireceok
uchar ricode[4]
uchar riprosok
uchar dis[8]
void dis_key(void)
void riwork(void)
void ripros(void)
void keyscan(void)
void bep(void)
void timer0init(void)
void init0init(void)
uchar key0,key1,key2,key0num,passwordok
uchar key,p,m,pnum,sha
uchar password[9]
uchar password1[9]={6,7,4,6,8,8,6,4,6}
void password_scan()
void post_key()
void dj1()
void dj2()
//////////////////////函数声明1302
void wr1302_byte(uchar byte)
void wr1302 (uchar add,uchar dat)
uchar read1302(uchar add)
uchar time_date[7]={10,3,12,8,21,37,20}////年周月日时分秒
uchar time_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80}////写入地址
uchar read_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81}////读出地址
uchar disp[13] ////将读出时间装入
void set_rtc()
void read_rtc()
void timepost() ////处理时间为10进制
void display()
void password_display()
void timeplay()
void runnian1()///闰年加
void runnian2() ///闰年减
void keypost() //按键处理
///////////////////////////// 函数声明 lcd ////////////////////
uchar code lcd_tab[]="0123456789- ():c"
uchar code lcd_tab1[]="Plese Password:"
uchar code table1[]="key=00-00-00-00"
uchar code table[]=" QQ:674688646"
uchar code numtab[]="0123456789ABCDEF"
uchar code numtab1[]=" 1234567890"
void delay(uint z)
void init_lcd()
void write_com(uchar com)
void write_date(uchar x)
///////////////////////////18b20////////////
void init18b20(void)
void wr1820_byte(uchar dat)
uchar read18b20_byte(void)
uchar read1820(void)
void delay1(uint t)
//////////////////////////////////////////
void timer0init(void) //开定时器2
{
TMOD=0X02
TH0=0X00
TL0=0X00
ET0=1
EA=1
TR0=1
}
void init0init(void) //外部中断
{
IT0=1
EX0=1
EA=1
}
void riwork(void)
{
dis[0]=ricode[0]/16
dis[1]=ricode[0]%16
dis[2]=ricode[1]/16
dis[3]=ricode[1]%16
dis[4]=ricode[2]/16
dis[5]=ricode[2]%16
dis[6]=ricode[3]/16
dis[7]=ricode[3]%16
}
void ripros(void)
{ uchar j,k,i,value
k=1
for(j=0j<4j++)
{
for(i=0i<8i++)
{
value=value>>1
if(ridate[k]>6)
{
value=value|0x80
}
k++
}
ricode[j]=value
}
riprosok=1
}
void timer0 () interrupt 1
{
ritime++
}
void int0() interrupt 0
{
if(startflag==1)
{
if(ritime>32)//检测引导码
{
bitnum=0
}
ridate[bitnum]=ritime
ritime=0
bitnum++
if(bitnum==33)
{
bitnum=0
rireceok=1
}
}
else
{
startflag=1
ritime=0
}
}
void keyscan(void)
{ if(rireceok==1)
{bep() //按键发声 但影响蜂鸣器 *** 作
ripros()
rireceok=0
}
if(riprosok==1)
{ riwork()
riprosok=0
switch(ricode[2])
{ case 0x46:p=1pnum++break
case 0x0c:key=1break
case 0x18:key=2break
case 0x5e:key=3break
case 0x08:key=4break
case 0x1c:key=5break
case 0x5a:key=6break
case 0x42:key=7break
case 0x52:key=8break
case 0x4a:key=9break
case 0x16:key=10break
case 0x09:key0=1key0num++break
case 0x15:key1=1break
case 0x07:sha=1key2=1break
if(key0==1){if(key0num==1)read_rtc()}
}
}
////按下设定键后读一次1302保证time_date内数据正常
}
void bep(void)
{
beep=0delay(100)beep=1
}
///////////////////////////////////////////////////////////
void write_com(uchar com) /////写命令
{
rs=0
P0=com
lcden=1
delay(5)
lcden=0
}
void write_date(uchar x)/////写数据
{
rs=1
P0=x
delay(5)
lcden=1
delay(5)
lcden=0
}
void init_lcd()// ///lcd初始化
{
wr=0
lcden=0
write_com(0x38)
write_com(0x0c)
write_com(0x06)
write_com(0x01)
}
void display()
{timepost()
write_com(0x80+2)
write_date(lcd_tab[2])
write_date(lcd_tab[0])
write_date(lcd_tab[disp[0]])
write_date(lcd_tab[disp[1]])
write_date(lcd_tab[10])
write_date(lcd_tab[disp[3]])
write_date(lcd_tab[disp[4]])
write_date(lcd_tab[10])
write_date(lcd_tab[disp[5]])
write_date(lcd_tab[disp[6]])
write_date(lcd_tab[11])
write_date(lcd_tab[12])
write_date(lcd_tab[disp[2]])
write_date(lcd_tab[13])
write_com(0x80+0x40+4)/////////第二行
write_date(lcd_tab[disp[7]])
write_date(lcd_tab[disp[8]])
write_date(lcd_tab[14])
write_date(lcd_tab[disp[9]])
write_date(lcd_tab[disp[10]])
write_date(lcd_tab[14])
write_date(lcd_tab[disp[11]])
write_date(lcd_tab[disp[12]])
write_date(lcd_tab[11])
write_date(lcd_tab[read1820()/10])/////显示温度
write_date(lcd_tab[read1820()%10])
write_date(lcd_tab[15])
}
//////////////// 1302 //////////////////////////////
void wr1302_byte(uchar byte) /////写入一个字节
{ uchar i
for(i=0i<8i++)
{ sck=0
sda=byte&0x01
byte>>=1
sck=1
}
}
void wr1302 (uchar add,uchar dat)/////写进1302 时间和地址
{ rst=0
_nop_()
sck=0
_nop_()
rst=1
_nop_()
wr1302_byte(add)
wr1302_byte(dat)
rst=0
//_nop_()
//sda=1
//sck=1
}
uchar read1302(uchar add)
{ uchar i,temp
rst=0
_nop_()
sck=0
_nop_()
rst=1
_nop_()
wr1302_byte(add)////////////////////写入要读的地址
for(i=0i<8i++)
{
if(sda)temp=temp|0x80
sck=0
temp>>=1
_nop_()
sck=1
}
rst=0 //////// 延时很重要
_nop_()
sck=0
_nop_()
sck=1
_nop_()
sda=0
_nop_()
sda=1
_nop_()
return temp
}
void set_rtc()
{
uchar i,j
for(i=0i<7i++)
{
j=time_date[i]/10 ///////将10进制变成16进制
time_date[i]=time_date[i]%10
time_date[i]=time_date[i]+j*16
}
wr1302(0x8e,0x00)//////去除写保护
for(i=0i<7i++)
{
wr1302(time_add[i],time_date[i])
}
wr1302(0x8e,0x80)//////加写保护
}
void read_rtc()
{uchar i,j
for(i=0i<7i++)
{
time_date[i]=read1302(read_add[i])
////将读到的bcd码转化成10进制码
j=time_date[i]&0x0f
time_date[i]>>=4
time_date[i]&=0x0f
time_date[i]*=10
time_date[i]=time_date[i]+j
}
}
void timepost()
{ disp[0]=time_date[0]/10/////年
disp[1]=time_date[0]%10
disp[2]=time_date[1]%10/////周
disp[3]=time_date[2]/10/////月
disp[4]=time_date[2]%10/////
disp[5]=time_date[3]/10/////日
disp[6]=time_date[3]%10////
disp[7]=time_date[4]/10////时
disp[8]=time_date[4]%10////
disp[9]=time_date[5]/10////分
disp[10]=time_date[5]%10////
disp[11]=time_date[6]/10////秒
disp[12]=time_date[6]%10////
}
void delay(uint z)
{
uint x,y
for(x=0x<20x++)
for(y=zy>0y--)
}
/////////////////////////18b20////////
void delay1(uint t)
{
while (t--)
}
void init18b20(void)
{
uchar n
dq=1
delay1(8)
dq=0
delay1(80)
dq=1
delay1(8)
n=dq
delay1(4)
}
void wr18b20_byte(uchar dat)
{
uchar i
for(i=0i<8i++)
{
dq=0
dq=dat&0x01
delay1(4)
dq=1
dat>>=1
}
delay1(4)
}
uchar read18b20_byte(void)
{
uchar i,value
for(i=0i<8i++)
{ dq=0
value>>=1
dq=1
if(dq)
value|=0x80
delay1(4)
}
return value
}
uchar read1820(void)
{ uchar a,b
init18b20()
wr18b20_byte(0xcc)
wr18b20_byte(0x44)
delay1(50)
init18b20()
wr18b20_byte(0xcc)
wr18b20_byte(0xbe)
a=read18b20_byte()
b=read18b20_byte()
b<<=4
b+=(a&0xf0)>>4
return b
}
///////////////////////////////////////////////////////
void keypost()
{ uchar n
if(key0==1)
{
if(key0num==1)
{write_com(0x80+0x40+10)
write_com(0x0f)delay(1000)
if(key1==1)
{ key1=0n=1
time_date[6]++
if(time_date[6]==60)time_date[6]=0
display()
}
if(key2==1)
{
key2=0n=1
time_date[6]--
if(time_date[6]==-1)time_date[6]=59
display()
}
}
if(key0num==2)
{write_com(0x80+0x40+8)
write_com(0x0f)delay(1000)
if(key1==1)
{ key1=0n=1
time_date[5]++
if(time_date[5]==60)time_date[5]=0
display()
}
if(key2==1)
{
key2=0n=1
time_date[5]--
if(time_date[5]==-1)time_date[5]=59
display()
}
}
if(key0num==3)
{write_com(0x80+0x40+5)
write_com(0x0f)delay(1000)
if(key1==1)
{ key1=0n=1
time_date[4]++
if(time_date[4]==24)time_date[4]=0
display()
}
if(key2==1)
{
key2=0n=1
time_date[4]--
if(time_date[4]==-1)time_date[4]=23
display()
}
}
if(key0num==4)
{write_com(0x80+14)
write_com(0x0f)delay(1000)
if(key1==1)
{ key1=0n=1
time_date[1]++
if(time_date[1]==8)time_date[1]=1
display()
}
if(key2==1)
{
key2=0n=1
time_date[1]--
if(time_date[1]==0)time_date[1]=7
display()
}
}
if(key0num==5)
{write_com(0x80+10)
write_com(0x0f)delay(1000)
if(key1==1)
{ key1=0n=1
time_date[3]++
runnian1()
display()
}
if(key2==1)
{
key2=0n=1
time_date[3]--
if(time_date[3]<1)time_date[3]=31
runnian2()
display()
}
}
if(key0num==6)
{write_com(0x80+7)
write_com(0x0f)delay(1000)
if(key1==1)
{ key1=0n=1
time_date[2]++
if(time_date[2]>12)time_date[2]=1
runnian2()
display()
}
if(key2==1)
{
key2=0n=1
time_date[2]--
if(time_date[2]==0)time_date[2]=12
runnian2()
display()
}
}
if(key0num==7)
{write_com(0x80+4)
write_com(0x0f)delay(1000)
if(key1==1)
{ key1=0n=1
time_date[0]++
if(time_date[0]==100)time_date[0]=0
runnian2()
display()
}
if(key2==1)
{
key2=0n=1
time_date[0]--
if(time_date[0]==-1)time_date[0]=99
runnian2()
display()
}
}
if(key0num==8)
{ key0num=0key0=0
write_com(0x0c)
if(n){n=0set_rtc()}
}
}
else
{
read_rtc()
timepost()
display()
if(time_date[5]==0)///整点报时
{if(time_date[6]==0)beep=0
else beep=1
}
}
}
void runnian1()////闰年加
{
if(time_date[2]==2) /////判断2月
{ if((time_date[0]+4)%4==0)
{ if(time_date[3]>29)time_date[3]=1}//判断闰年
else
{if(time_date[3]>28)time_date[3]=1}
}
else
{ if(time_date[2]<8)///判断月小于8
{
if((time_date[2]+1)%2==0)
{if(time_date[3]>31)time_date[3]=1}
else
{if(time_date[3]>30)time_date[3]=1}
}
if(time_date[2]>7)
{
if((time_date[2])%2==0)
{if(time_date[3]>31)time_date[3]=1}
else
{if(time_date[3]>30)time_date[3]=1}
}
}
}
void runnian2()//闰年减
{
if(time_date[2]==2) /////判断2月
{ if((time_date[0]+4)%4==0)
{ if(time_date[3]>29)time_date[3]=29}//判断闰年
else
{if(time_date[3]>28)time_date[3]=28}
}
else
{
if(time_date[2]<8)///判断月小于8
{
if((time_date[2]+1)%2==0)
{if(time_date[3]>31)time_date[3]=31}
else
{if(time_date[3]>30)time_date[3]=30}
}
if(time_date[2]>7)
{
if((time_date[2])%2==0)
{if(time_date[3]>31)time_date[3]=31}
else
{if(time_date[3]>30)time_date[3]=30}
}
}
}
void password_scan() ////////输入密码界面
{uchar l,i,j
write_com(0x80)
for(l=0l<15l++)
{write_date(lcd_tab1[l])}
write_com(0x80+0x40+4+i)
write_com(0x0f)delay(1000)
if(key!=0)
{
password[i]=key
write_com(0x80+0x40+4+i)
write_date(numtab1[key])
write_com(0x14)
i++key=0
}
if(i>0)
{if(sha==1)
{sha=0i--
write_com(0x80+0x40+4+i)
write_date(numtab1[0])
write_com(0x10)
}
}
if(i==9)
{ i=0
for(j=0j<9j++)
{
if(password1[j]==password[j])m++
else {init_lcd()m=0break}
}
if(m==9)
{
m=0passwordok=1
p=0pnum=0key=0
init_lcd()
for(i=0i<15i++)
{write_date(table[i])}
write_com(0x80+0x40)
for(i=0i<15i++)
{write_date(table1[i])}
}
}
}
void dis_key(void) //显示键值
{
write_com(0x80+0x40+4)
write_date(numtab[dis[0]])
write_date(numtab[dis[1]])
write_com(0x80+0x40+7)
write_date(numtab[dis[2]])
write_date(numtab[dis[3]])
write_com(0x80+0x40+10)
write_date(numtab[dis[4]])
write_date(numtab[dis[5]])
write_com(0x80+0x40+13)
write_date(numtab[dis[6]])
write_date(numtab[dis[7]])
}
void timeplay()
{
if(p==1)
{ uchar vkey0num=0key0=0
if(v==0){v=1init_lcd()key=0}
if(pnum==1)
{
password_scan()
}
if(pnum==2)
{ p=0pnum=0m=0v=0
init_lcd()
}
}
else keypost()
}
//////////////////////////主函数////////////////////////
void main()
{
init_lcd() /////初始化lcd
timer0init()///// 开定时器中断
init0init()///// 开外部器中断
key=0
while(1)
{
keyscan()
if(passwordok)
{ dis_key()
post_key()
if(p==1)
{ if(pnum==1)
{if(ricode[2]!=0x46)pnum=0}
if(pnum==2)
{pnum=0m=0
passwordok=0p=0
break
}
}
}
else timeplay()
}
}
void post_key()
{
if(key==1){key=0kj=0}
if(key==2){key=0kj=1}
if(key==3){key=0dj1()}
if(key==4){key=0dj2()}
}
void dj1()
{
uint i
for(i=0i<512i++)
{if(rireceok==1)break
a=0b=0delay(20)
a=1b=0delay(20)
b=0c=0delay(20)
b=1c=0delay(20)
c=0d=0delay(20)
c=1d=0delay(20)
d=0a=0delay(20)
d=1delay(20)
}
}
void dj2()
{ uint i
for(i=0i<512i++)
{if(rireceok==1)break
d=0a=0delay(20)
a=1d=0delay(20)
c=0d=0delay(20)
c=0d=1delay(20)
b=0c=0delay(20)
c=1b=0delay(20)
a=0b=0delay(20)
a=0b=1delay(20)
}
}
使用方法 本程序用于HC6800 V2.6 实验箱,需要装上1602液晶屏,18b20 温度传感器,红外接收头,和步进电机,同时保证遥控器好用(要用配套的小遥控器并且要按键值和我的一样才能准确的 *** 作本程序)
我的遥控器按键值如下
ch-0x45 ch 0x46 ch+0x47
<<0x44 >>0x40 >= 0x43
- 0x07 + 0x15 EQ 0x09
0 0x16 100+ 0x19200+ 0x0d
1 0x0c 2 0x18 3 0x5e
4 0x08 5 0x1c 6 0x5a
7 0x42 8 0x52 9 0x4a
主要 *** 作键为 ch EQ + - 123456789 等键,
程序下进去后 1602会显示日期 时间 温度
用EQ键可对日期 时间进行设定
用+ - 键对日期时间进行调节
调节日期时会自动识别大小月,及闰年并对日期进行相应调整
按下ch键后 会进入输入密码界面 依次输入674688646 会进入按键读值界面 ,输入错误可用 - 键退回
在按键读值界面 连续按两次ch 键后,程序 会退出到时间显示界面
在按键读值界面 按1 打开继电器 按2 关闭继电器 按3 步进电机正转一周,按 4 步进电机反转一周 ,步进电机转的过程中按其他键,步进电机停止
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)