实验三实验三 串行口实时时钟实验串行口实时时钟实验 实验目的实验目的1、了解实时时钟电路工作原理 2、了解串行时钟芯片的控制方法 3、掌握 DS1302 串行时钟芯片的使用方法实验仪器实验仪器单片机开发板、万利仿真机、稳压电源、计算机实验原理实验原理1、 DS1302 串行时钟芯片工作原理 DS1302 是一种高性能、低功耗、带 RAM 的实时时钟电路,它可以对年、月、日、周 日、时、分、秒进行计时,具有闰年补偿功能,工作电压为 2.5V~5.5V采用三线接口与 CPU 进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或 RAM 数据芯片 内部有一个 31×8 的用于临时性存放数据的 RAM 寄存器DS1302 增加了主电源/后背电 源双电源引脚,同时提供了对后背电源进行涓细电流充电的能力引脚图如图 4-77 所示图 4-77 DS1302 引脚图 DS1302 的控制字如下所示DS1302 的控制字最高位必须为 1;D6 位:1:读写内部通用存储器,0:读写时钟存 储器;随后是地址位最低位是读写控制:1 代表读,0:代表写 DS1302 内部日历数据存储器位定义如图 4-78 所示。
图 4-78 DS1302 内部日历数据存储器结构图1RAM/ CKA4A3A2A1A0R /WCH:时钟停止位(CH=0振荡器工作允许,CH=1振荡器停止) 寄存器2的第7位:12/24小时标志(bit7=1,12小时模式,bit7=0,24小时模式) 寄存器2的第5位:AM/PM定义(AP=1下午模式,AP=0上午模式) WP:写保护位(WP=0 寄存器数据能够写入,WP=1寄存器数据不能写入) TCS:涓流充电选择(TCS=1010使能涓流充电,TCS=其它禁止涓流充电) DS:二极管选择位(DS=01一个二极管,DS=10两个,DS=00或11,充电功能也被禁止)从图中可以看出,第1脚电源经过开关、二极管、电阻对接在第8脚的备用电源进行充 电调整涓流充电控制寄存器的值可以控制涓流充电方式 2、 DS1302 芯片读写时序 DS1302 采用三线串行口通迅,占用 IO 口少数据在 SCLK 的上升沿有效每个 SCLK 正脉冲锁存一位数据如图 4-80 所示图 4-80 DS 芯片读写时序图 DS1302 支持单字节读写和多字节读写方式单字节读写时,单片机先发出读写的地址, 然后再读写一字节数据;多字节读写时,单片机先发出读写的地址,然后再连续读写多个 字节。
如图 4-81 所示图 4-79 DS1302 内部充电电路结构图图 4-82 DS1302 读数据帧结构 3、 DS1302 应用电路 51 单片机没有 SPI 接口,只能用普通 IO 口来模拟读写时序将芯片 IO 口与单片机连 接,电容 C1 用于备份电源,电源断电时为 DS1302 提供电能DS1302 的复位端与 74LS138 的 Y6 连接,当 P2=0CH 时,复位端有效电路如图 4-83 所示图 4-83 DS1302 应用电路 4、 DS1302 应用程序设计 DS1302 应用程序设计包含:DS1302 串口驱动程序、DS1302 接口程序等DS1302 串 口驱动程序就是串口发送、接收一个字节数据程序DS1302 接口程序包含:时钟启动/停 止、时间日期设置、读时间日期、充电方式设计等根据原理说明,我们可以设计出一部 分程序流程序图如图 4-84 所示图 4-84 DS1302 应用程序流程图实验内容实验内容#include #include #define uint unsigned int #define uchar unsigned char #define data 1000 sbit LEDCLK=P3^4; sbit LEDDIN=P2^3; uchar code ledtable[]={0x03,0x9F,0x25,0x0D,0x99,0x49,0x41,0x1F,0x01,0x09,0x11,0xC1,0x63,0x85,0x61,0x71,0xFD}; uchar dispbuf[8]; uint msecond=0; uchar wei=0;uchar timebuf[3]={0x12,0x34,0x56}; #define second timebuf[0]DS1302 串口发输出一位数据SCLK 产生正脉冲传输 8 位?返回YNDS1302 串口收SCLK 高电平读数据, SCLK低传输 8 位?返回YN时间日期设置发写多字节命令写一个多字节3 字节数据指针加 1返回YN读时间日期 时间日期设置 发读多字节命令读一个多字节3 字节数据指针加 1返回YN#define minute timebuf[1] #define hour timebuf[2]#define NOP3() _nop_();_nop_();_nop_() /**DS1302 与 MCU 连接的各端口定义*****************/ sbit DS_IO=P3^5;//DS1302 数据口 sbit DS_SCLK=P1^7;//DS1302 串行时钟 #define DSRST_1 P2=0XFF;// #define DSRST_0 P2=0X03;///**DS1302 内部各个寄存器地址定义***********/ #define DS1302_SECOND 0X80 //秒 #define DS1302_MINUTE 0X82 // 分 #define DS1302_HOUR 0X84 //时 #define DS1302_DAY 0X86 //日 #define DS1302_MONTH 0X88 //月 #define DS1302_WEEK0X8A // 星期 #define DS1302_YEAR0X8C //年 #define DS1302_CONTROL 0X8E //写保护控制位 #define DS1302_RAM(X)(0XC0+(X)*2)//用于计算 DS1302 静态 RAM 地址 /************************************************ 延时函数 *功能: 可随意设置延时时间,延时时间为 tt ms.晶振为 12MHz *************************************************/ void delay1ms(unsigned int tms) { unsigned char i; while(tms--)for(i=123;i>0;i--) ; } /********************************************** 写入单个字节 **********************************************/ void DS1302WriteByte(uchar Wdate) { uchar i; EA=0; DS_SCLK=1; for(i=0;i>=1; } EA=1; } /*********************************************** 读取一个字节 *************************************************/ uchar DS1302ReadByte(void) { uchar i,temp; EA=0; for(i=0;i>=1; if(DS_IO==1) { temp=temp|0x80; } DS_SCLK=1; NOP3(); DS_SCLK=0; } EA=1; return(temp); } /********************************************** 对单个地址写相应的数据 ***********************************************/ void Write1302(uchar addr,uchar DSdate) { DSRST_0; DS_SCLK=0; DSRST_1; DS1302WriteByte(addr); //地址 DS1302WriteByte(DSdate); //数据 DS_SCLK=1; DSRST_0; } /********************************************** 读相应地址的数据 ***********************************************/ uchar Read1302(uchar addr) {uchar Rdate; DSRST_0; DS_SCLK=0; DSRST_1; DS1302WriteByte(addr|0x01); Rdate=DS1302ReadByte(); DS_SCLK=1; DSRST_0; return(Rdate); } /********************************************** 对多个地址写相应的数据 ***********************************************/ void Write1302_All(uchar addr,uchar *p) { DSRST_0; DS_SCLK=0; DSRST_1; DS1302WriteByte(addr); //地址 while(*p!='\0') {DS1302WriteByte(*p++); //数据 } DS_SCLK=1; DSRST_0; } /****************************************** 更新数据 ******************************************/ update() { dispbuf[0]=second%16; dispbuf[1]=second/16; dispbuf[2]=16; dispbuf[3]=minute%16; dispbuf[4]=minute/16; dispbuf[5]=16; dispbuf[6]=hour%16; dispbuf[7]=hour/16; } /****************************************** 动态扫描 ******************************************/ display(){ LEDCLK=0; if(wei==0) { LEDDIN=0; } else { LEDDIN=1; } LEDCLK=1; P0=ledtable[dispbuf[wei]]; LEDCLK=0; wei++; if(wei>8) { wei=0; } } /****************************************** 定时器 1 中断 ******************************************/ void time1_int() interrupt 3 { msecond++; update(); display(); TH1=(65536-data)>>8;TL1=(65536-data)%256; } /****************************************** MCU 初始化 ******************************************/ init_mcu() { TMOD=0x01;TH1=(65536-data)>>8;TL1=(65536-data)%256; ET1=1;TR1=1;EA=1; } /******************************************** DS1302 初始化 ***********。