基于单片机AT89C51实时时钟设计.docx

上传人:b****8 文档编号:30302740 上传时间:2023-08-13 格式:DOCX 页数:49 大小:298KB
下载 相关 举报
基于单片机AT89C51实时时钟设计.docx_第1页
第1页 / 共49页
基于单片机AT89C51实时时钟设计.docx_第2页
第2页 / 共49页
基于单片机AT89C51实时时钟设计.docx_第3页
第3页 / 共49页
基于单片机AT89C51实时时钟设计.docx_第4页
第4页 / 共49页
基于单片机AT89C51实时时钟设计.docx_第5页
第5页 / 共49页
点击查看更多>>
下载资源
资源描述

基于单片机AT89C51实时时钟设计.docx

《基于单片机AT89C51实时时钟设计.docx》由会员分享,可在线阅读,更多相关《基于单片机AT89C51实时时钟设计.docx(49页珍藏版)》请在冰豆网上搜索。

基于单片机AT89C51实时时钟设计.docx

基于单片机AT89C51实时时钟设计

 

基于单片机AT89C51

----实时时钟设计

 

学号

 

姓名

一.系统分析

本电路是由AT89C51单片机为控制核心,具有在线编程功能,低功耗,能在4.5V超低压工作;显示部分用LCD1602实现,能够同时显示16x02即32个字符;闹钟部分由蜂鸣器构成,蜂鸣器是一种一体化结构的电子讯响器;时钟电路由DS1302提供,它是一种高性能、低功耗、带RAM的实时时钟电路,可以对年、月、日、星期、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V.采用三线接口与单片机进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。

DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。

可产生年、月、日、周日、时、分、秒,具有使用寿命长,精度高和低功耗等特点,同时具有掉电自动保存功能,本设计中为DS1302增加了备用电池,当主电源掉电时,备用电池自动为其供电;温度的采集由DS18B20构成;当闹铃时间到时,通过蜂鸣器播放闹铃铃声。

二.系统功能框图的设计

三.系统硬件设计本设计采用的元器件如下:

单片机AT89C51

LM016L

DS1302

晶振CRYSTAL

DS18B20

24C02C

电容CAP

电解电容CAP-ELEC

电阻RES

排阻RESPACK-8

按键BUTTON

四.系统软件设计(流程图和软件设计)

主程序流程图

时间调整程序流程图

定时闹铃程序流程图

C程序:

#include

#include"intrins.h"

#include"24c02.h"

#defineucharunsignedchar

#defineuintunsignedint

//闹钟显示缓冲区

codeucharalarm_one[]="Hello,L.WHou";

codeucharalarm_two[]="GOODMORNINGHLW";

codeucharw1[]={0x01,0x03,0x1D,0x11,0x1D,0x03,0x01,0x00};

codeuintcyc[]={1800,1600,1440,1351,1200,1079,960};//音阶1-7的半周期数

codeuchartone[]={13,15,16,16,15,16,13,12,12,13,15,16,16,15,16,13,13,13,15,16,

16,15,16,13,12,12,15,13,12,13,12,11,12,6,6,12,15,13,12,6,6,15,13,12,13,12,11,

12,6,5,6,0xff};//乐曲《康定情歌》的简谱表

codeuchartime[]={8,8,8,4,4,8,8,12,4,8,8,8,4,4,8,16,8,8,8,8,4,4,8,8,12,4,8,8,4,

4,4,4,8,24,8,24,8,24,8,16,8,8,8,4,4,4,4,8,16,8,32};//节拍表

ucharH0,L0,cnt;

ucharcodetabe1[]="20--";//液晶一直显示的字符

ucharcodetabe2[]=":

:

";

ucharcodetabe3[]="Alarmset:

";

ucharmiao,fen,shi,nian,yue,ri,week,wendu_shi,wendu_ge,wendu_shu,variate,alarm_shi,alarm_fen,alarm_miao;

ucharflag=1,count=0,flag_up=0,flag_down=0,flag_alarm=0,alarm_on,alarm_count=0,done=0;

uintwendu;

//定义IO

sbitDQ=P1^0;//ds18b20温度传送数据IO口

sbitds1302_rst=P1^1;//1302复位

sbitds1302_io=P1^2;//数据输入输出

sbitds1302_sclk=P1^3;//串行时钟

sbitalarm_out=P3^6;

sbitlcd1602_rs=P2^0;//1602命令、数据选择

sbitlcd1602_rw=P2^1;//1602写

sbitlcd1602_e=P2^2;//1602使能

sbitset=P2^4;//选择按键

sbitup=P2^5;//加

sbitdown=P2^6;//减

sbitnao=P2^7;

sbitACC0=ACC^0;

sbitACC7=ACC^7;

sbitMODE=P3^2;

//延时

voiddelay(ucharx)

{

uchary,z;

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

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

}

voiddelay1()

{

_nop_();

_nop_();

}

voiddelay2(uintms)

{

uinti,j;

for(j=0;j

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

}

ds18b20_delay(ucharxus)//延时xus

{

while(xus--);

return0;

}

/**********************ds18b20***********************/

voidds18b20_init()//DS18B20初始化

{

ucharx=0;

DQ=1;

ds18b20_delay(8);

DQ=0;

ds18b20_delay(80);

DQ=1;

ds18b20_delay(14);

x=DQ;

ds18b20_delay(20);

}

voidwrite_onechar(uchardat)//写一字节

{

uchari;

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

{

DQ=0;

if(dat&0x01==0x01)

DQ=1;

else

DQ=0;

ds18b20_delay(5);

DQ=1;

ds18b20_delay

(1);

dat>>=1;

}

}

ucharread_onechar()//读一字节

{

ucharvalue=0,i;

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

{

value>>=1;

DQ=0;

ds18b20_delay

(1);

DQ=1;

if(DQ==1)

value|=0x80;

else

value&=0x7f;

ds18b20_delay(4);

}

returnvalue;

}

uintread_wendu()//DS18B20读温度

{

uchara=0,b=0;

uintwen=0x0000;

ds18b20_init();//初始化

write_onechar(0xcc);//跳过读序号列号的操作

write_onechar(0x44);//启动温度转换

ds18b20_delay(150);

ds18b20_init();//初始化

write_onechar(0xcc);//跳过读序号列号的操作

write_onechar(0xbe);//读取温度寄存器等(共可读9个寄存器)前两个就是温度

ds18b20_delay(150);

b=read_onechar();//读取温度值低位

a=read_onechar();//读取温度值高位

wen=a;

wen=(wen<<8)|b;

returnwen;

}

/**********************ds1302***************************/

voidwrite_byte(uchardat)//写一字节

{

uchark;

ACC=dat;

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

{

ds1302_io=ACC0;

ds1302_sclk=0;//拉低sclk

ds1302_sclk=1;//拉高sclk

ACC>>=1;

}

}

ucharread_byte()

{

uchark;

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

{

ACC7=ds1302_io;

ds1302_sclk=1;//拉高sclk

ds1302_sclk=0;//拉低sclk

ACC>>=1;

}

returnACC;

}

voidds1302_write(ucharadd,uchardate)

{

ds1302_rst=0;

ds1302_sclk=0;//在rst没拉高之前先把sclk置0

ds1302_rst=1;

write_byte(add);

write_byte(date);

ds1302_sclk=1;

ds1302_rst=0;

}

uchards1302_read(ucharadd)

{

uchartemp;

ds1302_rst=0;

ds1302_sclk=0;//在rst没拉高之前先把sclk置0

ds1302_rst=1;

write_byte(add);

temp=read_byte();

ds1302_sclk=1;

ds1302_rst=0;

returntemp;

}

voidds1302_init()//ds1302初始化

{

ds1302_rst=0;

ds1302_sclk=1;

ds1302_write(0x8e,0x00);//写允许

ds1302_write(0x80,0x58);

ds1302_write(0x82,0x56);

ds1302_write(0x84,0x09);

ds1302_write(0x86,0x12);

ds1302_write(0x88,0x05);

ds1302_write(0x8a,0x05);

ds1302_write(0x8c,0x12);

ds1302_write(0x8e,0x80);//写保护

}

/***************************lcd1602***************************/

voidlcd_write_com(ucharcom)//命令字写入lcd单元中

{

lcd1602_rw=0;

delay1();

lcd1602_rs=0;//RW=1,RS=0,写LCD命令字

delay1();

P0=com;//将com中的命令字写入LCD数据口

delay1();

lcd1602_e=1;//E端时序

delay1();

lcd1602_e=0;

delay1();

lcd1602_rw=1;

delay(5);

}

voidlcd_write_date(uchardate)//数据写入lcd单元中

{

lcd1602_rw=0;

delay1();

lcd1602_rs=1;//RW=0,RS=1,写LCD命令字

delay1();

lcd1602_e=1;//E端时序

delay1();

P0=date;//将dat中的显示数据写入LCD数据口

delay1();

lcd1602_e=0;

delay1();

lcd1602_rw=1;

delay(5);

}

voidlcd1602_init()//LCD初始化函数

{

ucharlcdnum;

P3=0xdf;

lcd_write_com(0x38);

lcd_write_com(0x0c);

lcd_write_com(0x06);

lcd_write_com(0x01);

lcd_write_com(0x80);

for(lcdnum=0;lcdnum<8;lcdnum++)//写第一行数据

{

lcd_write_date(tabe1[lcdnum]);

delay

(2);

}

lcd_write_com(0x80+0x40);//写入第二行数据

for(lcdnum=0;lcdnum<13;lcdnum++)

{

lcd_write_date(tabe2[lcdnum]);

delay

(2);

}

}

/****************************显示部分*****************************/

voidwrite_time1(ucharadd,uchardate)//日期送显示

{

ucharshi,ge;

shi=date/10;

ge=date%10;

lcd_write_com(0x80+add);

lcd_write_date(0x30+shi);

lcd_write_date(0x30+ge);

}

voidwrite_time2(ucharadd,uchardate)//时间送显示

{

ucharshi,ge;

shi=date/10;

ge=date%10;

lcd_write_com(0x80+0x40+add);

lcd_write_date(0x30+shi);

lcd_write_date(0x30+ge);

}

ucharbcd_decimal(ucharbcd)//bcd转换十进制

{

uchardecimal;

decimal=bcd>>4;

decimal=decimal*10+(bcd&=0x0f);

returndecimal;

}

voidwendu_decimal(uintdat)//温度转换后送显示

{

floattemp;

temp=dat*0.625;//dat*0.0625*10

wendu_shi=temp/100;//取十位temp除不用定义类型

wendu_ge=((uint)temp)%100/10;//取个位temp求模要定义类型,为

//16位,故定义uint

wendu_shu=((uint)temp)%100%10;//取小数

lcd_write_com(0x80+0x40+10);//送显示

lcd_write_date(0x30+wendu_shi);

lcd_write_date(0x30+wendu_ge);

lcd_write_date(0x2e);

lcd_write_date(0x30+wendu_shu);

lcd_write_date(0xdf);//温度符号

lcd_write_date(0x43);

}

voidwrite_week(ucharwe)//星期送显示

{

lcd_write_com(0x80+0x0d);

switch(we)

{

case1:

lcd_write_date('M');

lcd_write_date('O');

lcd_write_date('N');

break;

case2:

lcd_write_date('T');

lcd_write_date('U');

lcd_write_date('E');

break;

case3:

lcd_write_date('W');

lcd_write_date('E');

lcd_write_date('D');

break;

case4:

lcd_write_date('T');

lcd_write_date('H');

lcd_write_date('U');

break;

case5:

lcd_write_date('F');

lcd_write_date('R');

lcd_write_date('I');

break;

case6:

lcd_write_date('S');

lcd_write_date('A');

lcd_write_date('T');

break;

case7:

lcd_write_date('S');

lcd_write_date('U');

lcd_write_date('N');

break;

}

}

voidlcd_write_com1(ucharcom,bitrs)//命令字写入lcd单元中

{

lcd1602_rs=rs;

lcd1602_rw=0;//RW=1,RS=0,写LCD命令字

P0=com;

delay1();

delay1();//将com中的命令字写入LCD数据口

lcd1602_e=0;

delay1();

delay1();

lcd1602_e=1;//E端时序

delay1();

delay1();

lcd1602_e=0;

delay1();

delay1();

}

/***************LCD1602闹钟显示函数******************/

voiddisplay_1602_alarm()

{

uchari,j,k;

P3=0xdf;

lcd_write_com(0x38);

lcd_write_com(0x0c);

lcd_write_com(0x06);

lcd_write_com(0x01);

lcd_write_com(0x80);//液晶显示位置

delay2(5);

for(i=0;i

{

lcd_write_date(alarm_one[i]);

delay2(5);

}

lcd_write_com1(0x40,0);

lcd_write_com1(0x40,0);

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

lcd_write_com1(w1[j],1);

lcd_write_com1(0x80+0x0f,0);

lcd_write_com1(0x00,1);

lcd_write_com(0x80+0x40);//液晶显示位置

delay2(5);

for(k=0;k

{

lcd_write_date(alarm_two[k]);

delay2(5);

}

}

/***********************按键处理***************************/

ucharkey_bcd(ucharkey_decimal)//转成ds1302所需的BCD码

{

uchartemp;

temp=(((key_decimal/10)&0x0f)<<4)|(key_decimal%10);

returntemp;

}

voidkey_up_down()//加减键处理

{

if(up==0)

{

delay

(2);

flag_up=1;//加更新标志

while(!

up);

switch(count)

{

case1:

miao++;

if(miao>59)

miao=0;

break;

case2:

fen++;

if(fen>59)

fen=0;

break;

case3:

shi++;

if(shi>23)

shi=0;

break;

case4:

week++;

if(week>7)

week=1;

break;

case5:

ri++;

if(ri>31)

ri=1;

break;

case6:

yue++;

if(yue>12)

yue=1;

break;

case7:

nian++;

if(nian>99)

nian=0;

break;

}

}

if(down==0)//减键处理

{

delay

(2);

flag_down=1;//减更新标志

while(!

down);

switch(count)

{

case1:

miao--;

if(miao==255)

miao=59;

break;

case2:

fen--;

if(fen==255)

fen=59;

break;

case3:

shi--;

if(shi==255)

shi=23;

break;

case4:

week--;

if(week<1)

week=7;

break;

case5:

ri--;

if(ri<1)

ri=31;

break;

case6:

yue--;

if(yue<1)

yue=12;

break;

case7:

nian--;

if(nian==255)

nian=99;

break;

}

}

}

voidc02_init()

{

c_init();

alarm_shi=c02_read_add

(1);//读取闹钟时

delay(200);

alarm_fen=c02_read_add

(2);//分

delay(200);

alarm_miao=c02_read_add(3);//秒

delay(200);

alarm_on=c02_read_add(4);//读取闹钟开关值,为0关,为1开

delay(200);

}

voidalarm_huan()//按下闹钟键后,切换界面

{

ucharnum;

lcd_write_com(0x01);

lcd_write_com(0x80);

for(num=0;num<10;num++)//写第一行数据

{

lcd_write_date(tabe3[num]);

delay

(2);

}

lcd_write_com(0x0f);

write_time2(4,alarm_shi);

lcd_write_date(0x3a);

write_time2(7,alarm_fen);

lcd_write_date(0x3a);

write_time2(10,alarm_miao);

if(alarm_on==0)

{

lcd_write_com(0x80+0x40+13);

lcd_write_date('O');

lcd_write_date('F');

lcd_write_date('F');

}

if(alarm_on==1)

{

lcd_write_com(0x80+0x40+13);

lcd_write_date('');

lc

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1