?? 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 + -