1
控制/MCU
介绍了美国Dallas公司推出的低功耗时钟器件DS3231的结构和工作原理,DS3231能对年、月、日、时、分、秒计时,且具有温度补偿、闰年补偿等多种功能。给出了AVR单片机ATmega8与DS3231的软、硬件接口设计。
由单片机构成的测控系统或智能显示屏经常需要用到实时日历或时钟信号。为节省CPU资源,本文节绍了串行时钟器件DS3231的应用及其与AVR单片机ATmega8的接口,该系统具有抗干扰能力强,计时准确且不随季节变化产生误差的特点。
如图1所示,DS3231的主要组成部分有8个模块,划分为4个功能组:TCXO、电源控制、按钮复位和RTC。
DS3231是低成本、高精度I2C实时时钟(RTC)器件,具有集成的温度补偿晶体振荡器(TCXO)。该器件包含电池输入端,断开主电源时仍可保持精确计时。集成的晶体振荡器可提高器件的长期精确度。DS3231的寄存器能保存秒、分、时、星期、日期、月、年和闹钟设置等信息。少于31天的月份,可自动调整月末日期,包括闰年补偿。DS3231提供两个可编程日历闹钟和一路可编程方波输出。地址与数据通过I2C双向串行总线传输。
可以通过读取适当的寄存器字节获得时钟和日历信息。通过写入适当的寄存器字节设定或者初始化时钟和日历数据。时钟和日历寄存器的内容采用二-十进制编码(BCD)格式。DS3231运行于12小时或者24小时模式。小时寄存器的第6位定义为12或24小时模式选择位。该位为高时,选择12小时模式。在12小时模式下,第5位为AM/PM指示位,逻辑高时为PM。
TCXO包括温度传感器、振荡器和控制逻辑。控制器读取片上温度传感器输出,使用查表法确定所需的电容,加上AGE寄存器的老化修正。然后设置电容选择寄存器。仅在温度变化或者用户启动的温度转换完成时,才加载包括AGE寄存器变化的新值。VCC初次上电时就会读取温度值,然后每隔64 s读取一次。
电源控制功能由温度补偿电压基准(VPF)和监视VCC电平的比较器电路提供。当VCC高于VPF时,DS3231由VCC供电,当VCC低于VPF但高于VBAT时,DS3231由VCC供电;当VCC低于VPF并低于VBAT时,DS3231由VBAT供电。为保护电池,VBAT首次加到器件时振荡器并不启动,除非加载VCC,或者向器件写入一个有效的I2C地址。典型的振荡器启动时间在1 s以内。在VCC加电后或者有效的I2C地址写入后大约2 s,器件会测量一次温度,并使用计算的修正值校准振荡器。一旦振荡器运行,只要电源(VCC或者VBAT)有效就会一直保持工作状态。器件每隔64 s进行一次温度测量并校准振荡器频率。
DS3231具有连接至RST输出引脚的按钮开关功能。若DS3231不在复位周期,会持续监视RST信号的下降沿。如果检测到一个边沿转换,DS3231通过拉低RST完成开关去抖。内部定时器定时结束后,DS3231继续监视RST信号。如果信号依旧保持低电平,DS3231持续监视信号线以检测上升沿。一旦检测到按钮释放,DS3231强制RST为低电平并保持tRST。RST还可用于指示电源故障报警情况。当VCC低于VPF时,产生内部电源故障报警信号,并强制拉低RST引脚。当VCC返回至超过VPF电平时。RST保持低电平大约250 ms(tREC),使供电电源达到稳定。如果在VCC加载时,振荡器不工作,将跳过tREC,RST立刻变为高电平。
DS3231包含2个定时/日期闹钟。闹钟1可通过写入寄存器07h~0Ah设定。闹钟2可通过写入寄存器0Bh~0Dh设定。可对闹钟进行编程(通过控制寄存器的闹钟使能位和INTCN位),从而在闹钟匹配条件下触发INT/SQW输出。每个定时/日期闹钟寄存器的第7位是屏蔽位。当每个闹钟的屏蔽位均为逻辑0时,只有当计时寄存器中的值与存储于定时/日期闹钟寄存器中的对应值相匹配时才会告警。闹钟也可以编程为每秒、分、时、星期或日期重复告警。当RTC寄存器值与闹钟寄存器的设定值相匹配时,相应的闹钟标志位A1F或A2F置为逻辑1。如果对应的闹钟中断使能位A1IE或A2IE也置为逻辑1,并且INTCN位置为逻辑1,闹钟条件将会触发INT/SQW信号。RTC在时间和日期寄存器每秒更新时都会检测匹配情况。
DS3231通过I2C总线的双向数据线SDA和时钟线SCL与外界进行数据交换。DS3231在I2C总线上作为从器件。I2C主机通过执行START命令并且在验证器件地址后才可以访问DS3231,然后DS3231的寄存器可以被访问直到执行一个STOP命令为止。DS3231有两种操作方式:写操作和读操作。DS3231的地址固定为1101 000。
Atmega系列单片机片内集成2线制串行接口模块,Atmel称其为TWI接口。事实上,TWI与Philips的I2C总线是一回事。AVR硬件实现的TWI接口是面向字节和基于中断的,相对软件模拟I2C总线有更好的实时性和代码效率,引脚输入部分还具有毛刺抑制单元,可去除高频干扰。图3是DS3231与AVR单片机ATmega8的硬件接口电路原理图。
软件设计中,首先要对AVR单片机ATmega8与实时钟器件DS3231进行初始化,给DS3231准确的日期和时间。不论主控模式还是被控模式,都应当将TWI控制寄存器TWCR的TWEN位置为1,从而使能TWI模块。TWEN位被置位后,I/O引脚PC5和PC4转换成SCL和SDA,对TWI控制寄存器TWCR的操作可在总线上产生START和STOP信号。对TWI模块的操作均为寄存器的读写操作,Avr-libc没有提供专门的API。
#define SLA 0xD0
/*I2C总线主机模式错误处理*/
void error(unsigned char type) {
switch (type & 0xF8) {
case 0x20: /*址址写失败*/
/*stop 停止*/
TWCR = (1 《《 TWINT) | (1 《《 TWEN) | (1 《《 TWSTO);
break;
case 0x30: /*数据写失败*/
/*stop 停止*/
TWCR = (1 《《 TWINT) | (1 《《 TWEN) | (1 《《 TWSTO);
break;
case 0x38: /*仲裁失败*/
TWCR=(1《《TWINT)|(1《《TWEN)|(1《《TWEA);
break;
case 0x48: /*址址读失败*/
/*stop 停止*/
TWCR = (1 《《 TWINT) | (1 《《 TWEN) | (1 《《 TWSTO);
break;
}
}
/*I2C总线多字节写入
*n为需写入字节数
*addr为DS3231的寄存器地址
*数组dd中为需写入数据。
*注意,数组dd中的数据必须是BCD编码格式
*/
unsigned char twi_ds_write(unsigned char addr,
unsigned char dd[],int n) {
int i;
TWBR = 2;
/*start 启动*/
TWCR = (1 《《 TWINT)| (1 《《 TWSTA)| (1 《《 TWEN);
while (!(TWCR & (1 《《 TWINT)));
if ((TWSR & 0xF8)!= 0x08) {
error(TWSR);
return 0;
}
/*SLA_W芯片地址*/
TWDR = SLA;
TWCR = (1 《《 TWINT) | (1 《《 TWEN);
while (!(TWCR & (1 《《 TWINT)));
if ((TWSR & 0xF8) != 0x18) {
error(TWSR);
return 0;
}
/*addr 操作地址*/
TWDR = addr;
TWCR = (1 《《 TWINT) | (1 《《 TWEN);
while (!(TWCR & (1 《《 TWINT)));
if ((TWSR & 0xF8) != 0x28) {
error(TWSR);
return 0;
}
/*dd 写入second,minute等数据*/
for(i=0;i《n;i++)
{
TWDR = dd[i];
TWCR = (1 《《 TWINT)| (1 《《 TWEN);
while (!(TWCR & (1 《《 TWINT)));
if ((TWSR & 0xF8)!= 0x28) {
error(TWSR);
return 0;
}
}
/*stop 停止*/
TWCR = (1 《《 TWINT) | (1《《TWEA)|(1 《《 TWEN) | (1 《《
TWSTO);
return 1;
}
/*I2C总线多字节读取
*addr为DS3231寄存器起始地址,数组dd存放读取的n字节数据
*/
unsigned char twi_ds_read(unsigned char addr, unsigned char dd[],int
n) {
int i;
TWBR = 2;
/*start 启动*/
TWCR=(1《《TWINT)|(1《《TWSTA)|(1《《TWEN);
while(!(TWCR&(1《《TWINT)));
if ((TWSR & 0xF8) != 0x08) {
error(TWSR);
return 0;
}
/*SLA_W芯片地址*/
TWDR = SLA;
TWCR = (1 《《 TWINT) | (1 《《 TWEN);
while(!(TW R & ( 《《 TWINT)));
if((TWSR & xF ) != x ) {
error(TWSR);
return 0;
}
/*addr 操作地址*/
TWDR = addr;
TWCR = (1 《《 TWINT)| (1 《《 TWEN);
while (!(TWCR & (1 《《 TWINT)));
if ((TWSR & 0xF8)!= 0x28) {
error(TWSR);
return 0;
}
/*start 启动*/
TWCR = (1 《《 TWINT)| (1 《《 TWSTA)| (1 《《 TWEN);
while (!(TWCR & (1 《《 TWINT)));
if ((TWSR & 0xF8)!= 0x10) {
error(TWSR);
return 0;
}
/*SLA_R 芯片地址*/
TWDR = SLA+1;
TWCR = (1 《《 TWINT)| (1 《《 TWEN);
while (!(TWCR & (1 《《 TWINT)));
if ((TWSR & 0xF8)!= 0x40) {
error(TWSR);
return 0;
}
/*读取前n-1个数据*/
for(i=0;i《n-1;i++)
{
TWCR = (1 《《 TWINT)|(1《《TWEA)|(1 《《 TWEN);
while (!(TWCR & (1 《《 TWINT)));
if ((TWSR & 0xF8) != 0x50) {
error(TWSR);
return 0;
}
dd[i] = TWDR;
}
/*读取第n个数据*/
TWCR = (1 《《 TWINT)| (1 《《 TWEN);
while (!(TWCR & (1 《《 TWINT)));
if ((TWSR & 0xF8)!= 0x58) {
error(TWSR);
return 0;
}
dd[n-1] = TWDR;
/*stop 停止*/
TWCR = (1 《《 TWINT)|(1《《TWEA) | (1 《《 TWSTO) | (1 《《
TWEN);
return 1;
}
选用实时时钟器件DS3 3 和 VR单片机 T 设计了一个日历时钟系统,该系统体积小,通用性强。DS3231具有集成的温度补偿晶体振荡器(TCXO),计时准确且不随季节的变化而产生误差。该系统适用于智能显示屏以及实时测控系统。
全部0条评论
快来发表一下你的评论吧 !