0f7b5a87fb
登记簿、文档与代码注释里的存量字母加数字编号(N-x / S-x / T-x / E-x / A-x / 卡号) 一律改写为语义短语,净删 2,028 处引用;删除基线与待确认、并行分道方案、排期详述、 采集保护收尾 4 篇(内容已并入 docs/任务规划/README 与登记簿)。 门禁机器与三张账同批重打:check_ids.py 新增变更记录行豁免与第二根护栏 undecidable_total_ceiling;check_test_traceability.py 只加 stdout/stderr UTF-8 reconfigure(TC_RE 未动);check_cubemx_survival.py 的 --write 固定 newline=LF; id_registry / id_aliases(+19 条 retired-to-phrase)/ id_known_backlog 重打。 test/ 56 个文件同步 TC 标签语义化,其中 18 个 TU 改了 CHECK / printf 里的标签文字, 是本批唯一改变构建产物的文件集合。 为什么合成一笔、不拆四笔(实测撞闸,非偏好):pre-commit 跑钩子前会 stash 未 staged 部分,拆开后中间提交必然是「新规则 + 旧语料」——实跑可判定 85.15% < 基线 86.00%、 不可判定 1,453 > 上限 1,166,编号门禁直接拦下。编号识别面与它描述的语料只能同码移动。 实跑基线(工作区全量):754 文件 / 8,230 处编号字面量 / 可判定 7,079 = 86.01% (基线 86.0%,容差 0.1pp)/ 不可判定绝对数 1,151(上限 1,166)/ 校验 1-6 错误级 0 / 告警 = 悬空 2(App/algo/freq.c 的 S2,属 §4.4 同号不同义)+ 孤儿 50。 基线从 84.0 抬到 86.0 的理由见 docs/门禁说明/id-check.md §7.6:本批真删了 2,028 处 引用,可判定面随真实内容上升,不是把分母做小。同批新增排除 docs/硬件平台/ 语料,使 识别面少 264 处——芯片手册位号与网表料号不属编号空间(registry 有 excluded_paths_note)。 ⚠ 余量只剩 0.11pp(约 10 处)与绝对数 15 处:把「可判定的引用」改成散文会立刻撞第二 根护栏。另遗留一项:id_aliases 里 retired 的 N / S / T / A 别名没有 scope(U1~U5 有), 今后有人新写一个 A-4,校验 3 不会响,只能靠人,建议下批补 scope。 固件不变证据:115 个 .c/.h 剥注释并归一字符串后与 HEAD 逐字节全等,残留代码差异 0; App / Src / Drivers 的字符串字面量零改动。@build 0 错误 0 警告;40/40 主机套件、2,889 断言全通过;覆盖率 line 89.2% / func 92.6%;pre-commit 48 钩子 --all-files 全绿; check_doc_links --all 通过(176 文档,章节引用无法判定 0);逐字节卫生核过:14 个带 BOM 文件与 HEAD 一致、0 个 CR、0 个 U+FFFD,字符串字面量纯 ASCII。 .cubemx_survival_baseline.json 的 watchdog-module 哈希 56bf27 变 2bb051 属合法: Src/freertos.c 的 USER CODE 区内只有注释文字随编号改写,代码未变。 同批带上体积同码凭证与 RAM 台账行(@build 之后盖戳):RW_IRAM1 79,008 B / 60.3%, RW_CCM 57,376 B / 87.9%,阈值 92%。
316 lines
13 KiB
C
316 lines
13 KiB
C
/*
|
||
* 模块名称:SD2506API-G RTC 实时时钟驱动
|
||
* 模块功能:SD2506API-G 高精度温补实时时钟模块 I2C 驱动,提供时间读写、
|
||
* 温度读取、电池电压检测、ID 读取等功能
|
||
* 适用平台:STM32F407ZGT6,I2C1 接口 (PB6-SCL, PB7-SDA)
|
||
* 作者:王建锋
|
||
* 创建日期:2026-07-17
|
||
* 修改记录:
|
||
* 2026-07-17 王建锋 创建初始版本,参考 SD2506API-G Ver2.0 手册
|
||
*/
|
||
|
||
#ifndef SD2506_H
|
||
#define SD2506_H
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
#include "main.h"
|
||
|
||
/* ======================== I2C 地址 ======================== */
|
||
|
||
/*
|
||
* SD2506API-G 7位器件地址: 0x32
|
||
* HAL库使用8位地址: 写 0x64, 读 0x65
|
||
*/
|
||
#define SD2506_I2C_ADDR 0x32U
|
||
#define SD2506_I2C_ADDR_WRITE 0x64U
|
||
#define SD2506_I2C_ADDR_READ 0x65U
|
||
|
||
/* ======================== 寄存器地址定义 ======================== */
|
||
|
||
/* 实时时钟寄存器 (00H~06H) */
|
||
#define SD2506_REG_SEC 0x00U /* 秒 00~59 BCD */
|
||
#define SD2506_REG_MIN 0x01U /* 分 00~59 BCD */
|
||
#define SD2506_REG_HOUR 0x02U /* 时 00~23 BCD, bit7=12/24 */
|
||
#define SD2506_REG_WEEK 0x03U /* 星期 00~06 BCD */
|
||
#define SD2506_REG_DAY 0x04U /* 日 01~31 BCD */
|
||
#define SD2506_REG_MON 0x05U /* 月 01~12 BCD */
|
||
#define SD2506_REG_YEAR 0x06U /* 年 00~99 BCD */
|
||
|
||
/* 报警寄存器 (07H~0EH) */
|
||
#define SD2506_REG_AL_SEC 0x07U /* 秒报警 */
|
||
#define SD2506_REG_AL_MIN 0x08U /* 分报警 */
|
||
#define SD2506_REG_AL_HOUR 0x09U /* 时报警 */
|
||
#define SD2506_REG_AL_WEEK 0x0AU /* 星期报警 */
|
||
#define SD2506_REG_AL_DAY 0x0BU /* 日报警 */
|
||
#define SD2506_REG_AL_MON 0x0CU /* 月报警 */
|
||
#define SD2506_REG_AL_YEAR 0x0DU /* 年报警 */
|
||
#define SD2506_REG_AL_EN 0x0EU /* 报警允许寄存器 */
|
||
|
||
/* 控制寄存器 */
|
||
#define SD2506_REG_CTR1 0x0FU /* 控制寄存器1 */
|
||
#define SD2506_REG_CTR2 0x10U /* 控制寄存器2 */
|
||
#define SD2506_REG_CTR3 0x11U /* 控制寄存器3 */
|
||
|
||
/* 倒计时寄存器 (13H~15H) */
|
||
#define SD2506_REG_CNT0 0x13U /* 倒计时字节0 (LSB) */
|
||
#define SD2506_REG_CNT1 0x14U /* 倒计时字节1 */
|
||
#define SD2506_REG_CNT2 0x15U /* 倒计时字节2 (MSB) */
|
||
|
||
/* 温度寄存器 */
|
||
#define SD2506_REG_TEMP 0x16U /* 温度值 (bit7=符号位) */
|
||
#define SD2506_REG_AGTC 0x17U /* IIC控制寄存器 AGTC */
|
||
#define SD2506_REG_CHARGE 0x18U /* 充电选择寄存器 */
|
||
#define SD2506_REG_CTR4 0x19U /* 扩展控制寄存器 CTR4 */
|
||
#define SD2506_REG_CTR5 0x1AU /* 控制寄存器 CTR5 */
|
||
#define SD2506_REG_BAT_VAL 0x1BU /* 电池电压低8位 */
|
||
|
||
/* 温度报警及历史 */
|
||
#define SD2506_REG_TEMP_AL 0x1CU /* 低温报警温度值 */
|
||
#define SD2506_REG_TEMP_AH 0x1DU /* 高温报警温度值 */
|
||
#define SD2506_REG_TEMP_HIS_L 0x1EU /* 历史低温 */
|
||
#define SD2506_REG_TEMP_HIS_H 0x1FU /* 历史高温 */
|
||
|
||
/* 用户 SRAM (2CH~71H) */
|
||
#define SD2506_REG_SRAM_START 0x2CU
|
||
#define SD2506_REG_SRAM_END 0x71U
|
||
#define SD2506_SRAM_SIZE 70U /* 70字节 */
|
||
|
||
/* ID 码 (72H~79H) */
|
||
#define SD2506_REG_ID_START 0x72U
|
||
#define SD2506_REG_ID_END 0x79U
|
||
#define SD2506_ID_SIZE 8U /* 8字节 */
|
||
|
||
/* ======================== 控制位定义 ======================== */
|
||
|
||
/* 控制寄存器 1 (0FH):bit7=WRTC3 bit6=OSF bit5=INTAF bit4=INTDF bit3=BLF
|
||
* bit2=WRTC2 bit1=PMF bit0=RTCF(手册寄存器总表) */
|
||
#define SD2506_CTR1_INTAF (1U << 5) /* 报警中断标志 */
|
||
#define SD2506_CTR1_INTDF (1U << 4) /* 倒计时中断标志 */
|
||
#define SD2506_CTR1_BLF (1U << 3) /* 电池欠压标志 */
|
||
|
||
/* 控制寄存器 3 (11H) */
|
||
#define SD2506_CTR3_ARST (1U << 7) /* 自动复位使能(ARST=1 时读 CTR1 自动清 INTAF/INTDF/BLF) */
|
||
|
||
/* 控制寄存器 2 (10H) */
|
||
#define SD2506_CTR2_INTAE (1U << 5) /* 报警中断允许 */
|
||
#define SD2506_CTR2_INTFE (1U << 4) /* 频率中断允许 */
|
||
#define SD2506_CTR2_INTDE (1U << 3) /* 倒计时中断允许 */
|
||
#define SD2506_CTR2_IM (1U << 2) /* 中断模式: 0=单事件, 1=周期 */
|
||
#define SD2506_CTR2_INTS1 (1U << 1) /* INT输出选择 bit1 */
|
||
#define SD2506_CTR2_INTS0 (1U << 0) /* INT输出选择 bit0 */
|
||
|
||
/* 报警允许寄存器 (0EH) */
|
||
#define SD2506_AL_EN_EAY (1U << 6) /* 年报警允许 */
|
||
#define SD2506_AL_EN_EAMO (1U << 5) /* 月报警允许 */
|
||
#define SD2506_AL_EN_EAD (1U << 4) /* 日报警允许 */
|
||
#define SD2506_AL_EN_EAW (1U << 3) /* 星期报警允许 */
|
||
#define SD2506_AL_EN_EAH (1U << 2) /* 时报警允许 */
|
||
#define SD2506_AL_EN_EAMN (1U << 1) /* 分报警允许 */
|
||
#define SD2506_AL_EN_EAS (1U << 0) /* 秒报警允许 */
|
||
|
||
/* 24/12小时制位 */
|
||
#define SD2506_HOUR_24 (1U << 7) /* bit7=1 表示24小时制 */
|
||
|
||
/* ======================== 充电配置 ======================== */
|
||
|
||
/* 充电寄存器 (18H) 位定义(手册 §4.8):
|
||
* Bit7=EN_Charge(充电允许,复位 0=禁止);
|
||
* Bit1=Charge1、Bit0=Charge0:00=2K / 01=10K / 10=5K / 11=断开(复位态) */
|
||
|
||
#define SD2506_CHARGE_EN (1U << 7) /* EN_Charge: 充电允许 (Bit7) */
|
||
#define SD2506_CHARGE_2K (0U) /* 2K 电阻: Charge1=0, Charge0=0 */
|
||
#define SD2506_CHARGE_10K (1U << 0) /* 10K 电阻: Charge1=0, Charge0=1 */
|
||
#define SD2506_CHARGE_5K (1U << 1) /* 5K 电阻: Charge1=1, Charge0=0 */
|
||
#define SD2506_CHARGE_DISCON (0x03U) /* 断开: Charge1=1, Charge0=1(复位态) */
|
||
#define SD2506_CHARGE_INIT_VALUE (0x82U) /* 上电目标值: EN_Charge|5K = 出厂 82H */
|
||
|
||
/* ======================== 写保护配置 ======================== */
|
||
|
||
/* 写允许窗口内写 0FH 的建议值: 0xFF(手册 L396:WRTC 位只能保持 1,
|
||
* 0FH 其余位均为标志位) */
|
||
#define SD2506_CTR1_WRITE_ON 0xFFU
|
||
/* 写禁止过渡时 0FH 的建议值: 0x7B(WRTC2/WRTC3=0、标志位 1;WRTC1 在
|
||
* CTR2 需另行清除;ARST 在 CTR3 与本寄存器无关) */
|
||
#define SD2506_CTR1_WRITE_OFF 0x7BU
|
||
|
||
/* ======================== 返回值定义 ========================
|
||
* 本模块**不再自带错误码**(2026-10-23):统一走 Drivers/BSP/bsp_err.h。
|
||
* 旧码映射 —— SD2506_OK → BSP_OK;SD2506_ERROR(参数类)→ BSP_ERR_PARAM;
|
||
* SD2506_I2C_ERROR → BSP_ERR_IO,其中 I2C 超时刻意单独归成 **BSP_ERR_TIMEOUT
|
||
* (可重试)**:旧码把"总线上没人应答"和"超时"混成一个 -2,调用方没法规避。
|
||
* 三处旧宏已**删除而不是留别名**——留着就还能被新代码继续用,等于把迁移洗掉。
|
||
*/
|
||
|
||
#include "bsp_err.h"
|
||
|
||
/* ======================== 超时时间 ======================== */
|
||
|
||
#define SD2506_I2C_TIMEOUT_MS 100
|
||
|
||
/* ======================== 数据结构 ======================== */
|
||
|
||
/*
|
||
* RTC 时间日期结构体
|
||
* year: 2000~2099
|
||
* month: 1~12
|
||
* day: 1~31
|
||
* hour: 0~23 (24小时制)
|
||
* minute: 0~59
|
||
* second: 0~59
|
||
* week: 0~6 (0=星期天, 1=星期一, ..., 6=星期六)
|
||
*/
|
||
typedef struct {
|
||
uint16_t year;
|
||
uint8_t month;
|
||
uint8_t day;
|
||
uint8_t hour;
|
||
uint8_t minute;
|
||
uint8_t second;
|
||
uint8_t week;
|
||
} sd2506_time_t;
|
||
|
||
/* ======================== 函数声明 ======================== */
|
||
|
||
/*
|
||
* 函数功能:初始化 SD2506API-G RTC
|
||
* 入口参数:无
|
||
* 返回值:BSP_OK - 成功;BSP_ERR_IO - I2C 失败或回读校验不符;BSP_ERR_TIMEOUT - I2C 超时(可重试)
|
||
* 限定条件:CubeMX 已完成 I2C1 初始化
|
||
* 函数说明:1. 读取芯片 ID 验证通信
|
||
* 2. 充电寄存器 18H 回读校验(出厂 82H 非易失),值漂移时经写允许
|
||
* 窗口重置并回读验证
|
||
* 3. 上电即写禁止态(WRTC 全 0),无需再写 0FH
|
||
*/
|
||
bsp_err_t sd2506_init(void);
|
||
|
||
/*
|
||
* 函数功能:设置 RTC 时间日期
|
||
* 入口参数:time - 时间结构体指针,包含要设置的时间
|
||
* 返回值:BSP_OK - 成功;BSP_ERR_IO - I2C 通信失败;BSP_ERR_TIMEOUT - I2C 超时(可重试)
|
||
* 限定条件:sd2506_init() 已调用
|
||
* 函数说明:1. 先开写保护
|
||
* 2. 一次性写入 7 字节时间数据 (00H~06H)
|
||
* 3. 关闭写保护
|
||
* 注意:不可单独写某一个时间寄存器
|
||
*/
|
||
bsp_err_t sd2506_set_time(const sd2506_time_t *p_time);
|
||
|
||
/*
|
||
* 函数功能:读取 RTC 时间日期
|
||
* 入口参数:time - 时间结构体指针,用于存储读取结果
|
||
* 返回值:BSP_OK - 成功;BSP_ERR_IO - I2C 通信失败;BSP_ERR_TIMEOUT - I2C 超时(可重试)
|
||
* 限定条件:sd2506_init() 已调用
|
||
* 函数说明:1. 一次读取 7 字节时间数据 (00H~06H)
|
||
* 2. BCD 转十进制
|
||
* 3. 屏蔽小时 bit7 (12/24标志位)
|
||
*/
|
||
bsp_err_t sd2506_get_time(sd2506_time_t *p_time);
|
||
|
||
/*
|
||
* 函数功能:读取芯片内部温度
|
||
* 入口参数:temp - 温度输出指针 (整数部分, 有符号)
|
||
* 返回值:BSP_OK - 成功;BSP_ERR_IO - I2C 通信失败;BSP_ERR_TIMEOUT - I2C 超时(可重试)
|
||
* 限定条件:sd2506_init() 已调用
|
||
* 函数说明:读取 16H 寄存器,bit7 为符号位,范围 -40~+85
|
||
*/
|
||
bsp_err_t sd2506_get_temperature(int8_t *p_temp);
|
||
|
||
/*
|
||
* 函数功能:读取电池电压 (毫伏)
|
||
* 入口参数:voltage - 电压输出指针 (单位: mV)
|
||
* 返回值:BSP_OK - 成功;BSP_ERR_IO - I2C 通信失败;BSP_ERR_TIMEOUT - I2C 超时(可重试)
|
||
* 限定条件:sd2506_init() 已调用
|
||
* 函数说明:1. 读取 1AH bit7 (BAT8_VAL) 和 1BH (BAT_VL)
|
||
* 2. 组合 9 位数据得到电压值 (如 0x135 = 309 = 3.09V)
|
||
*/
|
||
bsp_err_t sd2506_get_battery_voltage(uint16_t *p_voltage);
|
||
|
||
/*
|
||
* 函数功能:读取芯片 8 字节 ID
|
||
* 入口参数:id - 8 字节输出缓冲区
|
||
* 返回值:BSP_OK - 成功;BSP_ERR_IO - I2C 通信失败;BSP_ERR_TIMEOUT - I2C 超时(可重试)
|
||
* 限定条件:sd2506_init() 已调用
|
||
* 函数说明:读取 72H~79H 共 8 字节唯一 ID
|
||
*/
|
||
bsp_err_t sd2506_get_id(uint8_t p_id[8]);
|
||
|
||
/*
|
||
* 函数功能:读取用户 SRAM 数据
|
||
* 入口参数:addr - SRAM 起始地址 (0~69)
|
||
* buf - 数据输出缓冲区
|
||
* len - 读取长度 (1~70)
|
||
* 返回值:BSP_OK - 成功;BSP_ERR_PARAM - 参数错误;BSP_ERR_IO - I2C 通信失败;
|
||
* BSP_ERR_TIMEOUT - I2C 超时(可重试)
|
||
* 限定条件:sd2506_init() 已调用
|
||
* 函数说明:SRAM 地址范围 0~69,对应寄存器 2CH~71H
|
||
*/
|
||
bsp_err_t sd2506_read_sram(uint8_t addr, uint8_t *p_buf, uint8_t len);
|
||
|
||
/*
|
||
* 函数功能:写入用户 SRAM 数据
|
||
* 入口参数:addr - SRAM 起始地址 (0~69)
|
||
* buf - 数据输入缓冲区
|
||
* len - 写入长度 (1~70)
|
||
* 返回值:BSP_OK - 成功;BSP_ERR_PARAM - 参数错误;BSP_ERR_IO - I2C 通信失败;
|
||
* BSP_ERR_TIMEOUT - I2C 超时(可重试)
|
||
* 限定条件:sd2506_init() 已调用
|
||
* 函数说明:SRAM 地址范围 0~69,对应寄存器 2CH~71H
|
||
* SRAM 无需开写保护即可写入
|
||
*/
|
||
bsp_err_t sd2506_write_sram(uint8_t addr, const uint8_t *p_buf, uint8_t len);
|
||
|
||
/*
|
||
* 函数功能:设置报警中断
|
||
* 入口参数:time - 报警时间结构体
|
||
* mask - 报警匹配掩码 (SD2506_AL_EN_xxx 位或组合)
|
||
* 返回值:BSP_OK - 成功;BSP_ERR_IO - I2C 通信失败;BSP_ERR_TIMEOUT - I2C 超时(可重试)
|
||
* 限定条件:sd2506_init() 已调用
|
||
* 函数说明:1. 开写保护
|
||
* 2. 写入报警寄存器 (07H~0EH)
|
||
* 3. 使能报警中断 INTAE
|
||
* 4. 关写保护
|
||
*/
|
||
bsp_err_t sd2506_set_alarm(const sd2506_time_t *p_time, uint8_t mask);
|
||
|
||
/*
|
||
* 函数功能:清除报警中断标志 INTAF
|
||
* 入口参数:无
|
||
* 返回值:BSP_OK - 成功;BSP_ERR_IO - I2C 通信失败;BSP_ERR_TIMEOUT - I2C 超时(可重试)
|
||
* 限定条件:sd2506_init() 已调用
|
||
* 函数说明:ARST(CTR3 bit7) 未启用,读 CTR1 不清 INTAF;本函数经写允许窗口
|
||
* 手动写 CTR1 将 INTAF 置 0
|
||
*/
|
||
bsp_err_t sd2506_clear_alarm(void);
|
||
|
||
/*
|
||
* 函数功能:读取当前 0FH 控制寄存器1 状态
|
||
* 入口参数:val - 输出值指针
|
||
* 返回值:BSP_OK - 成功;BSP_ERR_IO - I2C 通信失败;BSP_ERR_TIMEOUT - I2C 超时(可重试)
|
||
*/
|
||
bsp_err_t sd2506_read_ctr1(uint8_t *p_val);
|
||
|
||
/*
|
||
* 函数功能:BCD 码转十进制
|
||
* 入口参数:bcd - BCD 码值
|
||
* 返回值:十进制值
|
||
* 函数说明:内部辅助函数
|
||
*/
|
||
uint8_t sd2506_bcd_to_dec(uint8_t bcd);
|
||
|
||
/*
|
||
* 函数功能:十进制转 BCD 码
|
||
* 入口参数:dec - 十进制值
|
||
* 返回值:BCD 码值
|
||
* 函数说明:内部辅助函数
|
||
*/
|
||
uint8_t sd2506_dec_to_bcd(uint8_t dec);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* SD2506_H */
|