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/96882.html