芯片引脚图
DS1307是低功耗、两线制串行读写接口、日历和时钟数据按BCD码存取的时钟/日历芯片。它提供秒、分、小时、星期、日期、月和年等时钟日历数据。另外它还集成了如下几点功能:
(1)56 字节掉电时电池保持的NV SRAM 数据存储器
(2)可编程的方波信号输出
(3)掉电检测和自动切换电池供电模式
DS1307 把8 个寄存器和56 字节的RAM 进行了统一编址,具体地址和寄器数据组织格式如下表:
(日期为BCD码)
在读写过程中DS1307 内部维护一个地址指针,通过写操作可对它 值,读和写每一字节时自动加一,当指针越过DS1307 内部RAM 尾 时指针将返回到0 地址处。
DS1307 的时钟和日历数据按BCD 码存储。
DS1307
串行实时时钟记录年、月、日、时、分、秒、星期及日期; AM、PM 分别表示上午和下午; 56 个字节的NVRAM存放数据; 2线串口; 可编程的方波输出;电源故障检测及自动切换电路;电池电流小于500nA。
主要引脚定义如下: X1、32.768kHz 晶振接入端;
VBAT:X2:+3V 电池电压输入;
SDA: 串行数据;
SCL:串行时钟;
SQW/OUT:方波/输出驱动器。
方波信号输出功能从SQW/OUT 引脚输出设置频率的方波,CONTROL 寄存器用于控制SQW/OUT 脚的输出。
BIT7(OUT):此位表示在方波输出被禁止时(BIT4=0),SQW/OUT 引脚的逻辑电平,在BIT4=0(SQWE=0方波输出禁止)时,若BIT7(OUT) 为1 则SQL/OUT 引脚为高电平, 反之亦然。
BIT4(SQWE)方波输出允许/禁止控制位,SQWE =1 允许方波输出(有效);BIT4=0 禁止方波输出。
BIT0(RS0)、BIT1(RS1)于设定输出波形的频率,如下表:
要注意的是,00h 地址的第7 位为器件时钟允许位(CH),由于在在开始上电时内部RAM内容随机,所以在初始化时将CH 位设零(时钟允许)是非常重要的。
DS1307 在TWI 总线上是从器件,地址(SLA)固定为”11010000”
主控器件按如下顺序将数据写入到DS1307 寄存器或内部RAM 中:
第一步.START 信号
第二步。写SLA+W(0xd0)字节,DS1307 应答(ACK)
第三步。写1 字节内存地址(在以下第四步写入的第一字节将存入到DS1307 内该地址处),DS1307应答。
第四步。写数据(可写多个字节,每一字节写入后DS1307 内部地址计数器加一,DS1307 应答)
第五步.STOP 信号
主控器件按如下顺序将DS1307 寄存器或内部RAM 数据读取:
第一步.START 信号
第二步。写SLA+R(0xd1)字节,DS1307 应答(ACK)
第三步。读数据(可读多个字节,读取数据的DS1307 内部地址由上次写操作或读操作决定,读取每一字节DS1307 内部地址计数器加一,主器件应答,读取最后一字节时主器件回应一NACK信号)
第四步.STOP 信号
实时时钟(RTC)计算秒,分钟,小时,月,月,日的日期周和年份,闰年补偿,有效期至2100年
56字节,由电池供电,通用RAM与无限写操作I2C串行接口可编程方波输出信号
自动电源失效检测和切换电路消耗的电池备份超过500nA的少与振荡器运行模式
可选的工业温度范围:-40°C至+ 85°C提供8引脚塑料DIP或SO
美国保险商实验室(UL)认证
//********************************************************************
//***************************DS1307调试 *****************************
//********************************************************************
//**DS1307实时时钟芯片地址0xD0 读0xD1 写0xD0 *********************
//********************************************************************
#include《reg51.h》 //单片机80C51
sbit SCL=P1^1; //串口时钟信号
sbit SDA=P1^0; //串口数据信号
sbit clock=P1^2; //调试用脉冲输出信号**************
unsigned char error; //通讯正常error=0x10;超时error=0x11
void delay(int i); //延时子函数
void TimeInitial(); //时钟初始化子函数
void Start_I2C(); //打开串口子函数
void Stop_I2C (); //关闭串口子函数
void Ack_I2C(); //接受应答信号并判断是否正常子函数
void SendAck(); //发送应答信号子函数
void SendNotAck(); //发送非应答信号子函数
void Send_I2C (int ch); //向总线上发送一个字节
unsigned int Receive_I2C(); //在总线上接受一个字节
int read_time(int address); //从芯片D1307读出10为字节 地址1:秒 2:分 3:时 4:星期 5:号 6:月7:年 8 控制字
void write_time(int address,int date); //向芯片D1307 之中地址为address的寄存器写入数据date 仅为八位字节
void main() //主程序************************************************************
{
TimeInitial(); //时钟初始化
write_time(0x07,0x10); //向芯片D1307写入控制字(芯片地址0X07)0x10 控制字:1晶振使能(0有效)4:SOUT方波输出 7、8:方波频率编码
while(1)
{
}
}
void TimeInitial() //时钟初始化
{
TMOD=0x10; //时钟选择方式2 T1时钟
TH1=0x15;
TL1=0xA0; //定时60ms
EA=1; //中断准许
ET1=1; //时钟T1 溢出中断准许
TR1=1; //启动时钟T1
}
//**********************************延时
void delay(int i)
{
int j,h;
for(j=1;j《99;j++)
{
for(h=0;h《i;h++)
;
}
}
//**********************************传送启动
void Start_I2C()
{
EA=0; //关闭中断
SCL=0; //总线放空,以便更改总线数据
delay(1); //延时
SDA=1; //发送I2C总线起始条件的数据信号1以便总线使能时产生下降沿
delay(1); //延时
SCL=1; //发送I2C总线起始条件的时钟信号
delay(1); //延时
SDA=0; //产生下降沿 总线传输开始
delay(1); //延时
SCL=0; //时钟线从高到低一次跳变,总线放空 准备传输数据
}
//**********************************传送关闭
void Stop_I2C ()
{
SCL=0; //发送I2C总线时钟信号放空
SDA=0; //发送I2C总线停止条件的数据信号0以便产生上升沿
delay(1); //延时
SCL=1; //时钟线从低到高一次跳变 总线 使能
delay(1); //延时
SDA=1; //发送I2C总线数据信号产生上升沿 终止传送
delay(1); //延时
SCL=0; //发送I2C总线时钟信号放空
delay(1);
SDA=0; //发送I2C总线放空 准备下次动作
EA=1; //传输结束开启中断
}
//**********************************传送响应
void Ack_I2C()
{
unsigned char errtime=255; //因故障接收方无ACK,超时值为255。
SDA=1; //数据线升高,以便捕捉相应信号,(相应信号:拉低数据线)
SCL=1; // 主机放出一脉冲,等待捕捉相应信号
error=0x10; //通讯正常(即:接受到了相应信号)为0X10;
while(SDA) //等待捕捉相应信号,信号没有到来前一直保持循环,信号到来后迅速跳出循环
{
errtime--; //每循环一次,倒计时减一
if(!errtime) //判断倒计时是否减到了0,即循环了255次,如果减到了0,判定此次通讯未接受到响应信号,传送失败
{
Stop_I2C (); //传送失败,停止传送
error=0x11; //传送结果未传送失败0x11
return; //跳出循环
}
}
SCL=0; //无论传送是否正确,都需放空总线,以备后用
}
//**********************************向总线传送响应
void SendAck()
{
SDA=0; //数据线保持拉低,时钟线发生一次从高低的跳变 发送一个应答信号
delay(1);
SCL=1;
delay(1);
SCL=0;
}
//**********************************向总线传送非响应
void SendNotAck()
{
SDA=1; //数据线保持高,时钟线发生一次从高低的跳变 没有应答
delay(1);
SCL=1;
delay(1);
SCL=0;
}
//**********************************向总线传送字节
void Send_I2C (int ch)
{
int i;
for (i=1;i《=8;i++) //发送八位
{
SCL=0; //总线放空
delay(1); //延时
SDA=(ch&0x80); //根据给定数据,又高位到低位逐步提出字节位,发送到总线上
ch《《=1; //左循环以便输出下一位
delay(1); //延时
SCL=1; //总线使能,发送总线数据
delay(1); //延时
}
SCL=0; //总线8位传送完成,总线放空
}
//**********************************向总线读入字节
unsigned int Receive_I2C()
{
unsigned char i,a;
SDA=1; //不知道为啥,1的时候读入正确 0的时候读入全部为0;
for (i=1;i《=8;i++) //读入八个位
{
a《《=1; // 读入数据左循环
SCL=0; //总线放空
delay(1);
SCL=1; //时钟做一次从低到高的跳变 可以接收一位数据
delay(1);
a|=SDA; // 将数据编入变量a
}
SCL=0; //总线放空
return a; //反馈接收到的信息
}
//**********************************向芯片D1307 之中地址为address的寄存器写入数据date 仅为八位字节
void write_time(int address,int date)
{
Start_I2C(); //启动总线
Send_I2C (0xD0); //呼叫芯片D1307,并定义为 写 动作
Ack_I2C(); //等待响应信号
Send_I2C (address); //发送地址
Ack_I2C(); //等待响应信号
Send_I2C (date); //发送数据
Ack_I2C(); //等待响应信号
Stop_I2C (); //停止总线
}
//****************从芯片D1307读出10为字节 地址1:秒 2:分 3:时 4:星期 5:号 6:月7:年 8 控制字
int read_time(int address)
{
int a[10]; //定义一个数组以便接受数据
int i=1;
Start_I2C(); //启动传送
Send_I2C (0xD0); //呼叫芯片D1307,并定义为 写 动作
Ack_I2C(); //等待响应信号
Send_I2C (0x00); //发送起始地址
Ack_I2C(); //等待响应信号
Stop_I2C (); //关闭总线
Start_I2C(); //启动总线
Send_I2C (0xD1); //呼叫芯片D1307,并定义为 读 动作
SendAck(); //发送应答就位,准备接受数据
for(i;i《10;i++)
{
a[i]=Receive_I2C(); //接受自初始地址开始的10个字节 地址1:秒 2:分 3:时 4:星期 5:号 6:月7:年 8 控制字
SendAck(); //每成功接受一位发送一个响应信号 以便接受下一位
}
Stop_I2C (); //接受完成停止
return a[address]; //反馈所需数据
}
void t1(void) interrupt 3 using 0 //T1溢出中断
{
TH1=0x15;
TL1=0xa0; //重新载入60ms
clock=~clock; //调试用脉冲
P0=read_time(1); //将实时时钟 秒 送入P0口
}
全部0条评论
快来发表一下你的评论吧 !