DS1302与AT89C51七段数码管数字时钟电路 一.DS1302概述 DS1302 是 DALLAS 公司推出的涓流充电时钟芯片,内含有一个实时时钟/日 历和 31 字节静态 RAM,通过简单的串行接口与单片机进行通信。实时时钟/日 历电路提供秒、分、时、日、周、月、年的信息,每月的天数和闰年的天数可自 动调整。时钟操作可通过 AM/PM 指示,DS1302 与 单片机之间能简单地采用同步串行的方式进行通信,简易三线SPI通信模式:①RES 复位②I/O 数据线③SCLK 串行时钟。
图(1)DS1302外接端口图 1,VCC2:主电源引脚 2,X1、X2:DS1302 外部晶振引脚,通常需外接 32.768K 晶振 3,GND:电源地 4,CE:使能引脚,也是复位引脚(新版本功能变)。 5,I/O:串行数据引脚,数据输出或者输入都从这个引脚 6,SCLK:串行时钟引脚 7,VCC1:备用电源 2.ds1302控制寄存器 用于存放控制DS1302命令,可以控制该寄存器以控制选择读或写等操作。
图(2)ds1302控制寄存器 1.第7位,固定为1 2.第6位,1为寻址内部存储器地址RAM,0为寻址内部寄存器,即年月日所在存储器,一般设置为0 3.第5到1位,第6位存储器的地址 4.第0位,1位读操作,0为写操作 具体由下图所示。
图(3)命令表 3.DS1302时序图
图(4)单字节写
图(5)单字节读 CE:复位时序 SCLK:时钟时序 IO:数据传输时序 上升沿写,下降沿读 4. DS1302储存器格式
图(6)DS1302储存器格式 5.主程序 #include <reg51.h> #include <intrins.h> #define uchar unsigned char #define uint unsigned int uchar wei[6]={0Xfb,0Xf7,0XEf,0XDf,0XBf,0X7f}; 控制各位显示通断 sbit dula=P2^6; sbit wela=P2^7; sbit sclk=P3^5;脉冲 sbit io=P3^6;IO数据 sbit ce=P3^7;使能端 uchar code table_du[]={ 0x3f,0x06,0x5b,0x4f,0x66,0x6d, 0x7d,0x07,0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71};存放0——F之后对应 uchar time_data[]={13,6,4,17,11,58,30};初始设定时间,年星期月日时分秒 uchar write_add[]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};1302寄存器存入命令年星期月日时分秒 uchar read_add[]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};1302寄存器读出命令年星期月日时分秒 uchar disp[6];六个七段数码管准备写入的数 delay(uchar x)延时电路200x { uchar a,b; for(a=x;a>0;a–) for(b=200;b>0;b–); } void write_ds1302_byte(uchar add) 单字节写写入时间或命令一次写八位SCLK:串行时钟引脚 { uchar i; for(i=0;i<8;i++) { sclk=0;制造下降沿 io=add&0x01;用IO进行数据传输取与,取第0位 add=add>>1;将add右移一位 sclk=1;制造上升沿 此时读取io口数据进行传输 } } void write_ds1302(uchar add,uchar dat)单字节写入时间 { ce=0;复位引脚 sclk=0;脉冲置零 ce=1;片选准备读写 _nop_();等待下一个周期 write_ds1302_byte(add);前八个脉冲周期命令周期,给ds1302控制寄存器 write_ds1302_byte(dat);后八个周期数据交互写入16进制数 ce=0; _nop_(); io=1; sclk=1; } uchar read_ds1302(uchar add)单字节读取时间 { uchar i,value; ce=0;使能端 sclk=0;脉冲置零为上升沿写命令做准备 ce=1;选中1302 _nop_();等待一个周期 write_ds1302_byte(add);写入读命令 for(i=0;i<8;i++) { value=value>>1;右移一位 sclk=0;下降沿读取数据 if(io) { value=value|0x80; }因为1302只有一根数据线,一个时钟周期只能传1bit,而你要读的数据VALUE是8bit的,所以程序要读取8次IO,组成一个8bit的数据。 在每次循环中VALUE初值是0,先右移一次,结果还是0(右移的时候是最高位填充的是0)。 每次读取IO的时候都是先判断IO的信号,如果是1就把最高位置1(value=value|0x80),如果是0就不置1,最高位为0(右移的时候是最高位填充的是0)。 这样循环8次后就得到了你想要的8bit数据。 sclk=1; } ce=0; _nop_(); sclk=0; _nop_(); sclk=1; io=1; return value;输出时间 } void set_rtc()写入初始值 { uchar i,j,k; for(i=0;i<7;i++)输入为10进制数,转换为16进制写入 { j=time_data[i]/10;除10取整 k=time_data[i]%10;除10取余 time_data[i]=k+j*16;整数×16加余数 } write_ds1302(0x8e,0x00);关闭写保护 for(i=0;i<7;i++) { write_ds1302(write_add[i],time_data[i]);将16进制初始时间输入1302中 } write_ds1302(0x8e,0x80);打开写保护 } void read_rtc()读取时间 { uchar i; for(i=0;i<7;i++) { time_data[i]=read_ds1302(read_add[i]);将读到的数给写入库read_add[i]为读命令 } } void time_pros()进行数的转化16进制转化为10进制 { disp[0]=time_data[4]/16; disp[1]=time_data[4]%16; disp[2]=time_data[5]/16; disp[3]=time_data[5]%16; disp[4]=time_data[6]/16; disp[5]=time_data[6]%16; } void display()显示函数 { P2=0XFF;复位 P0=table_du[disp[0]];显示第一位在库里找第几位转化为共阴极显示的数 P2=wei[0];写入第一个七段数码管 delay(3);延时 P2=0XFF; P0=table_du[disp[1]]; P2=wei[1]; delay(3); P2=0XFF; P0=table_du[disp[2]]; P2=wei[2]; delay(3); P2=0XFF; P0=table_du[disp[3]]; P2=wei[3]; delay(3); P2=0XFF; P0=table_du[disp[4]]; P2=wei[4]; delay(3); P2=0XFF; P0=table_du[disp[5]]; P2=wei[5]; delay(3); P2=0XFF; } void main()主函数 { set_rtc();给1302写入初始值 while(1)循环 { read_rtc();读取时间 time_pros();数据转化为10进制 display();显示函数 } } 6.仿真
图(7)DS1302接线图
图(8)主电路图
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/87462.html