⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ds3231.c

📁 MAXIM的DS3231时钟,温度都具备的芯片.驱动IC为AVRmega16或者mega32.全功能.内附全部驱动程序.绝对原创.
💻 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 + -