DS3231作为一个走时精准的RTC芯片,内部带有温度补偿电路,此例将读取其中11H和12H寄存器,提取测得的温度值并传送到串口输出。
类似程序网上非常之多,不再赘述,在此重新提说几处需要注意的地方。
1.根据DS3231的芯片手册,其温度传感器的精度为±3℃,毕竟不是专用的温度传感器,在使用中可以作为一个参考,且仅此而已。
2.根据DS3231的芯片手册,其温度分辨率为±0.25℃,所以其小数部分读出的值只能是.00、.25、.50、.75这四种,如果读出的值不是这四种,则数据处理有误。
3.本实验使用一个float型数据直接接收了转换的温度值,没有对补码的符号位进行判断等。
注明:本程序没有使用CONV位进行强制转换,但是实际上温度值的刷新速度还是很令人满意(用手按住芯片,温度值更改速度很快,下面的测试图片是恒温下检测的,故无变化)。
测试程序:
#include
#include"stdio.h"
#include
//位定义
sbit DS3231_SDA=P3^3;
sbit DS3231_SCL=P3^2;
//运行数组
unsigned char DS3231_Time_Buffer[7]={0x00,0x48,0x11,0x02,0x12,0x02,0x19};
unsigned char temp[2]={0,0};
char buf[20]={0};
//运行标志位
bit busy=0;
//运行变量
float v;
/*##############################################################################
编写/测试:凌净清河
日期:2019年2月12日
测试平台:IAP15W4K58S4
鸣谢:DS3231部分驱动函数借用了51黑论坛上某位的程序,但是时间太久忘记是谁的了。
并未修改原作者的写法,如果原作者认出,鄙人在此表示感谢,或可联系我提名。
##############################################################################*/
/*###################以下为给DS3231定义的IIC通信函数################*/
void DS3231_Delay()//使用空操作进行短暂的延时
{
_nop_();
_nop_();
_nop_();
_nop_();
}
void DS3231_IIC_Start()//IIC总线的开始信号
{
DS3231_SCL=1;
DS3231_SDA=1;
DS3231_Delay();
DS3231_SDA=0;
DS3231_Delay();
DS3231_SCL=0;
}
void DS3231_IIC_Stop()//IIC总线的停止信号
{
DS3231_SCL=0;
DS3231_SDA=0;
DS3231_Delay();
DS3231_SCL=1;
DS3231_Delay();
DS3231_SDA=1;
DS3231_Delay();
}
bit DS3231_IIC_Send_Byte(unsigned char dat)//写操作
{
unsigned char mask;//定义一个掩码用于进行按位发送数据的操作
bit ack;
for(mask=0x80;mask!=0;mask>>=1)
{
if((mask&dat)==0)
DS3231_SDA=0;
else
DS3231_SDA=1;
DS3231_Delay();
DS3231_SCL=1;
DS3231_Delay();
DS3231_SCL=0;
}
DS3231_SDA=1;
DS3231_Delay();
DS3231_SCL=1;
ack=DS3231_SDA;
DS3231_Delay();
DS3231_SCL=0;
return (~ack);
}
unsigned char DS3231_IIC_Read_Byte_NAK()//读操作+非应答
{
unsigned char mask;//定义一个用于累加的位存储临时变量
unsigned char dat;
DS3231_SDA=1;
for(mask=0x80;mask!=0;mask>>=1)
{
DS3231_Delay();
DS3231_SCL=1;
if(DS3231_SDA==0)
dat&=~mask;
else
dat|=mask;
DS3231_Delay();
DS3231_SCL=0;
}
DS3231_SDA=1;
DS3231_Delay();
DS3231_SCL=1;
DS3231_Delay();
DS3231_SCL=0;
return dat;
}
unsigned char DS3231_IIC_Read_Byte_ACK()//读操作+应答
{
unsigned char mask;//定义一个用于累加的位存储临时变量
unsigned char dat;
DS3231_SDA=1;
for(mask=0x80;mask!=0;mask>>=1)
{
DS3231_Delay();
DS3231_SCL=1;
if(DS3231_SDA==0)
dat&=~mask;
else
dat|=mask;
DS3231_Delay();
DS3231_SCL=0;
}
DS3231_SDA=0;
DS3231_Delay();
DS3231_SCL=1;
DS3231_Delay();
DS3231_SCL=0;
return dat;
}
/*#################以下为给DS3231封装的寄存器通信函数###############*/
void DS3231_Read_Registers(unsigned char *buf,unsigned char addr,unsigned char len)//读EEPROM中多个字节
{
do{
DS3231_IIC_Start();
if(DS3231_IIC_Send_Byte(0xD0))
{
break;
}
DS3231_IIC_Stop();
}while(1);
DS3231_IIC_Send_Byte(addr);
DS3231_IIC_Start();
DS3231_IIC_Send_Byte((0xD0)|0x01);//寻址,读操作
while(len>1)
{
*buf++=DS3231_IIC_Read_Byte_ACK();
len--;
}
*buf=DS3231_IIC_Read_Byte_NAK();//读一个字节
DS3231_IIC_Stop();
}
void DS3231_Write_Registers(unsigned char *buf,unsigned char addr,unsigned char len)//写寄存器,传入待写入数组
{
while(len>0)
{
do{
DS3231_IIC_Start();
if(DS3231_IIC_Send_Byte(0xD0))
{
break;
}
DS3231_IIC_Stop();
}while(1);
DS3231_IIC_Send_Byte(addr);
while(len>0)
{
DS3231_IIC_Send_Byte(*buf++);
len--;
addr++;
if((addr&0x07)==0)
{
break;
}
}
DS3231_IIC_Stop();
}
}
void SendData(unsigned char dat)//串口1发送一个字节数据
{
while(busy);
busy=1;
SBUF=dat;
}
void SendString(char *p)//串口发送一个字符串
{
while(*p!='')
{
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』