Arduino 控制 DS1302 时钟芯片

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

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);
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,009评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,808评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,891评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,283评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,285评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,409评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,809评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,487评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,680评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,499评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,548评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,268评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,815评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,872评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,102评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,683评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,253评论 2 341

推荐阅读更多精彩内容