第12章使用DS1302设计数字时钟51单片机实战指南本章内容:2DS1302芯片介绍1封装的编程思想和结构体类型22DS1302读写操作的编程实现3DS1302读写实战412.1.1DS1302芯片特点DS1302实时时钟芯片具有功耗低、精确度高、软件编程较简单,且芯片体积小、成本低等特点–提供秒、分、小时、日期、月、年等信息,可以通过配置AM/PM来决定采用24小时格式还是12小时格式–拥有31*8位的额外数据暂存寄存器(即RAM,掉电丢失)–串行I/O通信方式–工作电压比较宽,在2.0~5.5V的范围内都可以正常工作–功耗很低,它在工作电压2.0V的时候,工作电流小于300nA–提供主电源和备用电源共两个电源,保证系统掉电的情况下仍继续工作12.1.2DS1302芯片引脚功能引脚编号引脚名称引脚功能1VCC2主电源引脚,当VCC2比VCC1高0.2V以上时,DS1302由VCC2供电,当VCC2低于VCC1时,由VCC1供电。2X1这两个引脚需要接一个32.768K的晶振,给DS1302提供一个基准。3X24GND接地引脚。5CE使能引脚。当读写DS1302时,这个引脚必须是高电平。6I/O串行数据输入/输出端(双向)。7SCLKSerialClock输入引脚,用来作为通信的时钟信号。8VCC1备用电源引脚。12.1.2DS1302芯片寄存器功能寄存器名命令字取值范围各位内容写操作读操作76543210秒寄存器80H81H00-59CH10SECSEC分钟寄存器82H83H00-59010MINMIN小时寄存器84H85H00-12/00-2312/010/PHRHR日期寄存器86H87H01-310010DATEDATE月份寄存器88H89H01-1200010MMONTH星期寄存器8AH8BH01-0700000DAY年份寄存器8CH8DH00-9910YEARYEAR控制寄存器8EH8FH—WP000000024Abit7bit6bit5bit4bit3bit2bit1bit01RAM/CKA4A3A2A1A0R/W本章内容:2DS1302芯片介绍1封装的编程思想和结构体类型22DS1302读写操作的编程实现3DS1302读写实战412.2.1封装的编程思想封装是面向对象编程三大特性(封装、继承、多态)之一核心思想就是尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系就C语言而言,封装的体现就是函数的编写(小封装)和模块文件的编写(大封装)如LCD,IIC总线,EEPROM,键盘等都进行了模块文件的编写lcd1602.c、i2c.c、EEPROM.c、keyboard.c,包括它们各自的头文件(.h)12.2.2结构体的应用1.结构体类型的定义DS1302的日历时钟寄存器可以如下定义:structsCalenda{//日历结构体定义unsignedintyear;//年,加上了‘2’‘0’,所以int类型unsignedcharmon;//月unsignedcharday;//日unsignedcharhour;//时unsignedcharmin;//分unsignedcharsec;//秒unsignedcharweek;//星期};12.2.2结构体的应用2.结构体变量的定义–结构体变量的定义有三种方法•先结构体先定义结构体类型,再定义变量名;•定义结构体类型同时定义结构体类型变量;•直接定义结构体类型变量。structsCalendacalenda;calenda.mon=0x07;//7月Calenda.day=0x19;//19日structsCalenda*calenda;calenda-mon=0x07;calenda-day=0x19;12.2.2结构体的应用3.结构体变量作为函数的参数–指针变量作为函数参数,实际上传递的是结构体变量的地址,并不是结构体变量本身voidGetCurrentTime(structsCalenda*calenda);本章内容:2DS1302芯片介绍1封装的编程思想和结构体类型22DS1302读写操作的编程实现3DS1302读写实战412.3.1操作DS1302寄存器函数的实现1.写DS1302寄存器函数CESCLKI/OA0A1A2A3A4R/C1D0D1D2D3D4D5D6D7R/W12.3.1操作DS1302寄存器函数的实现1.写DS1302寄存器函数voidDS1302WriteReg(unsignedcharreg,unsignedchardat){unsignedcharn;DS1302_CE=1;//将CE置高电平,使能通信for(n=0;n8;n++)//开始传送八位地址命令{DS1302_IO=reg&0x01;//数据从低位开始传送reg=1;DS1302_CK=1;//数据在上升沿时,DS1302读取数据DS1302_CK=0;}for(n=0;n8;n++)//写入8位数据{DS1302_IO=dat&0x01;dat=1;DS1302_CK=1;//数据在上升沿时,DS1302读取数据DS1302_CK=0;}DS1302_CE=0;//传送数据结束}12.3.1操作DS1302寄存器函数的实现1.读DS1302寄存器函数CESCLKI/OR/WA0A1A2A3A4R/C1D0D1D2D3D4D5D6D712.3.1操作DS1302寄存器函数的实现1.读DS1302寄存器函数unsignedcharDS1302ReadReg(unsignedcharreg){unsignedcharn,temp;unsignedchardat=0;DS1302_CE=1;//然后将CE)高电平。for(n=0;n8;n++)//开始传送八位地址命令{DS1302_IO=reg&0x01;//数据从低位开始传送reg=1;DS1302_CK=1;//数据在上升沿时,DS1302读取数据DS1302_CK=0;}for(n=0;n8;n++)//读取8位数据{temp=DS1302_IO;//从最低位开始接收,上升沿之前读dat=(dat1)|(temp7);DS1302_CK=1;//产生上升沿DS1302_CK=0;//DS1302下降沿输出数据,完成一个位的操作}DS1302_CE=0;//传送数据结束returndat;}12.3.2读写函数的封装-DS1302WriteByte/*发送一个字节到DS1302通信总线上*/voidDS1302WriteByte(unsignedchardat){unsignedchari;for(i=0;i8;i++)//低位在前,逐位移出{DS1302_IO=dat&0x01;dat=1;DS1302_CK=1;//然后拉高时钟DS1302_CK=0;//再拉低时钟,完成一个位的操作}DS1302_IO=1;//最后确保释放IO引脚}12.3.2读写函数的封装-DS1302WriteReg/*用单次写操作向某一寄存器写入一个字节,reg:寄存器地址,dat:待写入字节*/voidDS1302WriteReg(unsignedcharreg,unsignedchardat){DS1302_CE=1;//使能片选信号DS1302WriteByte((reg1)|0x80);//发送写寄存器指令DS1302WriteByte(dat);//写入字节数据DS1302_CE=0;//除能片选信号}12.3.2读写函数的封装-DS1302ReadByte/*由DS1302通信总线上读取一个字节*/unsignedcharDS1302ReadByte(){unsignedchari,temp;unsignedchardat=0;for(i=0;i8;i++)//低位在前,逐位读取{temp=DS1302_IO;dat=(dat1)|(temp7);DS1302_CK=1;//然后拉高时钟DS1302_CK=0;//再拉低时钟,完成一个位的操作}returndat;//最后返回读到的字节数据}12.3.2读写函数的封装-DS1302ReadReg/*用单次读操作从某一寄存器读取一个字节,reg:寄存器地址,返回值为读到的字节*/unsignedcharDS1302ReadReg(unsignedcharreg){unsignedchardat;DS1302_CE=1;//使能片选信号DS1302WriteByte((reg1)|0x81);//发送读寄存器指令dat=DS1302ReadByte();//读取字节数据DS1302_CE=0;//除能片选信号returndat;}本章内容:2DS1302芯片介绍1封装的编程思想和结构体类型22DS1302读写操作的编程实现3DS1302读写实战412.4DS1302读写实战【例12.1】在开发板上编程实现如下功能:先将2009年7月19号星期日14点00分00秒这个时间写到DS1302内部,让DS1302正常运行,然后再每隔200ms读取一次DS1302的当前时间,并显示在我们的液晶屏上。本开发板使用了P4.0~P4.2分别连接DS1302芯片的RST复位及使能引脚(CE)、DSIO数据线引脚及SCLK时钟引脚。需要特别注意的是,开发板与步进电机复用了此三个引脚,因此在使用该芯片时请注意跳线的正确连接。12.4DS1302读写实战【例12.1】在开发板上编程实现如下功能:先将2009年7月19号星期日14点00分00秒这个时间写到DS1302内部,让DS1302正常运行,然后再每隔200ms读取一次DS1302的当前时间,并显示在我们的液晶屏上。本开发板使用了P4.0~P4.2分别连接DS1302芯片的RST复位及使能引脚(CE)、DSIO数据线引脚及SCLK时钟引脚。需要特别注意的是,开发板与步进电机复用了此三个引脚,因此在使用该芯片时请注意跳线的正确连接。12.4DS1302读写实战-ds1302.c#includereg52.h#includelcd1602.h#includeDS1302.hbitflag200ms=0;//200ms定时标志unsignedcharT0RH=0;//T0重载值的高字节unsignedcharT0RL=0;//T0重载值的低字节voidConfigTimer0(unsignedintms);12.4DS1302读写实战-ds1302.cvoidmain(){//秒备份,初值AA确保首次读取时间后会刷新显示unsignedcharsecBackup=0xAA;unsignedcharstr[12];//字符串转换缓冲区structsCalendabufTime;//日历缓冲区EA=1;//开总中断ConfigTimer0(1);//T0定时1msInitDS1302();//初始化实时时钟InitLcd1602();//初始化液晶while(1){if(flag200ms){12.4DS1302读写实战-ds1302.cflag200ms=0;GetCurrentTime(&bufTime);//传递是地址if(secBackup!=bufTime.sec){//显示年月日信息str[0]='2';str[1]='0';str[2]=(bufTime.year4)+'0';str[3]=(bufTime.year&0x0F)+'0';str[4]='-';str[5]=(bufTime.mon4)+'0';str[6]=(bufTime.mon&0x0F)+'0';str[7]='-';str[8]=(bufTime.day4)+'0';str[9]=(bufTime.day&0x0F)+'0';str[10]='\0';LcdShowStr(0,0,str);//显示星期信息str[0]=(bufTime.week&0x0F