基于单片机AT89C51的实时时钟设计.docx
- 文档编号:7290571
- 上传时间:2023-01-22
- 格式:DOCX
- 页数:42
- 大小:298.51KB
基于单片机AT89C51的实时时钟设计.docx
《基于单片机AT89C51的实时时钟设计.docx》由会员分享,可在线阅读,更多相关《基于单片机AT89C51的实时时钟设计.docx(42页珍藏版)》请在冰豆网上搜索。
基于单片机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
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 单片机 AT89C51 实时 时钟 设计