From 68a29fd6461869f746294804e4b5491f8b33f470 Mon Sep 17 00:00:00 2001 From: liumin Date: Sun, 6 Jul 2025 16:12:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4=20RTC.c?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- RTC.c | 415 ---------------------------------------------------------- 1 file changed, 415 deletions(-) delete mode 100644 RTC.c diff --git a/RTC.c b/RTC.c deleted file mode 100644 index 380954c..0000000 --- a/RTC.c +++ /dev/null @@ -1,415 +0,0 @@ -#include "MAIN.H" -#include -#include "RTC.H" - -unsigned char bySta = 0; - -// 静态月份天数表(平年,索引1~12对应1月~12月) -ubyte days_in_month[12] = { - 31, // 1月 - 28, // 2月(平年) - 31, // 3月 - 30, // 4月 - 31, // 5月 - 30, // 6月 - 31, // 7月 - 31, // 8月 - 30, // 9月 - 31, // 10月 - 30, // 11月 - 31 // 12月 -}; - - -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; -} - -// 判断闰年 -ubyte leapYear(uword year) { - return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; -} - - -/** - * @brief 获取指定年份和月份的天数(自动处理闰年) - * @param year: 年份(四位数,如2024) - * @param month: 月份(1-12) - * @retval 该月天数(若参数非法返回0) - */ -ubyte getMonthDays(uword year, ubyte month) { - // 静态月份天数表(平年,索引1~12对应1月~12月) - ubyte days_in_month[13] = { - 0, 31, 28, 31, 30, 31, 30, - 31, 31, 30, 31, 30, 31 - }; - - // 参数校验 - if (month < 1 || month > 12) return 0; - - // 处理闰年2月 - if (month == 2 && leapYear(year)) { - return 29; - } - - // 返回常规天数 - return days_in_month[month]; -} - - -/** - * @brief 检查报警标志AF是否置位(Bit3) - * @retval true-报警已触发,false-无报警 - */ -bool bm8563CheckAlarmFlag(void) { - ubyte reg_val = BM8563_ReadReg(BM8563_CSR2); - return (reg_val & BM8563_AF_BIT) != 0; // 检查Bit3 -} - -/** - * @brief 清除报警标志AF(Bit3) - * @note 保留其他位(如Bit1 AIE标志)状态 - */ -void bm8563ClearAlarmFlag(void) { - ubyte reg_val = BM8563_ReadReg(BM8563_CSR2); - reg_val &= ~BM8563_AF_BIT; // 仅清除Bit3 - BM8563_WriteReg(BM8563_CSR2, reg_val); -} - - - -/** - * @brief 设置BM8563当前时间(整合世纪位到月份寄存器) - * @param pTime: 时间结构体指针(年份需为完整四位数,如1984、2024) - * @retval 无 - */ -void bm8563SetTime(UnTimeOutput *pTime) { - - ubyte century_bit = 0; // 完整四位数年份 - ubyte reg_sec = 0; - ubyte month_bcd = 0; - if (pTime == NULL) return; - - // --- 世纪位计算 --- - // 根据年份设置世纪标志(0:20世纪及之后,1:19世纪) -// uint8_t century_bit = (pTime->bit_data.year >= 2000) ? 0 : 1; // 完整四位数年份 - - // --- 寄存器写入(带掩码)--- - // 秒(地址0x02):保留Bit7(CH时钟停止位) - reg_sec = BM8563_ReadReg(BM8563_SEC) & 0x80; - BM8563_WriteReg(BM8563_SEC, reg_sec | (DecToBcd(pTime->bit_data.second) & 0x7F)); - - // 分(地址0x03) - BM8563_WriteReg(BM8563_MIN, DecToBcd(pTime->bit_data.minute) & 0x7F); - - // 小时(地址0x04):24小时制 - BM8563_WriteReg(BM8563_HOUR, DecToBcd(pTime->bit_data.hour) & 0x3F); - - // 日(地址0x05):屏蔽闹钟使能位 - BM8563_WriteReg(BM8563_DAY, DecToBcd(pTime->bit_data.day) & 0x3F); - - // 周(地址0x06):值范围1-7 - BM8563_WriteReg(BM8563_WEEK, pTime->bit_data.week & 0x07); - - // 月(地址0x07):世纪位写入Bit7,月份占低5位 - month_bcd = DecToBcd(pTime->bit_data.month); - BM8563_WriteReg(BM8563_MONTH, (century_bit << 7) | (month_bcd & 0x1F)); - - // 年(地址0x08):存储后两位(如2024→0x24) - BM8563_WriteReg(BM8563_YEAR, DecToBcd(pTime->bit_data.year)); -} - - -/** - * @brief 读取BM8563当前时间到联合体 - * @param pTime: UnTimeOutput联合体指针(用于存储读取到的时间数据) - * @retval 无 - */ -void bm8563GetTime(UnTimeOutput *pTime) { - if (pTime == NULL) { - return; // 错误处理可扩展 - } - - // 读取秒(地址0x02) - pTime->bit_data.second = BcdToDec(BM8563_ReadReg(BM8563_SEC) & 0x7F); // 屏蔽无效位 - - // 读取分钟(地址0x03) - pTime->bit_data.minute = BcdToDec(BM8563_ReadReg(BM8563_MIN) & 0x7F); - - // 读取小时(地址0x04) - pTime->bit_data.hour = BcdToDec(BM8563_ReadReg(BM8563_HOUR) & 0x3F); // 24小时制需屏蔽Bit6-7 - - // 读取日(地址0x05) - pTime->bit_data.day = BcdToDec(BM8563_ReadReg(BM8563_DAY) & 0x3F); // 屏蔽控制位 - - // 读取周(地址0x06,BM8563周值为0x01-0x07,无需BCD转换) - pTime->bit_data.week = BM8563_ReadReg(BM8563_WEEK) & 0x07; // 仅保留低3位 - - // 读取月(地址0x07) - pTime->bit_data.month = BcdToDec(BM8563_ReadReg(BM8563_MONTH) & 0x1F); // 屏蔽Bit5-7 - - // 读取年(地址0x08,假设为2000+年) - pTime->bit_data.year = BcdToDec(BM8563_ReadReg(BM8563_YEAR)); -} - - - - -/** - * @brief 设置BM8563闹钟(字段为0时禁用对应报警) - * @param pTime: UnTimeOutput联合体指针,包含闹钟时间参数 - * @retval 无 - */ -ubyte bm8563SetAlarm(UnTimeOutput *pTime) { - - UnTimeOutput un_temp_output = {0};//接收设定时间 - ubyte carry_hour = 0; - ubyte carry_day = 0; - ubyte month_days = 0; -//------------------------------------------------- - // 检查指针有效性 - if( (pTime == NULL) || ( (0 == pTime->bit_data.minute) && (0 == pTime->bit_data.hour) && (0 == pTime->bit_data.day) ) )//数据都为0或者指针都为0 - { - // 可选:添加错误处理(如日志输出) - return 1; - } - - bm8563GetTime(¤ttime); - - // 分钟溢出处理(0-59) - un_temp_output.bit_data.minute = currenttime.bit_data.minute + pTime->bit_data.minute; - if (un_temp_output.bit_data.minute >= 60) { - un_temp_output.bit_data.minute -= 60; - carry_hour = 1; // 向小时进位 - } - - // 小时溢出处理(0-23) - un_temp_output.bit_data.hour = currenttime.bit_data.hour + pTime->bit_data.hour + carry_hour; - if (un_temp_output.bit_data.hour >= 24) { - un_temp_output.bit_data.hour -= 24; - carry_day = 1; // 向天进位 - } - - // 天溢出处理(需考虑月份最大天数) - un_temp_output.bit_data.day = currenttime.bit_data.day + pTime->bit_data.day + carry_day; - //2月考虑平年和闰年 - month_days = getMonthDays( (currenttime.bit_data.year+2000),currenttime.bit_data.month); - - // 天溢出处理(需考虑月份最大天数) - if (un_temp_output.bit_data.day > month_days) - { - un_temp_output.bit_data.day -= month_days; - //最大限制,如果超过1个月,就少一天,BM8563最大只支持这么大 - if(un_temp_output.bit_data.day == currenttime.bit_data.day) - { - un_temp_output.bit_data.day = (currenttime.bit_data.day - 1); - } - } - - un_temp_output.bit_data.week = 0;//不需要周报警 - -// 报警分钟设置(地址0x09) - BM8563_WriteReg(BM8563_ALARM_MIN, DecToBcd(un_temp_output.bit_data.minute) & 0x7F); // AE_M=0(启用) -// 报警小时设置(地址0x0A) - BM8563_WriteReg(BM8563_ALARM_HOUR, DecToBcd(un_temp_output.bit_data.hour) & 0x7F); // AE_H=0(启用) -// 日报警/周报警互斥设置 - BM8563_WriteReg(BM8563_ALARM_DAY, DecToBcd(un_temp_output.bit_data.day) & 0x7F); // AE_D=0(启用日) - BM8563_WriteReg(BM8563_ALARM_WEEK, 0x80); // AE_W=1(禁用周) -// 使能闹钟中断(地址0x01,AIE=1,AF=0) - BM8563_WriteReg(BM8563_CSR2, 0x02); - - return 0; -} - - - - - - - - - - - - -//// 配置 BM8563 的闹钟,实现间隔 4 小时的唤醒 -//void BM8563_Set4HourAlarm() -//{ -// unsigned char alarmMin = BcdToDec( BM8563_ReadReg(BM8563_MIN) ); -// unsigned char alarmMinBcd = 0; -////------------------------------------------------------------ -// alarmMin = (alarmMin + 2) % 60;//计算 4 小时后的小时数 -// alarmMinBcd = DecToBcd(alarmMin); - -// BM8563_WriteReg(BM8563_ALARM_MIN,alarmMinBcd&0x7F);// 闹钟分钟设置 -// BM8563_WriteReg(BM8563_ALARM_HOUR, 0x80); // 无效 -// BM8563_WriteReg(BM8563_ALARM_DAY , 0x80); // 无效 -// BM8563_WriteReg(BM8563_ALARM_WEEK, 0x80); // 无效 -// -// // 配置闹钟控制寄存器,使能闹钟中断 -// BM8563_WriteReg(BM8563_CSR2, 0x02); -//} - - - - - - - - - - -