ds3231时钟模块测试程序

ds3231是一款高精度的时钟芯片,具有集成的温度补偿晶体振荡器和一个32.768khz的晶体,可为器件提供长期精确度;包含备用电源输入端,断开主电源后仍可保持精确的计时;寄存器内部能保存时间和闹钟设置等信息;提供两个可编程的日历闹钟和一个可编程方波输出,支持i2c总线接口。
ds3231的特性如下: 基本计时功能,提供秒、分、时、星期、日、月、年信息,并提供有效期到2100年的闰年补偿
两个日历闹钟功能
可编程方波输出
数字温度传感器输出:±3℃
老化修正寄存器功能
备用电池输入功能
时钟精度为:±2ppm(0℃~40℃)、±3.5ppm(-40℃~+85℃)
低功耗
ds3231测试程序,采用数码管显示 #include 《reg51.h》
#include 《intrins.h》
#define uchar unsigned char
#define uint unsigned int
sbit sda=p3^6; //模拟i2c数据传送位sda
sbit scl=p3^7; //模拟i2c时钟控制位scl
sbit int=p3^2;
sbit reset=p3^3;
sbit led0=p1^0;
sbit led1=p1^1;
sbit led2=p1^2;
sbit led3=p1^3;
sbit led4=p1^4;
sbit led5=p1^5;
sbit led6=p1^6;
sbit led7=p1^7;
bit ack; //应答标志位
#define ds3231_writeaddress 0xd0 //器件写地址
#define ds3231_readaddress 0xd1 //器件读地址
#define ds3231_second 0x00 //秒
#define ds3231_minute 0x01 //分
#define ds3231_hour 0x02 //时
#define ds3231_week 0x03 //星期
#define ds3231_day 0x04 //日
#define ds3231_month 0x05 //月
#define ds3231_year 0x06 //年
//闹铃1
#define ds3231_salarm1econd 0x07 //秒
#define ds3231_alarm1minute 0x08 //分
#define ds3231_alarm1hour 0x09 //时
#define ds3231_alarm1week 0x0a //星期/日
//闹铃2
#define ds3231_alarm2minute 0x0b //分
#define ds3231_alarm2hour 0x0c //时
#define ds3231_alarm2week 0x0d //星期/日
#define ds3231_control 0x0e //控制寄存器
#define ds3231_status 0x0f //状态寄存器
#define bsy 2 //忙
#define osf 7 //振荡器停止标志
#define ds3231_xtal 0x10 //晶体老化寄存器
#define ds3231_temperatureh 0x11 //温度寄存器高字节(8位)
#define ds3231_temperaturel 0x12 //温度寄存器低字节(高2位)
uchar code dis_code[11]={0xc0,0xf9,0xa4,0xb0, // 0,1,2,3
0x99,0x92,0x82,0xf8,0x80,0x90, 0xff}; // 4,5,6,7,8,9,off
uchar data dis_buf[8];
uchar data dis_index;
uchar data dis_digit;
uchar bcd2hex(uchar val) //bcd转换为byte
{
uchar temp;
temp=val&0x0f;
val》》=4;
val&=0x0f;
val*=10;
temp+=val;
return temp;
}
uchar hex2bcd(uchar val) //b码转换为bcd码
{
uchar i,j,k;
i=val/10;
j=val;
k=j+(i《《4);
return k;
}
void delayus(uint us)
{
while (us--);
}
void start_i2c()
{
sda=1; //发送起始条件的数据信号
delayus(1);
scl=1;
delayus(5); //起始条件建立时间大于4.7us,延时
sda=0; //发送起始信号
delayus(5); // 起始条件锁定时间大于4μs
scl=0; //钳住i2c总线,准备发送或接收数据
delayus(2);
}
void stop_i2c()
{
sda=0; //发送结束条件的数据信号
delayus(1); //发送结束条件的时钟信号
scl=1; //结束条件建立时间大于4us
delayus(5);
sda=1; //发送i2c总线结束信号
delayus(4);
}
void sendbyte(uchar c)
{
uchar bitcnt;
for(bitcnt=0;bitcnt《8;bitcnt++) //要传送的数据长度为8位
{
if((c《《bitcnt)&0x80)
sda=1; //判断发送位
else
sda=0;
delayus(1);
scl=1; //置时钟线为高,通知被控器开始接收数据位
delayus(5); //保证时钟高电平周期大于4μs
scl=0;
}
delayus(2);
sda=1; //8位发送完后释放数据线,准备接收应答位
delayus(2);
scl=1;
delayus(3);
if(sda==1)
ack=0;
else
ack=1; //判断是否接收到应答信号
scl=0;
delayus(2);
}
uchar rcvbyte()
{
uchar retc;
uchar bitcnt;
retc=0;
sda=1; //置数据线为输入方式
for(bitcnt=0;bitcnt《8;bitcnt++)
{
delayus(1);
scl=0; //置时钟线为低,准备接收数据位
delayus(5); //时钟低电平周期大于4.7μs
scl=1; //置时钟线为高使数据线上数据有效
delayus(3);
retc=retc《《1;
if(sda==1)
retc=retc+1; //读数据位,接收的数据位放入retc中
delayus(2);
}
scl=0;
delayus(2);
return(retc);
}
void ack_i2c(bit a)
{
if(a==0)
sda=0; //在此发出应答或非应答信号
else
sda=1;
delayus(3);
scl=1;
delayus(5); //时钟低电平周期大于4μs
scl=0; //清时钟线,钳住i2c总线以便继续接收
delayus(2);
}
uchar write_byte(uchar addr, uchar write_data)
{
start_i2c();
sendbyte(ds3231_writeaddress);
if (ack == 0)
return 0;
sendbyte(addr);
if (ack == 0)
return 0;
sendbyte(write_data);
if (ack == 0)
return 0;
stop_i2c();
delayus(10);
return 1;
}
uchar read_current()
{
uchar read_data;
start_i2c();
sendbyte(ds3231_readaddress);
if(ack==0)
return(0);
read_data = rcvbyte();
ack_i2c(1);
stop_i2c();
return read_data;
}
uchar read_random(uchar random_addr)
{
start_i2c();
sendbyte(ds3231_writeaddress);
if(ack==0)
return(0);
sendbyte(random_addr);
if(ack==0)
return(0);
return(read_current());
}
void modifytime(uchar yea,uchar mon,uchar da,uchar hou,uchar min,uchar sec)
{
uchar temp=0;
temp=hex2bcd(yea);
write_byte(ds3231_year,temp); //修改年
temp=hex2bcd(mon);
write_byte(ds3231_month,temp); //修改月
temp=hex2bcd(da);
write_byte(ds3231_day,temp); //修改日
temp=hex2bcd(hou);
write_byte(ds3231_hour,temp); //修改时
temp=hex2bcd(min);
write_byte(ds3231_minute,temp); //修改分
temp=hex2bcd(sec);
write_byte(ds3231_second,temp); //修改秒
}
void timedisplay(uchar dhour,uchar dmin,uchar dsec)
{
dis_buf[7]=dis_code[dhour / 10]; // 时十位
dis_buf[6]=dis_code[dhour % 10]; // 时个位
dis_buf[4]=dis_code[dmin / 10]; // 分十位
dis_buf[3]=dis_code[dmin % 10]; // 分个位
dis_buf[1]=dis_code[dsec / 10]; // 秒十位
dis_buf[0]=dis_code[dsec % 10]; // 秒个位
dis_buf[2]=0xbf; // 显示“-”
dis_buf[5]=0xbf;
}
void datedisplay(uchar dyear,uchar dmonth,uchar dday)
{
dis_buf[7]=dis_code[dyear / 10]; // 年十位
dis_buf[6]=dis_code[dyear % 10]; // 年个位
dis_buf[4]=dis_code[dmonth / 10]; // 月十位
dis_buf[3]=dis_code[dmonth % 10]; // 月个位
dis_buf[1]=dis_code[dday / 10]; // 天十位
dis_buf[0]=dis_code[dday % 10]; // 天个位
dis_buf[2]=0xbf; // 显示“-”
dis_buf[5]=0xbf;
}
void get_show_time(void)
{
uchar htemp1,htemp2,mtemp1,mtemp2,stemp1,stemp2;
htemp1=read_random(ds3231_hour); //时 24小时制
htemp1&=0x3f;
htemp2=bcd2hex(htemp1);
mtemp1=read_random(ds3231_minute); //分
mtemp2=bcd2hex(mtemp1);
stemp1=read_random(ds3231_second); //秒
stemp2=bcd2hex(stemp1);
timedisplay(htemp2,mtemp2,stemp2);
}
void get_show_date(void)
{
uchar ytemp1,ytemp2,mtemp1,mtemp2,dtemp1,dtemp2;
ytemp1=read_random(ds3231_year); //年
ytemp2=bcd2hex(ytemp1);
mtemp1=read_random(ds3231_month); //月
mtemp2=bcd2hex(mtemp1);
dtemp1=read_random(ds3231_day); //日
dtemp2=bcd2hex(dtemp1);
datedisplay(ytemp2,mtemp2,dtemp2);
}
void get_show_temperature(void)
{
uchar ttemp1,ttemp2,ttemp3,ttemp4;
ttemp1=read_random(ds3231_temperatureh); //温度 高字节
ttemp2=bcd2hex(ttemp1);
ttemp3=read_random(ds3231_temperaturel); //温度低字节
ttemp4=bcd2hex(ttemp3);
datedisplay(0,ttemp2,ttemp4);
}
void timer0() interrupt 1
{
th0=0xfc;
tl0=0x17;
p2=0xff; // 先关闭所有数码管
p0=dis_buf[dis_index]; // 显示代码传送到p0口
p2=dis_digit;
if (dis_digit & 0x80)
dis_digit=(dis_digit 《《 1) | 0x1;
else
dis_digit=(dis_digit 《《 1);
dis_index++;
dis_index&=0x07; // 8个数码管全部扫描完一遍之后,再回到第一个开始下一次扫描
}
void main()
{
uint ii = 0;
reset=0x1; //ds3231复位操作,正常操作下不需要每次都复位
delayus(5000);
led0=0;
led1=0;
led2=0;
led3=0;
led4=0;
p0=0xff;
p2=0xff;
dis_digit=0xfe;
dis_index=0;
timedisplay(12, 5, 18);
tmod=0x11; // 定时器0, 1工作模式1, 16位定时方式
th0=0xfc;
tl0=0x17;
tcon=0x01;
ie=0x82; // 使能timer0,1 中断
tr0=1;
if (write_byte(ds3231_control, 0x1c) == 0)
led0=1;
if (write_byte(ds3231_status, 0x00) == 0)
led1=1;
modifytime(10,6,13,15,30,00); //初始化时钟,2010/6/13,15/30/00
//小时采用24小时制
while(1)
{
//get_show_date(); //显示日期
//get_show_temperature(); //显示温度
get_show_time(); //显示时间
delayus(50000);
}
}
ds3231芯片主要功能测试实现的介绍 ds3231电路的测试板是根据其典型应用电路原理图进行设计的,其工作信息通过测试板与测试机进行交互,达到对内部寄存器访问、端口输出信息检测的目的。
下图所示是ds3231的典型应用原理图:
根据以上原理图,测试板的原理示意图如下:
在测试板上的外围器件要求以及端口处理要求如下: vcc:主电源的引脚,需要使用0.1uf至1.0uf电容进行去耦。当在3.3v电源电压条件下测试时用dps2供电,dps1断开;当在5.5v电源电压条件下进行测试时用dps1;
32khz:此漏极开路输出引脚要求接上拉电阻,使能状态下,输出可工作在任意电源下。在测试板上同时引到了测试机通道,上拉电阻选择1k;
int/sqw:低电平有效中断或方波输出,该漏极开路输出引脚需要接上拉电阻,此管脚上拉接10k电阻;
vbat:备用电源输入,需要使用0.1uf至1.0uf电容进行去耦,当此电源不用时,通过测试机内部继电器切断此电源;
sda:上拉电阻选择1k电阻。
基本计时功能以及备用电池供电计时功能的测试实现 ds3231运行于12小时或者24小时模式,小时寄存器的第六位定义为12小时或者24小时的选择位,该位为高时,选择12小时模式,在12小时模式下,第五为为am/pm指示位,逻辑高时为pm。
计时的功能是对内部的寄存器的时间信息进行测试,包括秒、分、时、星期、日期、月、年,对这种全面时间信息的测试,通常要选取一个覆盖信息全的时间,我们的测试实现是通过i2c向时间寄存器中写入数据2012年12月31日星期一23点59分59秒,在经过1s的时间后,读取内部寄存器的信息,应该为2013年01月01日星期二00点00分00秒,在j750ex测试机上通过对比测试向量,判断功能的正确与否。
该电路的备用电源输入管脚vbat,能够为器件提供备用电,当断掉主电源供电后由备用电池供电,电路的实时时钟功能不受影响,继续正常工作。按照条件dps2加电3.3v,dps1断开,dps3加电3v施加测试电源电压,向时间寄存器00h写入数据50h,按照dps2断开,dps1断开,dps3加电3v的条件施加电源电压,供电等待1s,1s后按照最初的电压条件供电,读取内部寄存器地址00h的数据,若读取数据为51h,则在vcc断开的条件下,vbat可以继续供电使芯片持续工作。
日历闹钟功能的测试实现 当rtc寄存器值与闹钟寄存器的设定值相匹配时,相应的闹钟标志位a1f或a2f置为逻辑1,如果相应的闹钟中断使能位a1ie或a2ie也置为逻辑1,并且intch位置为逻辑1,闹钟条件将会触发int/sqw信号,rtc在时间和日期寄存器每秒更新时都会检测匹配情况。
通过测试向量打开日历闹钟功能并设置响应时间,如果时间到达设定的闹钟响应时刻,会将闹钟标志位自动置位,可以通过i2c接口访问该标志位。通过对比标志位是否与向量一致。
数字传感器输出精度的测试实现 温度寄存器地址为11h和12h,ds3231需要读取的3个温度点为25℃、85℃、-40℃,测试时的温度是热流罩提供准确恒定的温度环境,通过i2c读取寄存器地址11h和12h中各3个温度点的数据。数字温度传感器输出的精度为±3℃,验证在相对恒温的热流罩温度环境中,读取值与测试向量是否相符。

罗德与施瓦茨一站式测试解决方案,满足中国5G测试市场的应用需求
物联网的主要体现价值在哪
科裕智能科技智能感应锁930-6-D简介
跑马灯和流水灯的区别是什么?单片机如何控制LED灯?
智慧医疗是如何带给我们便利的
ds3231时钟模块测试程序
意法半导体碳化硅产品2023年营收同比增长超60%
聚焦晶心科技新世代微处理器指令集架构AndeStar™ V5
智能电视还有哪些方面做得不够好?
德中LTCC/HTCC激光精密打孔设备
用89C51单片机控制红外线通信接口电路设计
自制污水井抽水装置的工作原理
N相和分相混合电感电容器开关的应用
Nexperia推出首款采用SMD铜夹片LFPAK88封装的热插拔专用MOSFET(ASFET),管脚尺寸缩小60%
台积电2018年高端机销量退步 加密货币或成公司业务增长主力
投影仪挑选成难题?小白科技分享五大高性价比投影仪推荐
传感器与AT89S52单片机的接口电路设计:测量模块电路
算力网络发展的三个阶段分别是
STM32 I2C总线通信与SPI总线通信专题讲解
一加5什么时候上市?一加5最新消息:捏死小米6命门,一加5现货,不玩抢购!