水电电工知识
电工技术|51单片机电子钟程序设计
2017-05-26  浏览:41
水电之家讯:硬件部分

基于51单片机、 ds1302时钟芯片、 ds18b20温度芯片、 以及1602液晶显示的 实时时间 和 实时温度显示 。同时可通过按键 设置 年、月、日、时、分、星期。并且可以设置闹钟 当闹钟时间到时 蜂鸣器持续发出 滴..声 同时LED灯不停闪烁 且在一分钟内没有按指定停止按键 闹钟将自动停止 。。。











软件部分

#include <reg52.h>

#define uchar unsigned char

#define uint unsigned int

sbit spk=P1^7;

sbit led=P1^5;

sbit DQ=P1^0;

sbit RS=P2^4;

sbit RW=P2^5;

sbit EN=P2^6;

sbit key1=P2^0;

sbit key2=P2^1;

sbit key3=P2^2;

sbit key4=P2^3;

sbit IO=P3^6;

sbit RST=P3^7;

sbit SCLK=P3^5;

uchar code table[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};

int nian,xing,yue,ri,shi,fen,miao;

uchar num,temp,c,d,time[7],a,b,aa,bb,ns,ng,ys,yg,rs,rg,ss,sg,fs,fg,ms,mg,flag;



void delay(int z)

{

int x,y;

for(x=z;x>0;x--)

for(y=100;y>0;y--);

}

void write_com(uchar com) //写命令

{

RS=0;

P0=com;

delay(5);

EN=1;

delay(5);

EN=0;

}

void write_data(uchar date) //写数据

{

RS=1;

P0=date;

delay(5);

EN=1;

delay(5);

EN=0;

}

void init() //初始化

{

RW=0;

EN=0;

write_com(0x38); //显示模式设置

write_com(0x0c); //开显示 不显示光标 不闪

write_com(0x06); //写一个字符 地址指针 光标 加一 整屏不移动

write_com(0x01); //显示清零

write_com(0x80+0x04);

write_data('2');

write_com(0x80+0x05);

write_data('0');

write_com(0x80+0x00);

write_data('c');

write_com(0x80+0x01);

write_data('a');

write_com(0x80+0x02);

write_data('i');

write_com(0x80+0x4e);

write_data(0xdf);

write_com(0x80+0x4f);

write_data('C');

write_com(0x80+0x4b);

write_data(0x2e); //显示"。"

}





void delay1(unsigned int t) //延时函数

{

while(t--);

}

void init1() //初始化

{

uchar n=0;

DQ=1; //DQ复位

delay1(8);

DQ=0; //主机将DQ拉低

delay1(80); //大于480us的延时

DQ=1;

delay1(5); //延时15~60us

n=DQ;

delay1(5); //若n=0初始成功 n=1初始失败(可设置返回值查看n是否为1)

}



void write_byte(uchar dat) //写入一个字节

{

uint i;

for(i=0;i<8;i++)

{

DQ=0;

DQ=dat&0x01;

delay1(12);

DQ=1;

dat>>=1;

}

delay1(4);

}

uchar read_byte() //读入一个字节

{

uint k=0;

uchar value=0;

for(k=0;k<8;k++)

{

DQ=0;

value>>=1;

DQ=1;

if(DQ)

value|=0x80;

delay1(4);

}

return value;

}

uchar read_temp() //读取温度函数

{

uchar a=0,b=0;

init1();

write_byte(0xcc);

write_byte(0x44);

delay1(200);

init1();

write_byte(0xcc);

write_byte(0xbe);

a=read_byte();

b=read_byte();

c=b;

d=a;

b<<=4;

b+=(a&0xf0)>>4;

return b;

}



void wirte_byte1(uchar date) //写入一个字节

{

uchar i;

for(i=8;i>0;i--)

{

IO=date&0x01;

SCLK=0;

SCLK=1;

date=date>>1;

}

}

uchar read_byte1() //读一个字节

{

uchar dat,i;

for(i=8;i>0;i--)

{

dat=dat>>1;

SCLK=0;

if(IO)

dat=dat|0x80;

SCLK=1;

}

return(dat);

}

void write_ds1302(uchar add,uchar date) //将数据写入1302中

{

RST=0;

SCLK=0;

RST=1;

wirte_byte1(add);

wirte_byte1(date);

RST=0;

SCLK=1;

}

uchar read_ds1302(uchar add) //读出1302中数据

{

uchar temp;

RST=0;

SCLK=0;

RST=1;

wirte_byte1(add);

temp=read_byte1();

RST=0;

SCLK=0;

return (temp);

}

uchar huan_BCD(uint z) //将数据 转换成BCD

{

uint a,b;

a=z/10;

b=z%10;

a=a&0xff;

b=b&0xff;

a<<=4;

a=a|b;

return (a);

}

void xian_shi() //液晶显示函数

{

if(b==0&a==0)

{

ms=time[0]/16;

mg=time[0]%16;

fs=time[1]/16;

fg=time[1]%16;

fen=fs*10+fg;



ss=time[2]/16;

sg=time[2]%16;

shi=ss*10+sg;

rs=time[3]/16;

rg=time[3]%16;

ri=rs*10+rg;

ys=time[4]/16;

yg=time[4]%16;

yue=ys*10+yg;

ns=time[6]/16;

ng=time[6]%16;

nian=ns*10+ng;

xing=time[5];

}

if(a==1|b==1)

{

ss=shi/10;

sg=shi%10;

write_com(0x80+0x41);

write_data(0xff);

write_com(0x80+0x40);

write_data(table[ss]);

write_com(0x80+0x41);

write_data(table[sg]);

}

if(a==2|b==2)

{

fs=fen/10;

fg=fen%10;

write_com(0x80+0x44);

write_data(0xff);

write_com(0x80+0x43);

write_data(table[fs]);

write_com(0x80+0x44);

write_data(table[fg]);

}

if(a==3)

{

rs=ri/10;

rg=ri%10;

write_com(0x80+0x0d);

write_data(0xff);

write_com(0x80+0x0c);

write_data(table[rs]);

write_com(0x80+0x0d);

write_data(table[rg]);

}

if(a==4)

{

ys=yue/10;

yg=yue%10;

write_com(0x80+0x0a);

write_data(0xff);

write_com(0x80+0x09);

write_data(table[ys]);

write_com(0x80+0x0a);

write_data(table[yg]);

}

if(a==5)

{

ns=nian/10;

ng=nian%10;

write_com(0x80+0x07);

write_data(0xff);

write_com(0x80+0x06);

write_data(table[ns]);

write_com(0x80+0x07);

write_data(table[ng]);

}

if(a==6)

{

write_com(0x80+0x0f);

write_data(0xff);

write_com(0x80+0x0f);

write_data(table[xing]);

}

write_com(0x80+0x06); //在液晶第一行第七八位显示 年

write_data(table[ns]);

write_com(0x80+0x07);

write_data(table[ng]);

write_com(0x80+0x08);

write_data('-');

write_com(0x80+0x09); //在液晶第一行第十十一位显示 月

write_data(table[ys]);

write_com(0x80+0x0a);

write_data(table[yg]);

write_com(0x80+0x0b);

write_data('-');

write_com(0x80+0x0c); //在液晶第一行第十三 十四位显示 日

write_data(table[rs]);

write_com(0x80+0x0d);

write_data(table[rg]);

write_com(0x80+0x0f); //在液晶第一行第十七位显示 星期

write_data(table[xing]);

write_com(0x80+0x40); //在液晶第二行第二三位显示 时

write_data(table[ss]);

write_com(0x80+0x41);

write_data(table[sg]);

write_com(0x80+0x42);

write_data(':');

write_com(0x80+0x43); //在液晶第二行第五六位显示 分

write_data(table[fs]);

write_com(0x80+0x44);

write_data(table[fg]);

write_com(0x80+0x45);

write_data(':');

write_com(0x80+0x46); //在液晶第二行第八九位显示 秒

write_data(table[ms]);

write_com(0x80+0x47);

write_data(table[mg]);

}

void keyscan() //按键设置函数 可任意设置年月日时分秒星期的数值

{

if(key4!=0)

{

if(key1==0) //key1按键 选择需设置的位

{

if(key1==0)

{

a++;

delay(1);

}

while(!key1)

{

delay(1);

}

}



if(a!=0)

{

if(key2==0) //key2按键 可将需设置的数 调大

{

if(a==1)

{

shi++;

if(shi>=24)

{

shi=0;

}

}

if(a==2)

{

fen++;

if(fen>=60)

{

fen=0;

}

}

if(a==3)

{

ri++;

if(ri>=32)

{

ri=1;

}

}

if(a==4)

{

yue++;

if(yue>=12)

{

yue=1;

}

}

if(a==5)

{

nian++;

if(nian>=99)

{

nian=0;

}

}

if(a==6)

{

xing++;

if(xing>=8)

{

xing=1;

}

}

}

if(key3==0) //key3按键 可将需设置的数 调小

{



if(a==1)

{

shi--;

if(shi<0)

{

shi=23;

}

}

if(a==2)

{

fen--;

if(fen<0)

{

fen=59;

}

}

if(a==3)

{

ri--;

if(ri<1)

{

ri=31;

}

}

if(a==4)

{

yue--;

if(yue<1)

{

yue=12;

}

}

if(a==5)

{

nian--;

if(nian<0)

{

nian=99;

}

}

if(a==6)

{

xing--;

if(xing<1)

{

xing=7;

}

}

}

if(a==7) //当按下key1 7次后 将个数据写入1302

{

a=0;

write_ds1302(0x8e,0x00); //WP=0 写操作

write_ds1302(0x80,0x00); //0x80是写秒数据

write_ds1302(0x82,huan_BCD(fen)); //0x82是写分数据

write_ds1302(0x84,huan_BCD(shi)); //0x84是写时数据

write_ds1302(0x86,huan_BCD(ri)); //0x84是写日数据

write_ds1302(0x88,huan_BCD(yue)); //0x84是写月数据

write_ds1302(0x8a,huan_BCD(xing)); //0x84是写星期数据

write_ds1302(0x8c,huan_BCD(nian)); //0x84是写年数据

write_ds1302(0x8e,0x80); //WP=1 写保护

}

}

}

}

void naozhong() //通过按键设置闹钟 时 分

{

if(key1!=0)

{

if(key4==0)

{

if(key4==0)

{

b++;

delay(1);

}

while(!key4)

{

delay(1);

}

}

if(b!=0)

{

if(key2==0) //key2按键 可将需设置的数 调大

{

if(b==1)

{

shi++;

if(shi>=24)

{

shi=0;

}

}

if(b==2)

{

fen++;

if(fen>=60)

{

fen=0;

}

}

}

if(key3==0) //key3按键 可将需设置的数 调小

{

if(b==1)

{

shi--;

if(shi<0)

{

shi=23;

}

}

if(b==2)

{

fen--;

if(fen<0)

{

fen=59;

}

}

}

aa=huan_BCD(shi); //将设置的时钟 赋值给aa

bb=huan_BCD(fen); //将设置的分钟 赋值给bb

if(b==3) //当按下key4 3次后 闹钟设置完成

{

b=0;

}

}

}

}

void main()

{

uint i,temp;

init();

TMOD=0x10;

EA=1;

TH1=(65536-51200)/256;

TL1=(65536-51200)%256;

ET1=1;

while(1)

{

temp=0x81; //读的初始地址

for(i=0;i<7;i++) //分别把秒分时日月年星期数据读出分7次读好一次地址加2" temp+=2;"

{

time[i]=read_ds1302(temp);

temp+=2;

}

if(bb==time[1]&aa==time[2]&!time[0]) //如果读出来的时钟 分钟与1302读出来的值相等且读出来的秒钟为零时 进入中断

{

TR1=1;

flag=1; //标志位设置为1

}

if(key3==0) //进入闹钟后 可由key3按下 停止中断 标志位置零 允许调时闹钟设置按键动作 停止闹铃

{

led=1;

spk=1;

flag=0;

TR1=0;

}

if(flag!=1) //当进入闹钟中断后 调时与设置闹钟的按键 无效

{

naozhong();

keyscan();

}

xian_shi();

temp=read_temp();

write_com(0x80+0x49);

write_data(table[temp/10]); //在液晶第二行第十位显示温度的十位

write_com(0x80+0x4a);

write_data(table[temp%10]); //在液晶第二行第十一位显示温度的个位

write_com(0x80+0x4c);

write_data(table[(d&0x0f)*625/1000]); //在液晶第二行第十三位显示温度的小数点后一位

write_com(0x80+0x4d);

write_data(table[(d&0x0f)*625/100%10]); //在液晶第二行第十四位显示温度的小数点后二位

}

}



void timer1() interrupt 3 //定时器

{

uint t;

TH1=(65536-50000)/256;

TL1=(65536-50000)%256;

t++;

spk=0; //蜂鸣器 发出 滴答 声

led=!led; //发光二极管 不停闪烁

delay1(10);

if(t==1120) //约1分钟后 闹钟自动停止 标志位

{

led=1;

spk=1;

t=0;

TR1=0;

flag=0;

}

}

水电之家为您提供最全面的管材,管件,水电,电线,电工,管材水电品牌的装修知识点和各种管材水电的导购与在线购买服务,拥有最便宜的管材水电价格和最优质的售后服务,每天都有秒杀的抢购活动哦!敬请登陆水电之家:http://shuidian.jc68.com/
更多»您可能感兴趣的文章:
更多»有关 水电 的产品:
  • 水电电工资讯
  • 发表评论 | 0评
  • 评论登陆
  • 移动社区 天花之家 木门之家 灯具之家 铁艺之家 幕墙之家 五金头条 楼梯头条 墙纸头条 壁纸头条 玻璃头条 老姚之家 灯饰之家 电气之家 全景头条 照明之家 防水之家 防盗之家 区快洞察 建材 枣庄建材 临沂建材 南昌建材 上饶建材 抚州建材 宜春建材 吉安建材 赣州建材 鹰潭建材 新余建材 九江建材 萍乡建材 景德镇陶瓷 石家庄建材 衡水建材 廊坊建材 沧州建材 承德建材 建材之家 企业之家 720全景
    (c)2015-2017 BYBC.CN SYSTEM All Rights Reserved