1、基于单片机AT89C51实时时钟设计基于单片机AT89C51-实时时钟设计学号姓名一系统分析本电路是由AT89C51单片机为控制核心,具有在线编程功能,低功耗,能在4.5V超低压工作;显示部分用LCD1602实现,能够同时显示16x02即32个字符;闹钟部分由蜂鸣器构成,蜂鸣器是一种一体化结构的电子讯响器;时钟电路由DS1302提供,它是一种高性能、低功耗、带RAM的实时时钟电路,可以对年、月、日、星期、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V5.5V.采用三线接口与单片机进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。DS1302内部有一个318的用于临
2、时性存放数据的RAM 寄存器。可产生年、月、日、周日、时、分、秒,具有使用寿命长,精度高和低功耗等特点,同时具有掉电自动保存功能,本设计中为DS1302增加了备用电池,当主电源掉电时,备用电池自动为其供电;温度的采集由DS18B20构成;当闹铃时间到时,通过蜂鸣器播放闹铃铃声。二.系统功能框图的设计三.系统硬件设计本设计采用的元器件如下:单片机AT89C51LM016LDS1302晶振CRYSTAL DS18B2024C02C电容CAP电解电容CAP-ELEC电阻RES排阻RESPACK-8按键BUTTON四.系统软件设计(流程图和软件设计)主程序流程图时间调整程序流程图定时闹铃程序流程图C程
3、序:#include #include intrins.h#include 24c02.h#define uchar unsigned char#define uint unsigned int/闹钟显示缓冲区code ucharalarm_one= Hello,L.WHou;codeucharalarm_two=GOOD MORNING HLW;code uchar w1=0x01,0x03,0x1D,0x11,0x1D,0x03,0x01,0x00;code uintcyc=1800,1600,1440,1351,1200,1079,960;/音阶1-7的半周期数code uchar to
4、ne=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;/ 乐曲康定情歌的简谱表code uchar time=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;/ 节拍表u
5、char H0,L0,cnt;uchar code tabe1=20 - - ; /液晶一直显示的字符uchar code tabe2= : : ;uchar code tabe3=Alarm set:;uchar miao,fen,shi,nian,yue,ri,week,wendu_shi,wendu_ge,wendu_shu,variate,alarm_shi,alarm_fen,alarm_miao;uchar flag=1,count=0,flag_up=0,flag_down=0,flag_alarm=0,alarm_on,alarm_count=0,done=0;uintwend
6、u;/定义IOsbit DQ = P10; /ds18b20温度传送数据IO口sbit ds1302_rst = P11; /1302复位sbit ds1302_io = P12; /数据输入输出sbit ds1302_sclk= P13; /串行时钟sbitalarm_out = P36; sbit lcd1602_rs = P20; / 1602命令、数据选择sbit lcd1602_rw = P21; / 1602写sbit lcd1602_e = P22; / 1602使能sbit set = P24; /选择按键sbit up = P25; /加sbit down= P26; /减s
7、bitnao = P27;sbit ACC0=ACC0;sbit ACC7=ACC7;sbit MODE=P32;/延时void delay(uchar x)uchary,z;for(z=x;z0;z-)for(y=110;y0;y-);void delay1() _nop_(); _nop_(); void delay2(uintms)uinti,j;for (j=0;jms;j+)for (i=0;i0;i-) DQ=0;if(dat&0x01=0x01) DQ=1;else DQ=0; ds18b20_delay(5); DQ=1; ds18b20_delay(1);dat=1; uch
8、arread_onechar() /读一字节uchar value=0,i;for(i=8;i0;i-) value=1; DQ=0; ds18b20_delay(1); DQ=1;if(DQ=1) value|=0x80; elsevalue&=0x7f; ds18b20_delay(4); return value;uintread_wendu() /DS18B20读温度uchar a=0,b=0;uint wen=0x0000; ds18b20_init(); /初始化write_onechar(0xcc); / 跳过读序号列号的操作write_onechar(0x44); / 启动温度
9、转换 ds18b20_delay(150); ds18b20_init(); /初始化write_onechar(0xcc); /跳过读序号列号的操作write_onechar(0xbe); /读取温度寄存器等(共可读9个寄存器)前两个就是温度 ds18b20_delay(150); b=read_onechar(); /读取温度值低位 a=read_onechar(); /读取温度值高位wen=a;wen=(wen0;k-) ds1302_io=ACC0; ds1302_sclk=0; /拉低sclk ds1302_sclk=1; /拉高sclk ACC=1; ucharread_byte(
10、)uchar k;for(k=8;k0;k-) ACC7=ds1302_io; ds1302_sclk=1; /拉高sclk ds1302_sclk=0; /拉低sclk ACC=1; return ACC; void ds1302_write(ucharadd,uchar date) ds1302_rst=0; ds1302_sclk=0; /在rst没拉高之前先把sclk置0 ds1302_rst=1;write_byte(add);write_byte(date); ds1302_sclk=1; ds1302_rst=0; uchar ds1302_read(uchar add)ucha
11、r temp; ds1302_rst=0; ds1302_sclk=0; /在rst没拉高之前先把sclk置0 ds1302_rst=1;write_byte(add);temp=read_byte(); ds1302_sclk=1; ds1302_rst=0;return temp; void ds1302_init() /ds1302初始化 ds1302_rst=0; ds1302_sclk=1; ds1302_write(0x8e,0x00); /写允许 ds1302_write(0x80,0x58); ds1302_write(0x82,0x56); ds1302_write(0x84
12、,0x09); ds1302_write(0x86,0x12); ds1302_write(0x88,0x05); ds1302_write(0x8a,0x05); ds1302_write(0x8c,0x12); ds1302_write(0x8e,0x80); /写保护 /*lcd1602*/void lcd_write_com(uchar com) /命令字写入lcd单元中 lcd1602_rw=0;delay1(); lcd1602_rs=0; / RW=1,RS=0,写LCD命令字delay1(); P0=com; /将com中的命令字写入LCD数据口delay1(); lcd160
13、2_e=1; /E端时序delay1(); lcd1602_e=0;delay1(); lcd1602_rw=1;delay(5);void lcd_write_date(uchar date) /数据写入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);void lcd1602
14、_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;lcdnum8;lcdnum+) /写第一行数据 lcd_write_date(tabe1lcdnum);delay(2); lcd_write_com(0x80+0x40); /写入第二行数据for(lcdnum=0;lcdnum4;decimal=decimal*10+(bcd&=0x0f
15、);return decimal; void wendu_decimal(uintdat) /温度转换后送显示float temp;temp=dat*0.625; /dat*0.0625*10wendu_shi=temp/100; /取十位 temp除不用定义类型wendu_ge =(uint)temp)%100/10; /取个位 temp求模要定义类型,为 /16位,故定义uintwendu_shu=(uint)temp)%100%10; /取小数lcd_write_com(0x80+0x40+10); /送显示lcd_write_date(0x30+wendu_shi);lcd_write
16、_date(0x30+wendu_ge);lcd_write_date(0x2e); lcd_write_date(0x30+wendu_shu);lcd_write_date(0xdf); /温度符号lcd_write_date(0x43); void write_week(uchar we) /星期送显示lcd_write_com(0x80+0x0d);switch(we) case 1: lcd_write_date(M);lcd_write_date(O);lcd_write_date(N);break;case 2: lcd_write_date(T);lcd_write_date(
17、U);lcd_write_date(E);break;case 3: lcd_write_date(W);lcd_write_date(E);lcd_write_date(D);break;case 4: lcd_write_date(T);lcd_write_date(H);lcd_write_date(U);break; case 5: lcd_write_date(F);lcd_write_date(R);lcd_write_date(I);break;case 6: lcd_write_date(S);lcd_write_date(A);lcd_write_date(T);break;
18、case 7: lcd_write_date(S);lcd_write_date(U);lcd_write_date(N);break; void lcd_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(
19、);delay1();/*LCD1602闹钟显示函数*/ void display_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;isizeof(alarm_one)-1;i+) lcd_write_date(alarm_onei);delay2(5); lcd_write_com1(0x40,0);lcd_write_com
20、1(0x40,0);for(j=0;j8;j+)lcd_write_com1(w1j,1);lcd_write_com1(0x80+0x0f,0);lcd_write_com1(0x00,1);lcd_write_com(0x80+0x40); /液晶显示位置delay2(5); for (k=0;ksizeof(alarm_two)-1;k+) lcd_write_date(alarm_twok);delay2(5); /*按键处理*/ucharkey_bcd(ucharkey_decimal) /转成ds1302所需的BCD码uchar temp;temp=(key_decimal/10)
21、&0x0f)59)miao=0;break;case 2:fen+;if(fen59)fen=0;break;case 3:shi+;if(shi23)shi=0;break; case 4:week+;if(week7)week=1;break; case 5:ri+;if(ri31)ri=1;break; case 6:yue+;if(yue12)yue=1;break; case 7: nian+;if(nian99)nian=0;break; if(down=0) /减键处理 delay(2);flag_down=1; /减更新标志 while(!down);switch(count)
22、case 1:miao-;if(miao=255)miao=59;break;case 2:fen-;if(fen=255)fen=59;break;case 3:shi-;if(shi=255)shi=23;break; case 4:week-;if(week1)week=7;break; case 5:ri-;if(ri1)ri=31;break; case 6:yue-;if(yue1)yue=12;break; case 7: nian-;if(nian=255)nian=99;break; void c02_init()c_init();alarm_shi=c02_read_add
23、(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); void alarm_huan() /按下闹钟键后,切换界面ucharnum;lcd_write_com(0x01);lcd_write_com(0x80); for(num=0;num10;num+) /写第一行数据 lcd_write_date(tabe3num);delay(
24、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