2020-12-18 09:35:14 +00:00
|
|
|
|
#include "BM8563_RTC.h"
|
|
|
|
|
|
|
|
|
|
BM8563_RTC::BM8563_RTC()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BM8563_RTC::begin(void)
|
|
|
|
|
{
|
|
|
|
|
Wire1.begin(21, 22);
|
|
|
|
|
WriteReg(0x00,0x00);
|
|
|
|
|
WriteReg(0x01,0x00);
|
|
|
|
|
WriteReg(0x0D,0x00);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BM8563_RTC::WriteReg(uint8_t reg, uint8_t data)
|
|
|
|
|
{
|
|
|
|
|
Wire1.beginTransmission(RTC_ADRESS);
|
|
|
|
|
Wire1.write(reg);
|
|
|
|
|
Wire1.write(data);
|
|
|
|
|
Wire1.endTransmission();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t BM8563_RTC::ReadReg(uint8_t reg)
|
|
|
|
|
{
|
|
|
|
|
Wire1.beginTransmission(0x51);
|
|
|
|
|
Wire1.write(reg);
|
|
|
|
|
Wire1.endTransmission();
|
|
|
|
|
Wire1.requestFrom(0x51, 1);
|
|
|
|
|
return Wire1.read();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BM8563_RTC::GetBm8563Time(void)
|
|
|
|
|
{
|
|
|
|
|
Wire1.beginTransmission(0x51);
|
|
|
|
|
Wire1.write(0x02);
|
|
|
|
|
Wire1.endTransmission();
|
|
|
|
|
Wire1.requestFrom(0x51, 7);
|
|
|
|
|
while (Wire1.available())
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
trdata[0] = Wire1.read();
|
|
|
|
|
trdata[1] = Wire1.read();
|
|
|
|
|
trdata[2] = Wire1.read();
|
|
|
|
|
trdata[3] = Wire1.read();
|
|
|
|
|
trdata[4] = Wire1.read();
|
|
|
|
|
trdata[5] = Wire1.read();
|
|
|
|
|
trdata[6] = Wire1.read();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DataMask();
|
|
|
|
|
Bcd2asc();
|
|
|
|
|
Str2Time();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BM8563_RTC::Str2Time(void)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
Second = (asc[0] - 0x30) * 10 + asc[1] - 0x30;
|
|
|
|
|
Minute = (asc[2] - 0x30) * 10 + asc[3] - 0x30;
|
|
|
|
|
Hour = (asc[4] - 0x30) * 10 + asc[5] - 0x30;
|
|
|
|
|
/*
|
|
|
|
|
uint8_t Hour;
|
|
|
|
|
uint8_t Week;
|
|
|
|
|
uint8_t Day;
|
|
|
|
|
uint8_t Month;
|
|
|
|
|
uint8_t Year;
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BM8563_RTC::DataMask()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
trdata[0] = trdata[0] & 0x7f; //秒
|
|
|
|
|
trdata[1] = trdata[1] & 0x7f; //分
|
|
|
|
|
trdata[2] = trdata[2] & 0x3f; //时
|
|
|
|
|
|
|
|
|
|
trdata[3] = trdata[3] & 0x3f; //日
|
|
|
|
|
trdata[4] = trdata[4] & 0x07; //星期
|
|
|
|
|
trdata[5] = trdata[5] & 0x1f; //月
|
|
|
|
|
|
|
|
|
|
trdata[6] = trdata[6] & 0xff; //年
|
|
|
|
|
}
|
|
|
|
|
/********************************************************************
|
|
|
|
|
函 数 名: void Bcd2asc(void)
|
|
|
|
|
功 能: bcd 码转换成 asc 码,供Lcd显示用
|
|
|
|
|
说 明:
|
|
|
|
|
调 用:
|
|
|
|
|
入口参数:
|
|
|
|
|
返 回 值:无
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
void BM8563_RTC::Bcd2asc(void)
|
|
|
|
|
{
|
|
|
|
|
uint8_t i, j;
|
|
|
|
|
for (j = 0, i = 0; i < 7; i++)
|
|
|
|
|
{
|
|
|
|
|
asc[j++] = (trdata[i] & 0xf0) >> 4 | 0x30; /*格式为: 秒 分 时 日 月 星期 年 */
|
|
|
|
|
asc[j++] = (trdata[i] & 0x0f) | 0x30;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t BM8563_RTC::Bcd2ToByte(uint8_t Value)
|
|
|
|
|
{
|
|
|
|
|
uint8_t tmp = 0;
|
|
|
|
|
tmp = ((uint8_t)(Value & (uint8_t)0xF0) >> (uint8_t)0x4) * 10;
|
|
|
|
|
return (tmp + (Value & (uint8_t)0x0F));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t BM8563_RTC::ByteToBcd2(uint8_t Value)
|
|
|
|
|
{
|
|
|
|
|
uint8_t bcdhigh = 0;
|
|
|
|
|
|
|
|
|
|
while (Value >= 10)
|
|
|
|
|
{
|
|
|
|
|
bcdhigh++;
|
|
|
|
|
Value -= 10;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ((uint8_t)(bcdhigh << 4) | Value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BM8563_RTC::GetTime(RTC_TimeTypeDef *RTC_TimeStruct)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
//if()
|
|
|
|
|
uint8_t buf[3] = {0};
|
|
|
|
|
|
|
|
|
|
Wire1.beginTransmission(0x51);
|
|
|
|
|
Wire1.write(0x02);
|
|
|
|
|
Wire1.endTransmission();
|
|
|
|
|
Wire1.requestFrom(0x51, 3);
|
|
|
|
|
|
|
|
|
|
while (Wire1.available())
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
buf[0] = Wire1.read();
|
|
|
|
|
buf[1] = Wire1.read();
|
|
|
|
|
buf[2] = Wire1.read();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RTC_TimeStruct->Seconds = Bcd2ToByte(buf[0] & 0x7f); //秒
|
|
|
|
|
RTC_TimeStruct->Minutes = Bcd2ToByte(buf[1] & 0x7f); //分
|
|
|
|
|
RTC_TimeStruct->Hours = Bcd2ToByte(buf[2] & 0x3f); //时
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BM8563_RTC::SetTime(RTC_TimeTypeDef *RTC_TimeStruct)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (RTC_TimeStruct == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
Wire1.beginTransmission(0x51);
|
|
|
|
|
Wire1.write(0x02);
|
|
|
|
|
Wire1.write(ByteToBcd2(RTC_TimeStruct->Seconds));
|
|
|
|
|
Wire1.write(ByteToBcd2(RTC_TimeStruct->Minutes));
|
|
|
|
|
Wire1.write(ByteToBcd2(RTC_TimeStruct->Hours));
|
|
|
|
|
Wire1.endTransmission();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BM8563_RTC::GetDate(RTC_DateTypeDef *RTC_DateStruct)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
uint8_t buf[4] = {0};
|
|
|
|
|
|
|
|
|
|
Wire1.beginTransmission(0x51);
|
|
|
|
|
Wire1.write(0x05);
|
|
|
|
|
Wire1.endTransmission();
|
|
|
|
|
Wire1.requestFrom(0x51, 4);
|
|
|
|
|
|
|
|
|
|
while (Wire1.available())
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
buf[0] = Wire1.read();
|
|
|
|
|
buf[1] = Wire1.read();
|
|
|
|
|
buf[2] = Wire1.read();
|
|
|
|
|
buf[3] = Wire1.read();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RTC_DateStruct->Date = Bcd2ToByte(buf[0] & 0x3f);
|
|
|
|
|
RTC_DateStruct->WeekDay = Bcd2ToByte(buf[1] & 0x07);
|
|
|
|
|
RTC_DateStruct->Month = Bcd2ToByte(buf[2] & 0x1f);
|
|
|
|
|
|
|
|
|
|
if (buf[2] & 0x80)
|
|
|
|
|
{
|
|
|
|
|
RTC_DateStruct->Year = 1900 + Bcd2ToByte(buf[3] & 0xff);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
RTC_DateStruct->Year = 2000 + Bcd2ToByte(buf[3] & 0xff);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BM8563_RTC::SetDate(RTC_DateTypeDef *RTC_DateStruct)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (RTC_DateStruct == NULL)
|
|
|
|
|
return;
|
|
|
|
|
Wire1.beginTransmission(0x51);
|
|
|
|
|
Wire1.write(0x05);
|
|
|
|
|
Wire1.write(ByteToBcd2(RTC_DateStruct->Date));
|
|
|
|
|
Wire1.write(ByteToBcd2(RTC_DateStruct->WeekDay));
|
|
|
|
|
|
|
|
|
|
if (RTC_DateStruct->Year < 2000)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
Wire1.write(ByteToBcd2(RTC_DateStruct->Month) | 0x80);
|
|
|
|
|
Wire1.write(ByteToBcd2((uint8_t)(RTC_DateStruct->Year % 100)));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* code */
|
|
|
|
|
Wire1.write(ByteToBcd2(RTC_DateStruct->Month) | 0x00);
|
|
|
|
|
Wire1.write(ByteToBcd2((uint8_t)(RTC_DateStruct->Year % 100)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Wire1.endTransmission();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int BM8563_RTC::SetAlarmIRQ(int afterSeconds)
|
|
|
|
|
{
|
|
|
|
|
uint8_t reg_value = 0;
|
|
|
|
|
reg_value = ReadReg(0x01);
|
|
|
|
|
|
|
|
|
|
if (afterSeconds < 0)
|
|
|
|
|
{
|
|
|
|
|
reg_value &= ~(1 << 0);
|
|
|
|
|
WriteReg(0x01, reg_value);
|
|
|
|
|
reg_value = 0x03;
|
|
|
|
|
WriteReg(0x0E, reg_value);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t type_value = 2;
|
|
|
|
|
uint8_t div = 1;
|
|
|
|
|
if (afterSeconds > 255)
|
|
|
|
|
{
|
|
|
|
|
div = 60;
|
|
|
|
|
type_value = 0x83;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
type_value = 0x82;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
afterSeconds = (afterSeconds / div) & 0xFF;
|
|
|
|
|
WriteReg(0x0F, afterSeconds);
|
|
|
|
|
WriteReg(0x0E, type_value);
|
|
|
|
|
|
|
|
|
|
reg_value |= (1 << 0);
|
|
|
|
|
reg_value &= ~(1 << 7);
|
|
|
|
|
WriteReg(0x01, reg_value);
|
|
|
|
|
return afterSeconds * div;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int BM8563_RTC::SetAlarmIRQ(const RTC_TimeTypeDef &RTC_TimeStruct)
|
|
|
|
|
{
|
|
|
|
|
uint8_t irq_enable = false;
|
|
|
|
|
uint8_t out_buf[4] = {0x80, 0x80, 0x80, 0x80};
|
|
|
|
|
|
|
|
|
|
if (RTC_TimeStruct.Minutes >= 0)
|
|
|
|
|
{
|
|
|
|
|
irq_enable = true;
|
|
|
|
|
out_buf[0] = ByteToBcd2(RTC_TimeStruct.Minutes) & 0x7f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (RTC_TimeStruct.Hours >= 0)
|
|
|
|
|
{
|
|
|
|
|
irq_enable = true;
|
|
|
|
|
out_buf[1] = ByteToBcd2(RTC_TimeStruct.Hours) & 0x3f;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-26 08:44:01 +00:00
|
|
|
|
//out_buf[2] = 0x00;
|
|
|
|
|
//out_buf[3] = 0x00;
|
2020-12-18 09:35:14 +00:00
|
|
|
|
|
|
|
|
|
uint8_t reg_value = ReadReg(0x01);
|
|
|
|
|
|
|
|
|
|
if (irq_enable)
|
|
|
|
|
{
|
|
|
|
|
reg_value |= (1 << 1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
reg_value &= ~(1 << 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
|
{
|
|
|
|
|
WriteReg(0x09 + i, out_buf[i]);
|
|
|
|
|
}
|
|
|
|
|
WriteReg(0x01, reg_value);
|
|
|
|
|
|
|
|
|
|
return irq_enable ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int BM8563_RTC::SetAlarmIRQ(const RTC_DateTypeDef &RTC_DateStruct, const RTC_TimeTypeDef &RTC_TimeStruct)
|
|
|
|
|
{
|
|
|
|
|
uint8_t irq_enable = false;
|
|
|
|
|
uint8_t out_buf[4] = {0x80, 0x80, 0x80, 0x80};
|
|
|
|
|
|
|
|
|
|
if (RTC_TimeStruct.Minutes >= 0)
|
|
|
|
|
{
|
|
|
|
|
irq_enable = true;
|
|
|
|
|
out_buf[0] = ByteToBcd2(RTC_TimeStruct.Minutes) & 0x7f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (RTC_TimeStruct.Hours >= 0)
|
|
|
|
|
{
|
|
|
|
|
irq_enable = true;
|
|
|
|
|
out_buf[1] = ByteToBcd2(RTC_TimeStruct.Hours) & 0x3f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (RTC_DateStruct.Date >= 0)
|
|
|
|
|
{
|
|
|
|
|
irq_enable = true;
|
|
|
|
|
out_buf[2] = ByteToBcd2(RTC_DateStruct.Date) & 0x3f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (RTC_DateStruct.WeekDay >= 0)
|
|
|
|
|
{
|
|
|
|
|
irq_enable = true;
|
|
|
|
|
out_buf[3] = ByteToBcd2(RTC_DateStruct.WeekDay) & 0x07;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t reg_value = ReadReg(0x01);
|
|
|
|
|
|
|
|
|
|
if (irq_enable)
|
|
|
|
|
{
|
|
|
|
|
reg_value |= (1 << 1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
reg_value &= ~(1 << 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
|
{
|
|
|
|
|
WriteReg(0x09 + i, out_buf[i]);
|
|
|
|
|
}
|
|
|
|
|
WriteReg(0x01, reg_value);
|
|
|
|
|
|
|
|
|
|
return irq_enable ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BM8563_RTC::clearIRQ()
|
|
|
|
|
{
|
|
|
|
|
uint8_t data = ReadReg(0x01);
|
|
|
|
|
WriteReg(0x01, data & 0xf3);
|
|
|
|
|
}
|
|
|
|
|
void BM8563_RTC::disableIRQ()
|
|
|
|
|
{
|
|
|
|
|
clearIRQ();
|
|
|
|
|
uint8_t data = ReadReg(0x01);
|
|
|
|
|
WriteReg(0x01, data & 0xfC);
|
|
|
|
|
}
|