📄 ds3231.c
字号:
#include "DS3231.h"
#include "system.h"
//-------------------------------------------------------------------
// DS3231特性
//
// 1.0℃~+40℃温度范围内,时钟精度为±2ppm;
// 2.-40℃~+85℃温度范围内,时钟精度为±3.5ppm;
// 3.为连续计时提供备用电池输入;
// 4.工作温度范围:
// 商用级:0℃~+70℃
// 工业级:-40℃~+85℃
// 5.低功耗;
// 6.实时时钟提供秒\分\时\星期\日\月\年信息,并提供有效期至2100年的闰年补偿;
// 7.2个日历闹钟;
// 8.可编程方波输出:1Hz,1024Hz,4096Hz,8192Hz;
// 9.快速(400kHz)I2C接口;
// 10.3.3V工作电压;
// 11.数字温度传感器温度输出:分辨率0.25℃,精度为±3℃;
// 12.老化修正寄存器;
// 13.RST输出,手动复位去抖输入;
// 14.通过保险商试验机构(UL)认证.
//--------------------------------------------------------------------
//器件地址
#define DS3231ADDR 0xD0
//读写操作位
#define CMD_READ 0x01
//#define CMD_WRITE 0x00
//时钟 命令
#define CMD_SECOND 0x00 //秒
#define CMD_MINUTE 0x01 //分
#define CMD_HOUR 0x02 //时
#define CMD_WEEK 0x03 //星期
#define CMD_DAY 0x04 //日
#define CMD_MONTH 0x05 //月
#define CMD_YEAR 0x06 //年
//闹铃1
#define CMD_SALARM1ECOND 0x07 //秒
#define CMD_ALARM1MINUTE 0x08 //分
#define CMD_ALARM1HOUR 0x09 //时
#define CMD_ALARM1WEEK 0x0A //星期/日
//闹铃2
#define CMD_ALARM2MINUTE 0x0b //分
#define CMD_ALARM2HOUR 0x0c //时
#define CMD_ALARM2WEEK 0x0d //星期/日#define CMD_CONTROL 0x0e //控制寄存器
#define CMD_STATUS 0x0f //状态寄存器
#define BSY 2 //忙
#define OSF 7 //振荡器停止标志
#define CMD_XTAL 0x10 //晶体老化寄存器
#define CMD_TEMPERATUREH 0x11 //温度寄存器高字节(8位)
#define CMD_TEMPERATUREL 0x12 //温度寄存器低字节(高2位)
#define TWIStop() TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO) //发送stop
#define TWIStart() TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN) //发送start
#define CheckTWINT() while(!(TWCR&(1<<TWINT)))
unsigned char RealTimeDate[7]={ //此处的排序是为了方便连续操作寄存器
0x08, //2008年
0x12, //12月
0x28, //26日
0x07, //星期五
0x23, //时 24小时制0~23
0x54, //分 0~59
0x50, //50秒 注意:这里把CH置0了 bit7位(CH)需要置0,震荡器才能起振
};
unsigned char ReadTemperatureflag=0;
unsigned char temperature=0;
unsigned char NowTemperature[]="现在温度是xx℃"; //当前温度
unsigned char NowDATE[]="20xx年xx月xx日xx时xx分xx秒 星期xx"; //当前时间
unsigned char WEEK[]="错一二三四五六日"; //注意:汉字要占用2个字节的空间
void BCDtoASCII(unsigned char cBCD,unsigned char *pstr)//压缩BCD码转换成ASCII码
{
unsigned char temp=cBCD>>4;
*pstr++=temp+0x30;
temp=cBCD&0x0F;
*pstr=temp+0x30;
}
void decodeWEEK(unsigned char week_,unsigned char *pstr) //BCD码0~7转换成汉字'一'~'日'
{
unsigned char i;
i=week_;
i&=0x07;
i=i<<1;
*pstr++=WEEK[i++];
*pstr=WEEK[i];
}
unsigned char BcdToBin(unsigned char val) //将BCD码转换为10进制数
{
return (val>>4)*10+(val&0x0f);
}
unsigned char BinToBcd(unsigned char val) //将10进制数转换为BCD码
{
return ((val/10)*16+val%10);
}
void DS3231Init(void)
//实际应用中注意每次查询一下状态寄存器.bit7:振荡器停止标志(OSF)位,如果为1,需要重新初始化时间,并清零.
{
TWBR=11;
TWSR=0;
//控制寄存器.bit7:使能振荡器(EOSC#) bit6:电池备份的方波使能(BBSQW)
//bit5:转换温度(CONV) bit4和bit3:频率选择(RES2和R)
//bit2:中断控制(INTCN) bit1:闹钟2中断使能(A2IE) bit0:闹钟1中断使能(A1IE)
DS3231TWIWrite(CMD_CONTROL,0x1c); //00011100
//状态寄存器.bit7:振荡器停止标志(OSF) bit6~bit4:空 bit3:使能32KHz输出(EN32KHz)
//bit2:忙(BSY) bit1:闹钟2标志(A2F) bit0:闹钟1标志(A1F)
DS3231TWIWrite(CMD_STATUS,0x00); //000010
//DS3231WriteTime();
}
void ERROR(void)
{
systemerror=1;
TWIStop();
}
unsigned char DS3231TWIRead(unsigned int addr) //从设备发送模式 DS3231读模式
{
unsigned char data; //读取数值缓存
TWIStart(); //发开始信号
CheckTWINT(); //等待结束
if((TWSR&0xF8)!=0x08)ERROR();
TWDR=DS3231ADDR; //TWDR=DS3231ADDR+CMD_WRITE;//发送SLA设备地址+写命令
TWCR=(1<<TWINT)|(1<<TWEN);
CheckTWINT(); //等待结束
if((TWSR&0xF8)!=0x18)ERROR();
TWDR=addr; //发送读取地址
TWCR=(1<<TWINT)|(1<<TWEN);
CheckTWINT();
if((TWSR&0xF8)!=0x28)ERROR();
TWIStart(); //发开始信号
CheckTWINT(); //等待结束
if((TWSR & 0xF8)!=0x10)ERROR();
TWDR=DS3231ADDR+CMD_READ; //发送SLA设备地址+读命令
TWCR=(1<<TWINT)|(1<<TWEN);
CheckTWINT();
if((TWSR&0xF8)!=0x40)ERROR();
TWCR=0x84; //接收8位数据,发送nACK
CheckTWINT();
if((TWSR&0xF8)!=0x58)ERROR();
data=TWDR;
TWIStop(); //发送STOP 信号
_delay_ms(5);
return data;
}
void DS3231TWIWrite(unsigned int addr,unsigned char data) //从设备接收模式 DS3231写模式
{
TWIStart(); //发开始信号
CheckTWINT(); //等待结束
if((TWSR&0xF8)!=0x08)ERROR();
TWDR=DS3231ADDR; //TWDR=DS3231ADDR+CMD_WRITE;//发送SLA设备地址+写命令
TWCR=(1<<TWINT)|(1<<TWEN);
CheckTWINT(); //等待结束
if((TWSR&0xF8)!=0x18)ERROR();
TWDR=addr; //发送读取地址
TWCR=(1<<TWINT)|(1<<TWEN);
CheckTWINT();
if((TWSR&0xF8)!=0x28)ERROR();
TWDR=data;
TWCR=(1<<TWINT)|(1<<TWEN);
CheckTWINT();
if((TWSR&0xF8)!=0x28)ERROR();
TWIStop(); //发送STOP 信号
_delay_ms(5);
}
void DS3231ReadTime(void) //此处需要连续读写
{
unsigned char i;
unsigned char command=CMD_YEAR;
for(i=0;i<7;i++)CURDATE[i]=DS3231TWIRead(command--); //依次读取:年\月\日\周\时\分\秒
}
void DS3231WriteTime(void) //此处需要连续读写
{
unsigned char i;
unsigned char command=CMD_YEAR;
for(i=0;i<7;i++)DS3231TWIWrite(command--,RealTimeDate[i]);//依次写入:年\周\月\日\时\分\秒
}
//读取当前时间并解释
void ReadDate(void)
{
DS3231ReadTime(); //读取当前时间
BCDtoASCII(CURDATE[0],&NowDATE[2]); //年 ,00~10
BCDtoASCII(CURDATE[1],&NowDATE[6]); //月 ,01~12
BCDtoASCII(CURDATE[2],&NowDATE[10]); //日 ,01~31(28/30/31)
BCDtoASCII(CURDATE[4],&NowDATE[14]); //时 ,00~23
BCDtoASCII(CURDATE[5],&NowDATE[18]); //分 ,00~59
BCDtoASCII(CURDATE[6],&NowDATE[22]); //秒 ,00~59
decodeWEEK(CURDATE[3],&NowDATE[31]); //星期 ,1~7 一~日
}
unsigned char DS3231TWIReadTemperature(void) //读取时间
{
unsigned char temph=0; //温度高字节
// unsigned char templ=0; //温度低字节
unsigned char temp=DS3231TWIRead(CMD_STATUS);
temp&=~(1<<BSY);
if(!temp)
{
temph=DS3231TWIRead(CMD_TEMPERATUREH);
/*templ=DS3231TWIRead(CMD_TEMPERATUREL);
//温度处理
temph<<=2;
templ>>=6;
temph=temph+templ;*/
}
return temph;
}
void ReadTemperature(void)
{
if(ReadTemperatureflag)
{
temperature=DS3231TWIReadTemperature();
if(temperature)
{
ReadTemperatureflag=0;
//temperature=DS3231TWIReadTemperature();
BCDtoASCII(temperature,&NowTemperature[10]);
UARTSendString(NowTemperature);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -