友情提示:380元/半年,儿童学编程,就上码丁实验室。
DS1302时钟芯片实验
产品介绍
DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,且具有闰年补偿等多种功能。工作电压为2.0V~5.5V。采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后备电源双电源引脚,同时提供了对后备电源进行涓细电流充电的能力。
结构:
DS1302的引脚排列,其中Vcc2为主电源,VCC1为后备电源。在主电源关闭的情况下,也能保持时钟的连续运行。DS1302由Vcc1或Vcc2两者中的较大者供电。当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。当Vcc2小于Vcc1时,DS1302由Vcc1供电。X1和X2是振荡源,外接32.768kHz晶振。RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据传送的方法。当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。上电运行时,在Vcc>2.0V之前,RST必须保持低电平。只有在SCLK为低电平时,才能将RST置为高电平。I/O为串行数据输入输出端(双向),后面有详细说明。SCLK为时钟输入端。 下图为DS1302的引脚功能图:
内部结构:
控制字节:
DS1302 的控制字如图2所示。控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。
数据流:
在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
寄存器:
DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字见表1。
此外,DS1302 还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM相关的寄存器等。时钟突发寄存器可一次性顺序读写除充电寄存器外的所有寄存器内容。DS1302与RAM相关的寄存器分为两类:一类是单个RAM单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;另一类为突发方式下的RAM寄存器,此方式下可一次性读写所有的RAM的31个字节,命令控制字为FEH(写)、FFH(读)。
实验器件及连线
■ DS1302芯片:1片
■ 32.768kHz晶振:1个
■ 多彩面包板实验跳绳:若干
程序代码
Arduino代码:
#include <stdio.h>
#include <string.h>
#include <DS1302.h>
/* 接口定义
CE(DS1302 pin5) -> ArduinoD5
IO(DS1302 pin6) -> ArduinoD6
SCLK(DS1302 pin7) -> ArduinoD7
*/
uint8_t CE_PIN = 5;
uint8_t IO_PIN = 6;
uint8_t SCLK_PIN = 7;
/* 日期变量缓存 */
char buf[50];
char day[10];
/* 串口数据缓存 */
String comdata=”” ;
int numdata[7] ={0}, j = 0,mark = 0;
/* 创建 DS1302 对象 */
DS1302 rtc(CE_PIN, IO_PIN,SCLK_PIN);
void print_time()
{
/* 从 DS1302 获取当前时间 */
Time t = rtc.time();
/* 将星期从数字转换为名称 */
memset(day, 0, sizeof(day));
switch (t.day)
{
case 1: strcpy(day, “Sunday”);break;
case 2: strcpy(day, “Monday”);break;
case 3: strcpy(day, “Tuesday”);break;
case 4: strcpy(day, “Wednesday”);break;
case 5: strcpy(day, “Thursday”);break;
case 6: strcpy(day, “Friday”);break;
case 7: strcpy(day, “Saturday”);break;
}
/* 将日期代码格式化凑成buf等待输出 */
snprintf(buf, sizeof(buf), “%s%04d-%02d-%02d %02d:%02d:%02d”, day, t.yr, t.mon, t.date, t.hr, t.min,t.sec);
/* 输出日期到串口 */
Serial.println(buf);
}
void setup()
{
Serial.begin(9600);
rtc.write_protect(false);
rtc.halt(false);
}
void loop()
{
/* 当串口有数据的时候,将数据拼接到变量comdata */
while (Serial.available() > 0)
{
comdata += char(Serial.read());
delay(2);
mark = 1;
}
/* 以逗号分隔分解comdata的字符串,分解结果变成转换成数字到numdata[]数组 */
if(mark == 1)
{
Serial.print(“You inputed :”);
Serial.println(comdata);
numdata[0] = (comdata[0]-’0′) * 1000 +(comdata[1] – ’0′)+(comdata[2]-’0′) * 100 + (comdata[3] – ’0′);//year
numdata[1] = (comdata[4]-’0′) * 10 +(comdata[5] – ’0′);//month
numdata[2] = (comdata[6]-’0′) * 10 +(comdata[7] – ’0′);//date
numdata[3] = (comdata[8]-’0′) * 10 +(comdata[9] – ’0′);//hour
numdata[4] = (comdata[10]-’0′) * 10 +(comdata[11] – ’0′);//minute
numdata[5] = (comdata[12]-’0′) * 10 +(comdata[13] – ’0′);//second
numdata[6] = (comdata[14]-’0′) * 10 +(comdata[15] – ’0′);//week
/* 将转换好的numdata凑成时间格式,写入DS1302 */
Time t(numdata[0], numdata[1],numdata[2], numdata[3], numdata[4], numdata[5], numdata[6]);
rtc.time(t);
mark = 0;j=0;
/* 清空 comdata 变量,以便等待下一次输入 */
comdata = String(“”);
/* 清空 numdata */
for(int i = 0; i < 7 ; i++)numdata[i]=0;
}
/* 打印当前时间 */
print_time();
delay(1000);
}
实验结论
打开串口监视器可以观察到其中设定的时间的变化。
转自公众号:
29号造物吧