|
|
本帖最后由 LinY 于 2026-3-31 16:18 编辑
MCU: STM32L431RCT6
最早是直接用STOP模式进行低功耗的,发现还是会有几mA,因为有个只要有电就亮的电源灯,还要其他周边。
后面改成用RX8025T做时能供电,断电前写入闹钟配置,闹钟触发自动重启使能
测试环境测试一直没问题,现在在现场有个别设备就是不定期隔几天唤醒不了,盒子拿回来也测不出来。
业务上是每半小时重启一次。
闹钟每次设置的每天的下一次整30分钟,00:00,00:30,01:00...
现场设备确实休眠了的,也没有重启,重启我这边能有请求的。
就是休眠之后换不行了
想问问各位大佬可能原因?
[C] 纯文本查看 复制代码
#ifndef __RX8025T_H
#define __RX8025T_H
#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"
#include <stdbool.h>
#include <stdlib.h>
/* RX8025T I2C地址配置 - 使用0x64 */
#define RX8025T_I2C_ADDR 0x64
#define RX8025T_I2C_ADDR_HAL RX8025T_I2C_ADDR // 使用0x64
/* 寄存器地址定义 */
#define RX8025T_REG_SEC 0x00
#define RX8025T_REG_MIN 0x01
#define RX8025T_REG_HOUR 0x02
#define RX8025T_REG_WEEK 0x03
#define RX8025T_REG_DAY 0x04
#define RX8025T_REG_MONTH 0x05
#define RX8025T_REG_YEAR 0x06
#define RX8025T_REG_RAM 0x07
#define RX8025T_REG_MIN_ALARM 0x08
#define RX8025T_REG_HOUR_ALARM 0x09
#define RX8025T_REG_WEEK_DAY_ALARM 0x0A
#define RX8025T_REG_TIM_CNT0 0x0B
#define RX8025T_REG_TIM_CNT1 0x0C
#define RX8025T_REG_EXTEN 0x0D
#define RX8025T_REG_FLAG 0x0E
#define RX8025T_REG_CONTROL 0x0F
/* 扩展寄存器(0x0D)位定义 */
#define RX8025T_EXTEN_TEST (1 << 7) // 测试位(不要使用)
#define RX8025T_EXTEN_WADA (1 << 6) // 0:周报警模式, 1:日报警模式
#define RX8025T_EXTEN_USEL (1 << 5) // 0:每秒更新, 1:每分钟更新
#define RX8025T_EXTEN_TE (1 << 4) // 定时器使能
#define RX8025T_EXTEN_FSEL1 (1 << 3) // FOUT频率选择
#define RX8025T_EXTEN_FSEL0 (1 << 2)
#define RX8025T_EXTEN_TSEL1 (1 << 1) // 定时器时钟源选择
#define RX8025T_EXTEN_TSEL0 (1 << 0)
/* 标志寄存器(0x0E)位定义 */
#define RX8025T_FLAG_UF (1 << 5) // 更新时间中断标志
#define RX8025T_FLAG_TF (1 << 4) // 定时器中断标志
#define RX8025T_FLAG_AF (1 << 3) // 报警中断标志
#define RX8025T_FLAG_VLF (1 << 1) // 电压低标志
#define RX8025T_FLAG_VDET (1 << 0) // 电压检测标志
/* 控制寄存器(0x0F)位定义 */
#define RX8025T_CONTR_CSEL1 (1 << 7) // 温度补偿间隔设置
#define RX8025T_CONTR_CSEL0 (1 << 6) // 00:0.5s, 01:1.0s, 10:2.0s(default), 11:4.0s
#define RX8025T_CONTR_UIE (1 << 5) // 更新时间中断使能
#define RX8025T_CONTR_TIE (1 << 4) // 定时器中断使能
#define RX8025T_CONTR_AIE (1 << 3) // 报警中断使能
#define RX8025T_CONTR_RESET (1 << 0) // 复位位(不要使用)
/* 报警使能标志 */
#define RX8025T_ALARM_AE_FLAG 0x80
/* 定时器时钟源选择 */
typedef enum
{
RX8025T_TIMER_SRC_4096HZ = 0x00, // 00: 4096Hz
RX8025T_TIMER_SRC_64HZ = 0x01, // 01: 64Hz
RX8025T_TIMER_SRC_1HZ = 0x02, // 10: 1Hz (每秒)
RX8025T_TIMER_SRC_1_60HZ = 0x03 // 11: 1/60Hz (每分钟)
} RX8025T_TimerSource;
/* FOUT频率选择 */
typedef enum
{
RX8025T_FOUT_DISABLE = 0x00, // 禁用输出
RX8025T_FOUT_32768HZ = 0x01, // 32768Hz
RX8025T_FOUT_1024HZ = 0x02, // 1024Hz
RX8025T_FOUT_1HZ = 0x03 // 1Hz
} RX8025T_FOUT_Freq;
/* 温度补偿间隔 */
typedef enum
{
RX8025T_TCS_0_5S = 0x00, // 0.5秒
RX8025T_TCS_1_0S = 0x40, // 1.0秒
RX8025T_TCS_2_0S = 0x80, // 2.0秒(默认)
RX8025T_TCS_4_0S = 0xC0 // 4.0秒
} RX8025T_TempCompInterval;
/* 星期枚举 */
typedef enum
{
RX8025T_SUNDAY = 0,
RX8025T_MONDAY,
RX8025T_TUESDAY,
RX8025T_WEDNESDAY,
RX8025T_THURSDAY,
RX8025T_FRIDAY,
RX8025T_SATURDAY
} RX8025T_DayOfWeek;
/* 时间结构体 */
typedef struct
{
uint8_t year; // 年份 (00-99)
uint8_t month; // 月份 (1-12)
uint8_t date; // 日期 (1-31)
uint8_t day_of_week; // 星期 (0-6, 0=周日)
uint8_t hour; // 小时 (0-23)
uint8_t minute; // 分钟 (0-59)
uint8_t second; // 秒 (0-59)
} RX8025T_TimeTypeDef;
/* 报警模式 */
typedef enum
{
RX8025T_ALARM_DISABLE = 0, // 报警禁用
RX8025T_ALARM_DAY_MODE = 1, // 日模式
RX8025T_ALARM_WEEK_MODE = 2 // 周模式
} RX8025T_AlarmMode;
/* 报警设置结构体 */
typedef struct
{
RX8025T_AlarmMode mode; // 报警模式
union
{
uint8_t day; // 日模式: 日期(1-31), 0x80:每天
uint8_t week; // 周模式: 位掩码(bit0-6:周日-周六)
} alarm_day_or_week; // 日期或星期
uint8_t hour; // 小时(0-23), 0x80:每小时
uint8_t minute; // 分钟(0-59), 0x80:每分钟(整点)
} RX8025T_AlarmTypeDef;
/* 电池状态结构体 */
typedef struct
{
bool voltage_low; // 电压低标志
bool voltage_detected; // 电压检测标志
} RX8025T_BatteryStatus;
/* 错误代码 */
typedef enum
{
RX8025T_OK = 0,
RX8025T_ERROR = 1,
RX8025T_ERROR_I2C = 2,
RX8025T_ERROR_TIMEOUT = 3,
RX8025T_ERROR_INVALID = 4,
RX8025T_ERROR_VOLTAGE = 5
} RX8025T_StatusTypeDef;
/* 初始化与基础操作 */
RX8025T_StatusTypeDef RX8025T_Init(I2C_HandleTypeDef* hi2c);
RX8025T_StatusTypeDef RX8025T_DeInit(void);
bool RX8025T_IsReady(void);
RX8025T_StatusTypeDef RX8025T_Reset(void);
/* 时间操作 */
RX8025T_StatusTypeDef RX8025T_GetTime(RX8025T_TimeTypeDef* time);
RX8025T_StatusTypeDef RX8025T_SetTime(RX8025T_TimeTypeDef* time);
bool RX8025T_ValidateTime(RX8025T_TimeTypeDef* time);
RX8025T_StatusTypeDef RX8025T_WaitUpdate(uint32_t timeout_ms);
/* 中断配置 */
RX8025T_StatusTypeDef RX8025T_EnableUpdateInterrupt(bool enable, bool per_second);
RX8025T_StatusTypeDef RX8025T_EnableTimerInterrupt(bool enable, RX8025T_TimerSource source, uint16_t count);
RX8025T_StatusTypeDef RX8025T_EnableAlarmInterrupt(bool enable, RX8025T_AlarmTypeDef* alarm);
/* 中断标志处理 */
RX8025T_StatusTypeDef RX8025T_GetInterruptFlags(uint8_t* flags);
RX8025T_StatusTypeDef RX8025T_ClearAllInterruptFlags(void);
RX8025T_StatusTypeDef RX8025T_ClearUpdateFlag(void);
RX8025T_StatusTypeDef RX8025T_ClearTimerFlag(void);
RX8025T_StatusTypeDef RX8025T_ClearAlarmFlag(void);
/* 其他功能 */
RX8025T_StatusTypeDef RX8025T_SetFOUT(RX8025T_FOUT_Freq freq);
RX8025T_StatusTypeDef RX8025T_GetBatteryStatus(RX8025T_BatteryStatus* status);
RX8025T_StatusTypeDef RX8025T_SetTempCompInterval(RX8025T_TempCompInterval interval);
RX8025T_StatusTypeDef RX8025T_SetRAM(uint8_t data);
RX8025T_StatusTypeDef RX8025T_GetRAM(uint8_t* data);
RX8025T_StatusTypeDef RX8025T_WriteRegister(uint8_t reg, uint8_t data);
RX8025T_StatusTypeDef RX8025T_ReadRegister(uint8_t reg, uint8_t* data);
/* 工具函数 */
uint8_t RX8025T_DecToBcd(uint8_t dec);
uint8_t RX8025T_BcdToDec(uint8_t bcd);
const char* RX8025T_GetDayOfWeekString(uint8_t day_of_week);
bool RX8025T_IsLeapYear(uint16_t year);
uint8_t RX8025T_GetDaysInMonth(uint8_t month, uint16_t year);
#ifdef __cplusplus
}
#endif
#endif /* __RX8025T_H */
[C] 纯文本查看 复制代码
#include "rx8025t.h"
#include <stdio.h>
#include <string.h>
#define RX8025T_I2C_TIMEOUT 500
#define RX8025T_UPDATE_TIMEOUT 1000
/* 全局句柄 */
static I2C_HandleTypeDef* rx8025t_hi2c = NULL;
/* 静态函数声明 */
static uint8_t DayOfWeekToRegister(uint8_t day_of_week);
static uint8_t RegisterToDayOfWeek(uint8_t reg_value);
static RX8025T_StatusTypeDef RX8025T_I2C_Check(void);
static RX8025T_StatusTypeDef RX8025T_ReadBytes(uint8_t reg, uint8_t* data, uint16_t len);
static RX8025T_StatusTypeDef RX8025T_WriteBytes(uint8_t reg, uint8_t* data, uint16_t len);
static bool IsTimeValid(RX8025T_TimeTypeDef* time);
/* 初始化函数 - 修正版 */
RX8025T_StatusTypeDef RX8025T_Init(I2C_HandleTypeDef* hi2c)
{
uint8_t flag_reg = 0;
uint8_t control_reg = 0;
if (hi2c == NULL)
{
return RX8025T_ERROR_INVALID;
}
rx8025t_hi2c = hi2c;
printf("[RX8025T] Initializing with I2C address: 0x%02X\n", RX8025T_I2C_ADDR_HAL);
/* 检查I2C通信 - 使用简单的寄存器读取 */
if (RX8025T_ReadRegister(0x00, &flag_reg) != RX8025T_OK)
{
printf("[RX8025T] Error: I2C communication failed\n");
rx8025t_hi2c = NULL;
return RX8025T_ERROR_I2C;
}
printf("[RX8025T] I2C communication OK, SEC register: 0x%02X\n", flag_reg);
/* 读取标志寄存器 */
if (RX8025T_ReadRegister(RX8025T_REG_FLAG, &flag_reg) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
printf("[RX8025T] Flag register: 0x%02X\n", flag_reg);
/* 检查电压低标志 */
if (flag_reg & RX8025T_FLAG_VLF)
{
printf("[RX8025T] Warning: Voltage low, reinitializing RTC\n");
/* 电压低,需要重新初始化 */
RX8025T_TimeTypeDef default_time = {
.year = 26, /* 2026年 */
.month = 1, /* 1月 */
.date = 1, /* 1日 */
.day_of_week = RX8025T_THURSDAY, /* 2026-1-1是星期四 */
.hour = 0, /* 0时 */
.minute = 0, /* 0分 */
.second = 0 /* 0秒 */
};
if (RX8025T_SetTime(&default_time) != RX8025T_OK)
{
return RX8025T_ERROR;
}
printf("[RX8025T] RTC initialized with default time\n");
}
/* 清除所有中断标志 */
if (RX8025T_ClearAllInterruptFlags() != RX8025T_OK)
{
return RX8025T_ERROR;
}
/* 设置控制寄存器默认值 */
if (RX8025T_ReadRegister(RX8025T_REG_CONTROL, &control_reg) != RX8025T_OK)
{
return RX8025T_ERROR;
}
/* 设置温度补偿间隔为2.0秒,禁用所有中断 */
control_reg &= 0x3F; /* 清空高2位 */
control_reg |= RX8025T_TCS_2_0S; /* 01000000b */
control_reg &= ~(RX8025T_CONTR_UIE | RX8025T_CONTR_TIE | RX8025T_CONTR_AIE);
if (RX8025T_WriteRegister(RX8025T_REG_CONTROL, control_reg) != RX8025T_OK)
{
return RX8025T_ERROR;
}
/* 设置扩展寄存器默认值 */
if (RX8025T_WriteRegister(RX8025T_REG_EXTEN, 0x00) != RX8025T_OK)
{
return RX8025T_ERROR;
}
printf("[RX8025T] Initialization completed successfully\n");
return RX8025T_OK;
}
/* 反初始化 */
RX8025T_StatusTypeDef RX8025T_DeInit(void)
{
if (rx8025t_hi2c == NULL)
{
return RX8025T_ERROR_INVALID;
}
/* 禁用所有中断 */
uint8_t control_reg = 0;
if (RX8025T_ReadRegister(RX8025T_REG_CONTROL, &control_reg) == RX8025T_OK)
{
control_reg &= ~(RX8025T_CONTR_UIE | RX8025T_CONTR_TIE | RX8025T_CONTR_AIE);
RX8025T_WriteRegister(RX8025T_REG_CONTROL, control_reg);
}
rx8025t_hi2c = NULL;
return RX8025T_OK;
}
/* 检查设备是否就绪 */
bool RX8025T_IsReady(void)
{
if (rx8025t_hi2c == NULL || rx8025t_hi2c->State != HAL_I2C_STATE_READY)
{
return false;
}
/* 尝试读取设备ID或固定寄存器 */
uint8_t test_byte = 0;
if (RX8025T_ReadRegister(RX8025T_REG_SEC, &test_byte) != RX8025T_OK)
{
return false;
}
return true;
}
/* 软复位 */
RX8025T_StatusTypeDef RX8025T_Reset(void)
{
uint8_t control_reg = 0;
/* 读取控制寄存器 */
if (RX8025T_ReadRegister(RX8025T_REG_CONTROL, &control_reg) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
/* 设置复位位 */
control_reg |= RX8025T_CONTR_RESET;
/* 写入复位命令 */
if (RX8025T_WriteRegister(RX8025T_REG_CONTROL, control_reg) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
/* 等待复位完成 */
HAL_Delay(10);
/* 清除复位位 */
control_reg &= ~RX8025T_CONTR_RESET;
if (RX8025T_WriteRegister(RX8025T_REG_CONTROL, control_reg) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
HAL_Delay(10);
return RX8025T_OK;
}
/* 获取当前时间 */
RX8025T_StatusTypeDef RX8025T_GetTime(RX8025T_TimeTypeDef* time)
{
uint8_t buffer[7] = {0};
if (time == NULL)
{
return RX8025T_ERROR_INVALID;
}
if (RX8025T_I2C_Check() != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
/* 读取时间寄存器 */
if (RX8025T_ReadBytes(RX8025T_REG_SEC, buffer, sizeof(buffer)) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
/* 解析时间数据 */
time->second = RX8025T_BcdToDec(buffer[0] & 0x7F);
time->minute = RX8025T_BcdToDec(buffer[1] & 0x7F);
time->hour = RX8025T_BcdToDec(buffer[2] & 0x3F);
time->day_of_week = RegisterToDayOfWeek(buffer[3] & 0x07);
time->date = RX8025T_BcdToDec(buffer[4] & 0x3F);
time->month = RX8025T_BcdToDec(buffer[5] & 0x1F);
time->year = RX8025T_BcdToDec(buffer[6]);
return RX8025T_OK;
}
/* 设置时间 */
RX8025T_StatusTypeDef RX8025T_SetTime(RX8025T_TimeTypeDef* time)
{
uint8_t buffer[7];
if (time == NULL || !IsTimeValid(time))
{
return RX8025T_ERROR;
}
/* 准备BCD时间数据 */
buffer[0] = ((time->second / 10) << 4) | (time->second % 10);
buffer[1] = ((time->minute / 10) << 4) | (time->minute % 10);
buffer[2] = ((time->hour / 10) << 4) | (time->hour % 10);
buffer[3] = 1 << time->day_of_week; /* 星期位映射 */
buffer[4] = ((time->date / 10) << 4) | (time->date % 10);
buffer[5] = ((time->month / 10) << 4) | (time->month % 10);
buffer[6] = ((time->year / 10) << 4) | (time->year % 10);
/* 清除STOP位(确保时钟运行) */
buffer[0] &= 0x7F;
/* 写入时间 */
return RX8025T_WriteBytes(RX8025T_REG_SEC, buffer, 7);
}
/* 验证时间有效性 */
bool RX8025T_ValidateTime(RX8025T_TimeTypeDef* time)
{
if (time == NULL)
{
return false;
}
/* 检查秒 */
if (time->second > 59)
{
return false;
}
/* 检查分 */
if (time->minute > 59)
{
return false;
}
/* 检查时 */
if (time->hour > 23)
{
return false;
}
/* 检查星期 */
if (time->day_of_week > 6)
{
return false;
}
/* 检查日期 */
if (time->date < 1 || time->date > 31)
{
return false;
}
/* 检查月份 */
if (time->month < 1 || time->month > 12)
{
return false;
}
/* 检查年份 */
if (time->year > 99)
{
return false;
}
/* 检查特定月份的天数 */
uint8_t max_days = RX8025T_GetDaysInMonth(time->month, 2000 + time->year);
if (time->date > max_days)
{
return false;
}
return true;
}
/* 等待更新完成 */
RX8025T_StatusTypeDef RX8025T_WaitUpdate(uint32_t timeout_ms)
{
uint32_t tickstart = HAL_GetTick();
uint8_t flag_reg = 0;
do
{
if (RX8025T_ReadRegister(RX8025T_REG_FLAG, &flag_reg) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
if ((flag_reg & RX8025T_FLAG_UF) == 0)
{
return RX8025T_OK;
}
if (timeout_ms > 0 && (HAL_GetTick() - tickstart) > timeout_ms)
{
return RX8025T_ERROR_TIMEOUT;
}
HAL_Delay(1);
}
while (1);
}
/* 使能更新时间中断 */
RX8025T_StatusTypeDef RX8025T_EnableUpdateInterrupt(bool enable, bool per_second)
{
uint8_t extreg = 0;
uint8_t control = 0;
if (RX8025T_I2C_Check() != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
/* 配置扩展寄存器 */
if (RX8025T_ReadRegister(RX8025T_REG_EXTEN, &extreg) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
if (per_second)
{
extreg &= ~RX8025T_EXTEN_USEL; /* 秒更新 */
}
else
{
extreg |= RX8025T_EXTEN_USEL; /* 分更新 */
}
if (RX8025T_WriteRegister(RX8025T_REG_EXTEN, extreg) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
/* 配置控制寄存器 */
if (RX8025T_ReadRegister(RX8025T_REG_CONTROL, &control) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
if (enable)
{
control |= RX8025T_CONTR_UIE;
}
else
{
control &= ~RX8025T_CONTR_UIE;
}
if (RX8025T_WriteRegister(RX8025T_REG_CONTROL, control) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
/* 清除更新标志 */
if (enable)
{
RX8025T_ClearUpdateFlag();
}
return RX8025T_OK;
}
/* 使能定时器中断 */
RX8025T_StatusTypeDef RX8025T_EnableTimerInterrupt(bool enable, RX8025T_TimerSource source, uint16_t count)
{
uint8_t extreg = 0;
uint8_t control = 0;
if (RX8025T_I2C_Check() != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
/* 设置计数值 */
if (enable && count > 0)
{
if (RX8025T_WriteRegister(RX8025T_REG_TIM_CNT0, (uint8_t)(count & 0xFF)) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
if (RX8025T_WriteRegister(RX8025T_REG_TIM_CNT1, (uint8_t)((count >> 8) & 0x0F)) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
}
/* 配置扩展寄存器 */
if (RX8025T_ReadRegister(RX8025T_REG_EXTEN, &extreg) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
extreg &= ~(RX8025T_EXTEN_TSEL0 | RX8025T_EXTEN_TSEL1);
extreg |= (source & 0x03);
if (enable)
{
extreg |= RX8025T_EXTEN_TE;
}
else
{
extreg &= ~RX8025T_EXTEN_TE;
}
if (RX8025T_WriteRegister(RX8025T_REG_EXTEN, extreg) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
/* 配置控制寄存器 */
if (RX8025T_ReadRegister(RX8025T_REG_CONTROL, &control) != RX8025T_OK)
{
return RX8025T_ERROR;
}
if (enable)
{
control |= RX8025T_CONTR_TIE;
}
else
{
control &= ~RX8025T_CONTR_TIE;
}
if (RX8025T_WriteRegister(RX8025T_REG_CONTROL, control) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
/* 清除定时器标志 */
if (enable)
{
RX8025T_ClearTimerFlag();
}
return RX8025T_OK;
}
/* 使能报警中断 */
RX8025T_StatusTypeDef RX8025T_EnableAlarmInterrupt(bool enable, RX8025T_AlarmTypeDef* alarm)
{
uint8_t extreg = 0;
uint8_t control = 0;
if (RX8025T_I2C_Check() != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
if (enable && alarm == NULL)
{
return RX8025T_ERROR_INVALID;
}
/* 设置报警时间 */
if (enable)
{
/* 设置星期/日寄存器 */
if (alarm->mode == RX8025T_ALARM_DAY_MODE)
{ /* 日模式 */
if (alarm->alarm_day_or_week.day & RX8025T_ALARM_AE_FLAG)
{
/* 每天 */
if (RX8025T_WriteRegister(RX8025T_REG_WEEK_DAY_ALARM, RX8025T_ALARM_AE_FLAG) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
}
else if (alarm->alarm_day_or_week.day > 0 && alarm->alarm_day_or_week.day <= 31)
{
/* 特定日期 */
if (RX8025T_WriteRegister(RX8025T_REG_WEEK_DAY_ALARM, RX8025T_DecToBcd(alarm->alarm_day_or_week.day)) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
}
else
{
return RX8025T_ERROR_INVALID;
}
}
else if (alarm->mode == RX8025T_ALARM_WEEK_MODE)
{ /* 周模式 */
if (alarm->alarm_day_or_week.week > 0 && alarm->alarm_day_or_week.week <= 0x7F)
{
if (RX8025T_WriteRegister(RX8025T_REG_WEEK_DAY_ALARM, alarm->alarm_day_or_week.week) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
}
else
{
return RX8025T_ERROR_INVALID;
}
}
else
{
return RX8025T_ERROR_INVALID;
}
/* 设置小时寄存器 */
if (alarm->hour & RX8025T_ALARM_AE_FLAG)
{
/* 每小时 */
if (RX8025T_WriteRegister(RX8025T_REG_HOUR_ALARM, RX8025T_ALARM_AE_FLAG) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
}
else if (alarm->hour < 24)
{
/* 特定小时 */
if (RX8025T_WriteRegister(RX8025T_REG_HOUR_ALARM, RX8025T_DecToBcd(alarm->hour)) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
}
else
{
return RX8025T_ERROR_INVALID;
}
/* 设置分钟寄存器 */
if (alarm->minute & RX8025T_ALARM_AE_FLAG)
{
/* 每分钟 */
if (RX8025T_WriteRegister(RX8025T_REG_MIN_ALARM, RX8025T_ALARM_AE_FLAG) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
}
else if (alarm->minute < 60)
{
/* 特定分钟 */
if (RX8025T_WriteRegister(RX8025T_REG_MIN_ALARM, RX8025T_DecToBcd(alarm->minute)) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
}
else
{
return RX8025T_ERROR_INVALID;
}
}
/* 配置扩展寄存器 */
if (RX8025T_ReadRegister(RX8025T_REG_EXTEN, &extreg) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
if (enable)
{
if (alarm->mode == RX8025T_ALARM_DAY_MODE)
{
extreg |= RX8025T_EXTEN_WADA; /* 日模式 */
}
else
{
extreg &= ~RX8025T_EXTEN_WADA; /* 周模式 */
}
}
if (RX8025T_WriteRegister(RX8025T_REG_EXTEN, extreg) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
/* 配置控制寄存器 */
if (RX8025T_ReadRegister(RX8025T_REG_CONTROL, &control) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
if (enable)
{
control |= RX8025T_CONTR_AIE;
}
else
{
control &= ~RX8025T_CONTR_AIE;
}
if (RX8025T_WriteRegister(RX8025T_REG_CONTROL, control) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
/* 清除报警标志 */
if (enable)
{
RX8025T_ClearAlarmFlag();
}
return RX8025T_OK;
}
/* 获取中断标志 */
RX8025T_StatusTypeDef RX8025T_GetInterruptFlags(uint8_t* flags)
{
if (flags == NULL)
{
return RX8025T_ERROR_INVALID;
}
if (RX8025T_I2C_Check() != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
return RX8025T_ReadRegister(RX8025T_REG_FLAG, flags);
}
/* 清除所有中断标志 */
RX8025T_StatusTypeDef RX8025T_ClearAllInterruptFlags(void)
{
if (RX8025T_I2C_Check() != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
/* 写入0清除所有标志位 */
return RX8025T_WriteRegister(RX8025T_REG_FLAG, 0x00);
}
/* 清除更新标志 */
RX8025T_StatusTypeDef RX8025T_ClearUpdateFlag(void)
{
uint8_t flag_reg = 0;
if (RX8025T_ReadRegister(RX8025T_REG_FLAG, &flag_reg) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
flag_reg &= ~RX8025T_FLAG_UF;
return RX8025T_WriteRegister(RX8025T_REG_FLAG, flag_reg);
}
/* 清除定时器标志 */
RX8025T_StatusTypeDef RX8025T_ClearTimerFlag(void)
{
uint8_t flag_reg = 0;
if (RX8025T_ReadRegister(RX8025T_REG_FLAG, &flag_reg) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
flag_reg &= ~RX8025T_FLAG_TF;
return RX8025T_WriteRegister(RX8025T_REG_FLAG, flag_reg);
}
/* 清除报警标志 */
RX8025T_StatusTypeDef RX8025T_ClearAlarmFlag(void)
{
uint8_t flag_reg = 0;
if (RX8025T_ReadRegister(RX8025T_REG_FLAG, &flag_reg) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
flag_reg &= ~RX8025T_FLAG_AF;
return RX8025T_WriteRegister(RX8025T_REG_FLAG, flag_reg);
}
/* 设置FOUT输出频率 */
RX8025T_StatusTypeDef RX8025T_SetFOUT(RX8025T_FOUT_Freq freq)
{
uint8_t extreg = 0;
if (freq > 3)
{
return RX8025T_ERROR_INVALID;
}
if (RX8025T_ReadRegister(RX8025T_REG_EXTEN, &extreg) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
extreg &= ~(RX8025T_EXTEN_FSEL0 | RX8025T_EXTEN_FSEL1);
extreg |= ((freq & 0x03) << 2);
return RX8025T_WriteRegister(RX8025T_REG_EXTEN, extreg);
}
/* 获取电池状态 */
RX8025T_StatusTypeDef RX8025T_GetBatteryStatus(RX8025T_BatteryStatus* status)
{
uint8_t flag_reg = 0;
if (status == NULL)
{
return RX8025T_ERROR_INVALID;
}
if (RX8025T_I2C_Check() != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
if (RX8025T_ReadRegister(RX8025T_REG_FLAG, &flag_reg) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
status->voltage_low = (flag_reg & RX8025T_FLAG_VLF) ? true : false;
status->voltage_detected = (flag_reg & RX8025T_FLAG_VDET) ? true : false;
return RX8025T_OK;
}
/* 设置温度补偿间隔 */
RX8025T_StatusTypeDef RX8025T_SetTempCompInterval(RX8025T_TempCompInterval interval)
{
uint8_t control_reg = 0;
if (RX8025T_ReadRegister(RX8025T_REG_CONTROL, &control_reg) != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
control_reg &= 0x3F; /* 清空CSEL位 */
control_reg |= interval;
return RX8025T_WriteRegister(RX8025T_REG_CONTROL, control_reg);
}
/* 设置RAM数据 */
RX8025T_StatusTypeDef RX8025T_SetRAM(uint8_t data)
{
return RX8025T_WriteRegister(RX8025T_REG_RAM, data);
}
/* 读取RAM数据 */
RX8025T_StatusTypeDef RX8025T_GetRAM(uint8_t* data)
{
if (data == NULL)
{
return RX8025T_ERROR_INVALID;
}
return RX8025T_ReadRegister(RX8025T_REG_RAM, data);
}
/* 写入寄存器 */
RX8025T_StatusTypeDef RX8025T_WriteRegister(uint8_t reg, uint8_t data)
{
uint8_t buffer[2];
if (RX8025T_I2C_Check() != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
buffer[0] = reg;
buffer[1] = data;
if (HAL_I2C_Master_Transmit(rx8025t_hi2c, RX8025T_I2C_ADDR_HAL, buffer, 2, RX8025T_I2C_TIMEOUT) != HAL_OK)
{
return RX8025T_ERROR_I2C;
}
return RX8025T_OK;
}
/* 读取寄存器 */
RX8025T_StatusTypeDef RX8025T_ReadRegister(uint8_t reg, uint8_t* data)
{
if (data == NULL)
{
return RX8025T_ERROR_INVALID;
}
if (RX8025T_I2C_Check() != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
/* 发送寄存器地址 */
if (HAL_I2C_Master_Transmit(rx8025t_hi2c, RX8025T_I2C_ADDR_HAL, ®, 1, RX8025T_I2C_TIMEOUT) != HAL_OK)
{
return RX8025T_ERROR_I2C;
}
/* 读取数据 */
if (HAL_I2C_Master_Receive(rx8025t_hi2c, RX8025T_I2C_ADDR_HAL, data, 1, RX8025T_I2C_TIMEOUT) != HAL_OK)
{
return RX8025T_ERROR_I2C;
}
return RX8025T_OK;
}
/* 十进制转BCD */
uint8_t RX8025T_DecToBcd(uint8_t dec)
{
return ((dec / 10) << 4) | (dec % 10);
}
/* BCD转十进制 */
uint8_t RX8025T_BcdToDec(uint8_t bcd)
{
return ((bcd >> 4) * 10) + (bcd & 0x0F);
}
/* 获取星期字符串 */
const char* RX8025T_GetDayOfWeekString(uint8_t day_of_week)
{
static const char* days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
if (day_of_week > 6)
{
return "Invalid";
}
return days[day_of_week];
}
/* 判断是否为闰年 */
bool RX8025T_IsLeapYear(uint16_t year)
{
return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0));
}
/* 获取月份天数 */
uint8_t RX8025T_GetDaysInMonth(uint8_t month, uint16_t year)
{
static const uint8_t days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (month < 1 || month > 12)
{
return 0;
}
if (month == 2 && RX8025T_IsLeapYear(year))
{
return 29;
}
return days_in_month[month - 1];
}
/* 星期转寄存器值 */
static uint8_t DayOfWeekToRegister(uint8_t day_of_week)
{
if (day_of_week > 6)
{
return 0x01; /* 默认周日 */
}
return (1 << day_of_week);
}
/* 寄存器值转星期 */
static uint8_t RegisterToDayOfWeek(uint8_t reg_value)
{
reg_value &= 0x07; /* 只取低3位 */
switch (reg_value)
{
case 0x01:
return 0; /* 周日 */
case 0x02:
return 1; /* 周一 */
case 0x04:
return 2; /* 周二 */
case 0x08:
return 3; /* 周三 */
case 0x10:
return 4; /* 周四 */
case 0x20:
return 5; /* 周五 */
case 0x40:
return 6; /* 周六 */
default:
return 0; /* 默认周日 */
}
}
/* 检查I2C状态 */
static RX8025T_StatusTypeDef RX8025T_I2C_Check(void)
{
if (rx8025t_hi2c == NULL)
{
return RX8025T_ERROR;
}
if (rx8025t_hi2c->State == HAL_I2C_STATE_BUSY || rx8025t_hi2c->State == HAL_I2C_STATE_BUSY_TX || rx8025t_hi2c->State == HAL_I2C_STATE_BUSY_RX)
{
return RX8025T_ERROR;
}
return RX8025T_OK;
}
/* 读取多个字节 */
static RX8025T_StatusTypeDef RX8025T_ReadBytes(uint8_t reg, uint8_t* data, uint16_t len)
{
if (data == NULL || len == 0)
{
return RX8025T_ERROR_INVALID;
}
if (RX8025T_I2C_Check() != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
/* 使用HAL_I2C_Mem_Read一次性读取多个寄存器 */
if (HAL_I2C_Mem_Read(rx8025t_hi2c, RX8025T_I2C_ADDR_HAL, reg, I2C_MEMADD_SIZE_8BIT, data, len, RX8025T_I2C_TIMEOUT) != HAL_OK)
{
return RX8025T_ERROR_I2C;
}
return RX8025T_OK;
}
/* 写入多个字节 */
static RX8025T_StatusTypeDef RX8025T_WriteBytes(uint8_t reg, uint8_t* data, uint16_t len)
{
if (data == NULL || len == 0)
{
return RX8025T_ERROR_INVALID;
}
if (RX8025T_I2C_Check() != RX8025T_OK)
{
return RX8025T_ERROR_I2C;
}
/* 使用HAL_I2C_Mem_Write一次性写入多个寄存器 */
if (HAL_I2C_Mem_Write(rx8025t_hi2c, RX8025T_I2C_ADDR_HAL, reg, I2C_MEMADD_SIZE_8BIT, data, len, RX8025T_I2C_TIMEOUT) != HAL_OK)
{
return RX8025T_ERROR_I2C;
}
return RX8025T_OK;
}
/* 验证时间有效性 */
static bool IsTimeValid(RX8025T_TimeTypeDef* time)
{
if (time == NULL)
{
return false;
}
/* 基本范围检查 */
if (time->second > 59 || time->minute > 59 || time->hour > 23 || time->day_of_week > 6 || time->date < 1 || time->date > 31 || time->month < 1 ||
time->month > 12 || time->year > 99)
{
return false;
}
/* 月份天数检查 */
uint8_t max_days = RX8025T_GetDaysInMonth(time->month, 2000 + time->year);
if (time->date > max_days)
{
return false;
}
return true;
}
[C] 纯文本查看 复制代码
调用:
void enter_standby_mode(void)
{
// clear flag
RX8025T_ClearAllInterruptFlags();
HAL_Delay(5);
// 重新回复GPIO
InitBoardGPIO();
// RX8025X gpio set to turn off
__PWR_OFF_ENABLE;
HAL_Delay(1);
// Delay util turn off
uint32_t d = 0;
while (1)
{
printf("d:%d\n", d++);
HAL_Delay(200);
}
}
// 休眠业务代码
if (can_enter_standby())
{
// 防止有外设还有缓存没有发送完
osDelay(3000);
// 发送一次测试完成请求
UploadACK();
// 设置下一次闹钟时间,中间调用有任何返回失败的就重启
set_next_alarm_time();
// 进入休眠模式
enter_standby_mode();
HAL_Delay(100);
}
|
|