Arduino 控制 DS1302 时钟芯片

xiaoxiao2021-02-28  98

原创内容, 分享保留本页链接。

DS1302 芯片介绍

一个时钟芯片,可以设置和获取当前时间。 可以自动处理月份、闰年等信息。

两个电源,可以使用外接电源和电池同时供电。系统会选用电压较高的一个供电。这样,可以接一个3v的纽扣电池, 接5v的外接电源,当外界电源断电后,就会使用纽扣电池供电。

封装

(1) VCC2 VCC1 (8) (2) X1 SCLK (7) (3) X2 I/O (6) (4) GND ‘RST (5)

引脚意义

VCC1 和VCC2 ,如上所述,为两个供电电源。 X1 和X2 接32768Hz晶振 SCLK和IO和RST共同完成通讯过程。 SCLK为通讯的时钟信号。当RST为高电平时,开始通讯。

写入时序

通过命令的方式写入年月日时分秒信息。 命令格式为2字节。 第一字节为地址,第二字节为内容。

写入逻辑: 1 将RST先拉低 2 将SCLK拉低(如果不拉低,且本来是高电平,则瞬间就发出了一个bit,我们还没放数据呢) 3 再RST拉高。。 形成一个上升沿 4 在IO口放入一个bit(字节发送顺序,从低位到高位) 5 设SCLK为高电平,形成上升沿,这时候DS1302就会读取IO口的数据存入它的寄存器。 6 拉低SCLK,为下一个字节做准备。,跳转到5 ,直到发送完所有的16个字节 7 拉低RST,整个写入过程完成。

读取逻辑

读取逻辑和写入相似,区别在于写入一个字节后,读取一个字节。

1 发送一个字节过程与写入完全相同。 2 发送完最后一个bit后,SCLK为高电平,这时候先将单片机IO口设为读取端口 3 拉低SCLK 4 读取IO口数据(数据也是从低位到高位读取的) 5 拉高SCLK,跳转到3 ,直到读取完8各位 6 拉低RST

命令格式

虽然命令字节看起来很复杂,但编写程序很简单,比如你要设置秒为13秒。那么发送的两个字节的数据应该是什么? 第一个字节是 0x80 (写入秒的命令,见上图)。第二个数据,第四位为3,高四位为1 。 就是 (1<<4) | 3 , 为0x13

其他的年月日类似。 比较特殊的几个位说一下。

(1)如果想让表停下来(不往下走了,怎么办?) 发送一个设置秒的命令, 第二个字节最高位置为1 ,即,发送 0x80 0x80 即可。

(2) 小时的第二个字节的最高位控制着12还是24进制

Arduino连线

代码

/* * 读写DS1302 时钟芯片 * @author Yangtf * 很棒的文档 http://www.21ic.com/jichuzhishi/datasheet/DS1302/data/185858.html * 时序图 http://www.21ic.com/d/file/201307/0a93263a0126e1580cc71c89dce1fda9.jpg * */ #define RST 7 #define SCLK 6 #define IO 5 //#define L(item) digitalWrite((item),LOW) //#define H(item) digitalWrite((item),HIGH) #define uchar unsigned char void setup() { pinMode(RST,OUTPUT); pinMode(SCLK,OUTPUT); pinMode(IO,OUTPUT); Serial.begin(9600); attachInterrupt(0, settm, FALLING ); } void writeData(unsigned char addr,unsigned char dat){ pinMode(IO,OUTPUT); digitalWrite(RST,LOW); //下拉低,再拉高 digitalWrite(SCLK,LOW) ; //SCLK的上升沿, 芯片会读取IO端口 delayMicroseconds(1); digitalWrite(RST,HIGH); int i; for(i =0;i<8;i++){ digitalWrite(SCLK,LOW); digitalWrite(IO, addr&1); addr =addr>>1; digitalWrite(SCLK,HIGH); delayMicroseconds(1); } for(i =0;i<8;i++){ digitalWrite(SCLK,LOW); digitalWrite(IO, dat&1); dat =dat>>1; digitalWrite(SCLK,HIGH); delayMicroseconds(1); } digitalWrite(RST,LOW); } uchar readData(uchar addr){ addr = addr | 1; //读操作最低位置为1 pinMode(IO,OUTPUT); digitalWrite(RST,LOW); //下拉低,再拉高 digitalWrite(SCLK,LOW) ; //SCLK的上升沿, 芯片会读取IO端口 delayMicroseconds(1); digitalWrite(RST,HIGH); int i; for(i =0;i<8;i++){ digitalWrite(SCLK,LOW); digitalWrite(IO, addr&1); addr =addr>>1; digitalWrite(SCLK,HIGH); delayMicroseconds(1); } pinMode(IO,INPUT); int dat = 0; for(i =0;i<8;i++){ digitalWrite(SCLK,LOW); delayMicroseconds(10); uchar b = digitalRead(IO); dat = dat >>1; //先向右平移 dat = dat | (b<<7); //将所得放入最高位 digitalWrite(SCLK,HIGH); delayMicroseconds(1); } digitalWrite(RST,LOW); return dat ; } #define SECOND 0x80 #define MIN 0x82 #define HOUR 0x84 #define DAY 0x86 #define MONTH 0x88 #define YEAR 0x8C #define WEEK 0x8A void writeTimeUnit(uchar TYPE,uchar data){ uchar high = data / 10; uchar low = data % 10; uchar d = ((data /10) << 4) | (data % 10); writeData(TYPE,data); } uchar readTimeUnit(uchar TYPE){ uchar r = readData(TYPE); r = 10*(r >> 4)+ (r & 0xf); return r; } void writeAllTm(uchar tm[]){ uchar s = SECOND; for(uchar i=0;i<5;i++){ writeTimeUnit(s,tm[5-i]); s+=2; } writeTimeUnit(YEAR,tm[0]); } void readAllTm(uchar tm[]){ uchar s = SECOND; for(uchar i=0;i<5;i++){ tm[5-i] = readTimeUnit(s); s+=2; } tm[0] = readTimeUnit(YEAR); tm[6] = readTimeUnit(WEEK); } void printTm(uchar tm[]){ Serial.print(tm[0]); Serial.print("-"); Serial.print(tm[1]); Serial.print("-"); Serial.print(tm[2]); Serial.print(" "); Serial.print(tm[3]); Serial.print(":"); Serial.print(tm[4]); Serial.print(":"); Serial.print(tm[5]); Serial.print(" week "); Serial.print(tm[6]); Serial.println(); } uchar st = 0; void loop() { uchar tm[7] = {0}; readAllTm(tm); printTm(tm); delay(1000); } void settm()//中断函数 { uchar tm[] = {11,12,13,4,5,6 ,0}; // 2011-12-22 3:4:1 Serial.println("set tm ..."); writeAllTm(tm); }
转载请注明原文地址: https://www.6miu.com/read-69850.html

最新回复(0)