1
嵌入式软件/开发板
X1 X2 32.768KHz ————晶振管脚
GND ———— 地
RST ———— 复位脚
I/O ————数据输入/输出引脚
SCLK ———— 串行时钟
Vcc1,Vcc2 ————电源供电管脚
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的电路一个重点就是时钟电路,它所使用的晶振是一个32.768k的晶振,晶振外部也不需要额外添加其他的电容或者电阻电路了。时钟的精度,首先取决于晶振的精度以及晶振的引脚负载电容。如果晶振不准或者负载电容过大过小,都会导致时钟误差过大。在这一切都搞定后,最终一个考虑因素是晶振的温漂。随着温度的变化,晶振往往精度会发生变化,因此,在实际的系统中,其中一种方法就是经常校对。比如我们所用的电脑的时钟,通常我们会设置一个选项“将计算机设置于internet时间同步”。选中这个选项后,一般可以过一段时间,我们的计算机就会和internet时间校准同步一次。
1脚VCC2是主电源正极的引脚,2脚X1和3脚X2是晶振输入和输出引脚,4脚GND是负极,5脚CE是使能引脚,接单片机的IO口,6脚I/O是数据传输引脚,接单片机的IO口,7脚SCLK是通信时钟引脚,接单片机的IO口,8脚VCC1是备用电源引脚。考虑到KST-51开发板是一套以学习为目的的板子,加上备用电池对航空运输和携带不方便,所以8脚没有接备用电池,而是接了一个10uF的电容,这个电容就相当于一个电量很小的电池,经过试验测量得出其可以在系统掉电后仍维持DS1302运行1分钟左右,如果大家想运行时间再长,可以加大电容的容量或者换成备用电池,如果掉电后不需要它再维持运行,也可以干脆悬空,如图15-7和图15-8所示。
涓流充电功能,基本也用不到,因为实际应用中很少会选择可充电电池作为备用电源,成本太高,本课程也不讲了,大家作为选学即可。我们使用的时候直接用5V电源接一个二极管,在主电源上电的情况下给电容充电,在主电源掉电的情况下,二极管可以防止电容向主电路放电,而仅用来维持DS1302的供电,这种电路的最大用处是在电池供电系统中更换主电池的时候保持实时时钟的运行不中断,1分钟的时间对于更换电池足够了。此外,通过我们的使用经验,在DS1302的主电源引脚串联一个1K电阻可以有效的防止电源对DS1302的冲击,R6就是这个电阻,而R9、R26、R32都是上拉电阻。
通过命令的方式写入年月日时分秒信息。 命令格式为2字节。 第一字节为地址,第二字节为内容。
写入逻辑:
1 将RST先拉低
2 将SCLK拉低(如果不拉低,且本来是高电平,则瞬间就发出了一个bit,我们还没放数据呢)
3 再RST拉高。。 形成一个上升沿
4 在IO口放入一个bit(字节发送顺序,从低位到高位)
5 设SCLK为高电平,形成上升沿,这时候DS1302就会读取IO口的数据存入它的寄存器。
6 拉低SCLK,为下一个字节做准备。,跳转到5 ,直到发送完所有的16个字节
7 拉低RST,整个写入过程完成。
虽然命令字节看起来很复杂,但编写程序很简单,比如你要设置秒为13秒。那么发送的两个字节的数据应该是什么?第一个字节是0x80(写入秒的命令,见上图)。第二个数据,第四位为3,高四位为1。就是(1<<4)|3,为0x13
其他的年月日类似。比较特殊的几个位说一下。
(1)如果想让表停下来
发送一个设置秒的命令,第二个字节最高位置为1,即,发送0x800x80即可。
(2)小时的第二个字节的最高位控制着12还是24进制
/* * 读写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端口 d
elayMicroseconds(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);
}
全部0条评论
快来发表一下你的评论吧 !