原创内容, 分享保留本页链接。
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连线
代码
#define RST 7
#define SCLK 6
#define IO 5
#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) ;
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;
pinMode(IO,OUTPUT);
digitalWrite(RST,LOW);
digitalWrite(SCLK,LOW) ;
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};
Serial.println(
"set tm ...");
writeAllTm(tm);
}