单片机外设驱动-DS1302
介绍:
什么是DS1302?
DS1302是美国DALLAS公司推出的高性能、低功耗的实时时钟,附加31字节的静态RAM,采用SP三线接口与MCU进行同步通信,并可采用突发方式一次传送多个字节的时钟参数和RAM数据。时钟计数功能,可以对秒、分钟、小时、月、星期、年的计数,年计数可达到2100 年。
简单来说,DS1302的使用方法和我们平时使用电子手表差不多,你可以设定时间,也可以读取时间,只不过这些工作是通过SPI接口有MCU去完成而已。
在DS1302中有两块存储器:日历时钟寄存器和今天RAM存储器。前者用于记录实时时间,后者用于记录其他数据。对于基本计时应用,重点关注的是日历时钟寄存器。设定时间参数就是往这些寄存器写入内容,读取实时时间也是从这些寄存器读出数据。
芯片参数:
1.芯片功能
- 实时时钟计算年、月、日、时、分、秒、星 期,直到 2100 年,并有闰年调节功能
- 31 x 8 位 通用暂存 RAM
- 串行输入输出,使管脚数最少
- 2.0V 至 5.5V 宽电压范围操作
- 在 2.0V 时工作电流小于 300nA
- 读写时钟或 RAM 数据时有单字节或多字节(脉冲串模式)数据传送方式
- 8 管脚 DIP 封装或可选的 8 管脚表面安装 SO 封装
- 简单的 3 线接口
- 与 TTL 兼容 (VCC = 5V)
- 可选的工业温度范围:-40°C to +85°C
2.引脚说明
DS1302采用三线接口的双向数据通信接口。
RST:片引脚,低电平有效
SCLK:时钟芯片,为通信提供时钟源
I/O:为数据输入输出引脚,用于传输及接收数据
VCC1:连接到备用电源,VCC2:主电源失效时保持时间和日期数据
参考电路
上图为CT107D平台的电路原理图
控制程序
1.日历时钟寄存器
DS1302有关日历和时钟的寄存器有12个,而我们用其中的7个就已经足够了。
什么是BCD码?
用十六进制来表示十进制。
例:十六进制数0x15的值为十进制的21,而BCD码表示的是整数15。
这在一会我们编程的时候需要用到。
2.接口时序的实现
DS1302的基本操作实际上非常简单,只有两个操作:设定时间参数,读取实时时间。
控制字都是从最低位开始输出的。在控制字输入后的下一个SCLK时钟信号的上升沿,数据被写入DS1302,数据的输入从最低位开始;在控制字指令输入后的下一个SCLK时钟信号的下降沿,数据从DS1302读出,数据的读出也是从最低位到最高位。
单字节写的时序:
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0; i<8; i++)
{
SCK=0;
SDA=temp&0x01;
temp>>=1;
SCK=1;
}
}
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
单字节读的时序
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_();
Write_Ds1302(address);
for (i=0; i<8; i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0;
_nop_();
SCK=0;
_nop_();
SCK=1;
_nop_();
SDA=0;
_nop_();
SDA=1;
_nop_();
return (temp);
}
DS1302参数配置
//读寄存器
unsigned char code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
//写寄存器
unsigned char code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
void DS1302_Config()
{
unsigned char n;
Write_Ds1302_Byte(0x8E,0x00); //允许向内存写入数据
for (n=0; n<7; n++) //写入时间参数
{
Write_Ds1302_Byte(WRITE_RTC_ADDR[n],TIME[n]);
}
Write_Ds1302_Byte(0x8E,0x80); //禁止向内存写入数据
}
Write_Ds1302_Byte函数中的0x8E,0X00,0X80又是什么意思呢?
其实对照着寄存器写入格式就能够清晰的理解:往0x8E(写寄存器)里面写入数据,而数据则为0X00,0X80
WP为0时,可对任何的时钟或RAM寄存器进行写操作。
WP为1时,禁止对任一寄存器进行写操作。
DS1302时间数据读取
void DS1302_ReadTime()
{
unsigned char n;
for (n=0; n<7; n++) //读时间参数
{
TIME[n] = Read_Ds1302_Byte(READ_RTC_ADDR[n]);
}
}
DS1302时间显示到数码管
unsigned char TIME[7] = {0x30, 0x50, 0x23, 0x17, 0x02, 0x06, 0x18};
void display_time()
{
DS1302_ReadTime();
updateLed(0,TIME[2]/16);
updateLed(1,TIME[2]%16);
updateLed(2,11);
updateLed(3,TIME[1]/16);
updateLed(4,TIME[1]%16);
updateLed(5,11);
updateLed(6,TIME[0]/16);
updateLed(7,TIME[0]%16);
}
值得注意的是:这里显示到数码管是按照高四位低四位分别显示的,所以用/16取高四位,%16取低四位。
至于数码管驱动之后会写文章