Files
acquisition_module/RTC.c

305 lines
7.5 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "MAIN.H"
#include <stdio.h>
#include "RTC.H"
#include <string.h>
//unsigned char bySta = 0;
void SDAOut(bit c)
{
SFR_PAGE(_pp0, noSST); // switch to page 0
P0_DIR = P0_DIR | 0x08;//修改P0.3为输出
P0_3 = c;
}
void SCLOut(bit c)
{
P0_2 = c;
}
void iic_start(void)
{
SDAOut(1);
_nop_();
SCLOut(1);
somenop;
SDAOut(0);
somenop;
SCLOut(0);
}
void iic_stop(void)
{
SDAOut(0);
_nop_();
SCLOut(1);
somenop;
SDAOut(1);
}
void iic_ack(bit ackbit)
{
if(ackbit)
SDAOut(0);
else
SDAOut(1);
somenop;
SCLOut(1);
somenop;
SCLOut(0);
SDAOut(1);
somenop;
}
bit iic_waitack(void)
{
SDAOut(1);
somenop;
SCLOut(1);
SFR_PAGE(_pp0, noSST); // switch to page 0
P0_DIR = P0_DIR & 0xF7;//修改P4.3为输入
somenop;
if(P0_3)
{
SCLOut(0);
iic_stop();
return 0;
}
else
{
SCLOut(0);
return 1;
}
}
void iic_sendbyte(unsigned char byt)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(byt&0x80)
SDAOut(1);
else
SDAOut(0);
somenop;
SCLOut(1);
byt <<= 1;
somenop;
SCLOut(0);
}
}
unsigned char iic_recbyte(void)
{
unsigned char da;
unsigned char i;
SFR_PAGE(_pp0, noSST); // switch to page 0
P0_DIR = P0_DIR & 0xF7;//修改P4.3为输入
for(i=0;i<8;i++)
{
SCLOut(1);
somenop;
da <<= 1;
// P1_IOCR01 = 0x0020; // load port control register 1
if(P0_3)
da |= 0x01;
SCLOut(0);
somenop;
}
return da;
}
// 十进制转 BCD 码
unsigned char DecToBcd(unsigned char dec)
{
return ((dec / 10) << 4) | (dec % 10);
}
// BCD 码转十进制
unsigned char BcdToDec(unsigned char bcd)
{
return ((bcd >> 4) * 10) + (bcd & 0x0F);
}
// BM8563 写寄存器函数
void BM8563_WriteReg(unsigned char reg, unsigned char rdata)
{
iic_start();
iic_sendbyte(BM8563_ADDR); // 发送 BM8563 的 I2C 地址,写操作
iic_waitack();
iic_sendbyte(reg); // 发送寄存器地址
iic_waitack();
iic_sendbyte(rdata); // 发送数据
iic_waitack();
iic_stop();
}
// BM8563 读寄存器函数
unsigned char BM8563_ReadReg(unsigned char reg)
{
unsigned char rdata;
iic_start();
iic_sendbyte(BM8563_ADDR); // 发送 BM8563 的 I2C 地址,写操作
iic_waitack();
iic_sendbyte(reg); // 发送寄存器地址
iic_waitack();
iic_start();
iic_sendbyte(BM8563_ADDR | 0x01); // 发送 BM8563 的 I2C 地址,读操作
iic_waitack();
rdata = iic_recbyte();
iic_ack(0);
iic_stop();
return rdata;
}
/**
* @brief 检查报警标志AF是否置位Bit3
* @retval true-报警已触发false-无报警
*/
bool bm8563CheckAlarmFlag(void)
{
ubyte reg_val = BM8563_ReadReg(BM8563_CSR2);
return (reg_val & BM8563_AF_BIT) != 0; // 检查Bit3,如果为0的话那就
}
// 限制值在最小值和最大值之间
ubyte constrain(ubyte value, ubyte min_val, ubyte max_val)
{
if (value < min_val)
{
return min_val;
}
else if (value > max_val)
{
return max_val;
}
else
{
return value;
}
}
/**
* @brief 设置BM8563当前时间整合世纪位到月份寄存器
* @param pTime: 时间结构体指针年份需为完整四位数如1984、2024
* @retval 无
*/
void bm8563SetTime(UnTimeOutput *pTime)
{
ubyte reg_sec = 0;
UnTimeOutput time_temp = {0};
if (pTime == NULL) {
return; // 错误处理可扩展
}
memcpy(&time_temp,pTime,sizeof(UnTimeOutput));//先拷贝
time_temp.bit_data.year = constrain(time_temp.bit_data.year,0,99);//限制值范围
time_temp.bit_data.month = constrain(time_temp.bit_data.month,1,12);//限制值范围
time_temp.bit_data.day = constrain(time_temp.bit_data.day,1,31);//限制值范围
time_temp.bit_data.hour = constrain(time_temp.bit_data.hour,0,23);//限制值范围
time_temp.bit_data.week = constrain(time_temp.bit_data.week,0,6);//限制值范围
time_temp.bit_data.minute = constrain(time_temp.bit_data.minute,0,59);//限制值范围
time_temp.bit_data.second = constrain(time_temp.bit_data.second,0,59);//限制值范围
BM8563_WriteReg( BM8563_YEAR, DecToBcd(pTime->bit_data.year) );//写年还得转换为BCD码
BM8563_WriteReg( BM8563_MONTH, DecToBcd(pTime->bit_data.month)&0x1F);//写月还得转换为BCD码
BM8563_WriteReg( BM8563_DAY, DecToBcd(pTime->bit_data.day)&0x3F);//写日还得转换为BCD码
BM8563_WriteReg( BM8563_HOUR, DecToBcd(pTime->bit_data.hour)&0x3F);//写小时还得转换为BCD码
BM8563_WriteReg( BM8563_WEEK, pTime->bit_data.week&0x07 );//写周,不需要转
BM8563_WriteReg( BM8563_MIN, DecToBcd( pTime->bit_data.minute)&0x7F);//写分钟还得转换为BCD码
// 秒地址0x02保留Bit7CH时钟停止位
reg_sec = BM8563_ReadReg(BM8563_SEC) & 0x80;//
BM8563_WriteReg(BM8563_SEC, reg_sec | (DecToBcd(pTime->bit_data.second) & 0x7F));//注意高位为掉电指示
}
/**
* @brief 读取BM8563当前时间到联合体
* @param pTime: UnTimeOutput联合体指针用于存储读取到的时间数据
* @retval 无
*/
void bm8563GetTime(UnTimeOutput *pTime)
{
pTime->bit_data.year = BcdToDec(BM8563_ReadReg(BM8563_YEAR) );//先去除多余位在转换10进制
pTime->bit_data.month = BcdToDec(BM8563_ReadReg(BM8563_MONTH)&0x1F);
pTime->bit_data.day = BcdToDec(BM8563_ReadReg(BM8563_DAY)&0x3F);
pTime->bit_data.hour = BcdToDec(BM8563_ReadReg(BM8563_HOUR)&0x3F);
pTime->bit_data.week = BM8563_ReadReg(BM8563_WEEK)&0x07;
pTime->bit_data.minute = BcdToDec(BM8563_ReadReg(BM8563_MIN)&0x7F);
pTime->bit_data.second = BcdToDec(BM8563_ReadReg(BM8563_SEC)&0x7F);
}
/**
* @brief 设置BM8563闹钟字段为0时禁用对应报警
* @param pTime: UnTimeOutput联合体指针包含闹钟时间参数
* @retval 无
*/
ubyte bm8563SetAlarm(UnTimeOutput *pTime)
{
UnTimeOutput current_time_temp = {0};
UnTimeOutput output_time_temp = {0};
ubyte carry_hour = 0;
ubyte carry_day = 0;
// 检查指针有效性
if( (pTime == NULL) || ( (0 == pTime->bit_data.minute) && (0 == pTime->bit_data.hour) && (0 == pTime->bit_data.day) ) )//数据都为0或者指针都为0
{
// 可选:添加错误处理(如日志输出)
return 1;
}
bm8563GetTime(&current_time_temp);//先获取当前时间
//计算分
output_time_temp.bit_data.minute = current_time_temp.bit_data.minute + pTime->bit_data.minute;
if( output_time_temp.bit_data.minute >= 60 )//超过需要进位
{
output_time_temp.bit_data.minute = output_time_temp.bit_data.minute - 60;
carry_hour = 1;
}
//计算小时
output_time_temp.bit_data.hour = current_time_temp.bit_data.hour + pTime->bit_data.hour + carry_hour;
if( output_time_temp.bit_data.hour >= 24 )//超过需要进位
{
output_time_temp.bit_data.hour = output_time_temp.bit_data.hour - 24;
carry_day = 1;
}
output_time_temp.bit_data.day = current_time_temp.bit_data.day + pTime->bit_data.day + carry_day;
if( output_time_temp.bit_data.day >= 31 )//超过需要进位
{
output_time_temp.bit_data.day = 31;
}
output_time_temp.bit_data.week = 0;
BM8563_WriteReg( BM8563_ALARM_DAY, DecToBcd(output_time_temp.bit_data.day)&0x3F);//写日还得转换为BCD码
BM8563_WriteReg( BM8563_ALARM_HOUR, DecToBcd(output_time_temp.bit_data.hour)&0x3F);//写小时还得转换为BCD码
BM8563_WriteReg( BM8563_ALARM_WEEK, 0x80 );//写周,会和日冲突,所以不需要闹钟
BM8563_WriteReg( BM8563_ALARM_MIN, DecToBcd(output_time_temp.bit_data.minute)&0x7F);//写分钟还得转换为BCD码
// 秒地址0x02保留Bit7CH时钟停止位
// 使能闹钟中断地址0x01AIE=1AF=0
BM8563_WriteReg(BM8563_CSR2, 0x02);
return 0;
}