单片机基础模块——DS1302模块
1.简介
DS1302 是DALLAS 公司推出的滑流充电时钟芯片,内含有一个实时时钟/日历和 31字节静态RAM, 通过简单的串行接口与单片机进行通信。实时时钟/日历电路提供秒、分、时、日、日期、月、年的信息,每月的天数和国年的天数可自动调整,时钟操作可通过 AM/PM 指示决定采用 24 或 12 小时格式。DS1302 与单片机之间能简单地采用同步串行的方式进行通信,仅需用到三个口线:(1)RES(复位),(2)I/O(数据线),(3)SCLK(串行时钟)。时钟/RAM的读/写数据以一个字节或多达 31 个字节的字符组方式通信。DS1302 工作时功耗很低,保持数据和时钟信息时功率小于1mW。
DS1302 是由 DS1202 改进而来,增加了以下的特性:双电源管脚用于主电源和备份电源供应,Vccl 为可编程滑流充电电源,附加七个字节存储器。它广泛应用于电话、传真、便携式仪器以及电池供电的仪器仪表等产品领域。
2.管脚配置
3.原理图
在写程序时只需控制5 6 7三个引脚的端口即可,其他管脚已配置完毕。
寄存器:
在最后一位地址即0对应的那个格子,1 – 读取寄存器 0 – 写入寄存器
以输入57秒为例,因为要写入数据,所以地址为1000 0000 –> 0x80,然后将57转换为BCD码即0x57写入。需要注意的是在写小时的时候有12进制和24进制,当最高位写0时代表使用24进制,写1时代表使用12进制。
在该芯片的数据手册中可以找到地址,不必自己推。
4.DS1302内部寄存器
只有在振荡器工作允许条件下才可以实现时钟功能,由数据手册可知,当设置秒时,十位最高位5,用二进制表示则为101,即最多占用三位,CH是最高位默认为0
5.时序
5.1 写入
//定义一个写入函数,这里仅用来写入数据
Void Write_Ds1302(unsigned char temp)//入口参数为需要写入的数据
{
unsigned char i;//定义一个变量i循环八次,相当于把每一位写入
for(i=0;i<8;i++)
{
SCK = 0;//先将信号拉低
SDA = temp&0x01;//SDA即为I/O,与上0x01后,前七位均为零,相当于屏蔽高七位,只留最后一位
temp >>= 1;//temp右移相当于0x01左移,意思就是从低位开始,每次取一个值,temp右移一位更好理解,第二次循环则屏蔽前六位,和上一次循环识别的那一位,只进行倒数第二位的操作。
SCK = 1;//再将信号拉高,进行信号读取
}
}
例如将1010 0000输入最终写入I/O的顺序为0000 0101,这里并不是反的,从低位读取,而这里R/W –> 1从左到右就是由低位到高位。
void Write_Ds1302_Byte(unsigned char address,unsigned char dat)//两个入口参数,分别为地址和数据
{
RST = 0; _nop_();//先将信号拉低,_nop_()的作用是等待一段时间
SCK = 0; _nop_();//然后将SCK信号拉低
RST = 1; _nop_();//再将信号拉高
Write_Ds1302(address);//写入地址
Write_Ds1302(dat);//写入数据
RST = 0;//将信号拉低
}
[注意]上述两个代码在比赛时官方会给出,在底层驱动代码参考中可找到。
5.2 读取
//定义一个读取函数
unsigned char Read_Ds1302_Byte(unsigned char address)//入口参数为地址
{
unsigned char i,temp = 0x00;//变量i用于循环,temp用于接收读取的数据
RST = 0; _nop_();//拉低
SCK = 0; _nop_();//拉低
RST = 1; _nop_();//拉高
Write_Ds1302(address);//写入地址
for(i=0;i<8;i++)
{
SCK = 0;//拉低
temp >>= 1;//向右移1位
if(SDA)//如果SDA有数据为1时,执行下列语句
temp |= 0x80;//或上0x80 --> 1000 0000
SCK = 1;//拉高
}
RST = 0; _nop_();
SCK = 0; _nop_();
SCK = 1; _nop_();
SDA = 0; _nop_();
SDA = 1; _nop_();
return(temp);
}
6. ds1302.c 代码
首先到赛点资源包里找到DS1302的.c和.h文件,复制到Driver文件夹下,为了避免报错,将.h文件中预定义的头文件复制到.c文件中
#include <reg52.h>
#include <intrins.h>
sbit SCK = P1^7;
sbit SDA = P2^3;
sbit RST = P1^3;
写一个程序将时分秒均写入芯片中再进行读取,写完后需将新写的变量在.h文件中进行声明
//写入
void Set_Rtc(unsigned char* ucRtc)//Rtc相当于用户的时钟,定义入口参数,使用指针,ucRtc为一个数组,数组的名字相当于地址
{
unsigned char i;//该变量用于for循环
Write_Ds1302_Byte(0x8e,0x00);//写地址函数,这里的0x8e可以在数据手册里查找,为了写保护位,所以WP = 0,即0x00
for(i=0;i<3;i++)
Write_Ds1302_Byte(0x84-2*i,ucRtc[i]);
// Write_Ds1302_Byte(0x84,ucRtc[0]);//小时,通常默认为24小时制,数组的第0位存放需要写入的数据
// Write_Ds1302_Byte(0x82,ucRtc[1]);
// Write_Ds1302_Byte(0x80,ucRtc[2]);
Write_Ds1302_Byte(0x8e,0x80);//关闭保护位,即WP = 1,1000 0000 --> 0x80
}
//读取
void Read_Rtc(unsigned char* ucRtc)//以数组的形式存储起来
{
unsigned char i;//该变量用于for循环
for(i=0;i<3;i++)
ucRtc[i] = Read_Ds1302_Byte(0x85-2*i);
// ucRtc[0] = Read_Ds1302_Byte(0x85);//小时,将读出的数据存到数组的第0位
// ucRtc[1] = Read_Ds1302_Byte(0x83);
// ucRtc[2] = Read_Ds1302_Byte(0x81);
}
[补充]BCD码
B —— 二进制 D —— 十进制,所以 BCD码本质上是二进制和十进制互相转换
将BCD码转换为十进制:
将十进制转换为BCD码:
其他进制数求BCD码时,需先将其他进制转换为十进制,再求BCD码
作者:Moonnnn.