Files
STM32F4-Base/Drivers/BSP/SD2506/sd2506.c
T
wandering1 67fbdd9897 refactor(结构债): S-4 删零消费点占位宏;S-2 消两处与 Inc 重复的 extern
用户批准「先只跑 1+2」(报告 §0.4 结构债三项 S-1/S-2/S-4 的评估结论)。

**S-4 闭环**:删除 `App/app/app_cfg.h` 里 4 个**全库零消费点**的宏
(`APP_NET_ENABLE` / `APP_ADC_ENABLE` / `APP_RS485_ENABLE` /
`APP_SYS_TIME_SRC`),文件降格为「决策占位说明」——修改记录 v1.2 写明为什么删、
将来在真实初始化点接入门控时怎么接回;同时去掉 `app_main.c` 里只为它存在的
include。留「看着能裁剪、其实不生效」的宏比不留更糟:它不产生任何编译期效果,
却会让评审误信模块可裁剪——此前为了对冲这个误解,AGENTS 之外还得在 6 处文档各
写一句「未接线占位,别当开关用」。

**文档口径同步 17 处**:`App/app/README.md`、`App/README.md`、根 `README.md`、
`项目架构总览.md`、`项目部署环境要求.md`(§3.2 两行 + 配置表一行)、`产品需求
设计文档.md`(B0 结论 + 配置表)、`基线与待确认.md`、`排期详述.md` C5、`登记簿
.md` N-23 残余、`RAM使用分析与优化方案.md` 三处。

**顺带纠出另一个「文档里有、代码里从来没有」的东西**:`RAM使用分析与优化方案
.md` 把 `APP_CCM_ENABLE` 写成「加在 `App/app/app_cfg.h`」,全库只有那篇文档提
到它,从未落地——已就地标注「未实现,重开本簇时一起落地」,免得下一个读者以为
CCM 有回退开关。

**S-2 第一步**:删 `gd5f2gq5ue.c:47`、`sd2506.c:20` 两处与 `Inc/spi.h` /
`Inc/i2c.h` 重复的 `extern`;GD5F 改 `#include "spi.h"`(沿用 `ch395f.c:22`
的既有做法)。

**镜像体积逐项不变**:`Code=213,188 RO-data=18,580 RW-data=1,184
ZI-data=131,504` 与改动前完全相同,`@build` 0 错 0 警告 → 两步均为行为中性。

报告 §0.4/§9 同步为实测口径并**认错**:S-2 不是旧写的「4 处」而是 **25 处**
(`App/task/default_task.c:52-69` 一次就 18 行任务句柄/属性 extern;
`stm32f4xx_it.c` 的 `fault_entry_hard` 属 ARMCC `__asm` 合法例外,不该「
修」);S-1 不是「语义层错位」而是**真实的 BSP→App 反向依赖**(NETCFG 10 处
include `App/cfg/cfg_file.h` + UI 3 个文件)。这两个旧数字是 v3.0 重写时沿用
未测所致。

途中被自家门禁正确拦下一次:在 .c 注释里写「S-2a」→ `+1 [校验1] 未登记编号
`,改成平实语言后转绿(正合既有纪律「代码注释禁用不可检索的内部编号」)。

门禁:`@build` 0/0;`check_ids.py --strict` 增量拦截通过、存量债 650 → 640、
可判定比例 82.83%(地板 82.6%+0.1pp);`check_doc_links.py --all
--sections-strict` 146 文档 0 问题;`pre-commit` 相关文件全 Passed;字节卫生 15
个文件 BOM/CR/U+FFFD/行尾空格全清(`end-of-file-fixer` 修掉 app_cfg.h 的一个
多余空行)。未推送。
2026-10-22 18:22:58 +08:00

539 lines
21 KiB
C
Raw 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.
/*
* 模块名称:SD2506API-G RTC Driver
* 模块功能:SD2506API-G 高精度温补实时时钟驱动,I2C 接口
* 适用平台:STM32F407ZGTx + SD2506API-G 实时时钟芯片(I2C1: PB6-SCL, PB7-SDA)
* 作者:王建锋
* 创建日期:2026-07-17
* 修改记录:
* 2026-07-17 王建锋 创建初始版本,参考 SD2506API-G Ver2.0 手册
*/
#include <string.h>
#include <stdio.h>
#include "sd2506.h"
#include "i2c.h"
#define DBG_TAG "[RTC]"
#include "dbg_log.h"
/* ======================== 内部辅助函数 ======================== */
/*
* 函数功能:BCD 码转十进制数
* 入口参数:bcd - BCD 编码值 uint8_t 0x00 - 0x99
* 返回值:十进制数值 uint8_t
* 限定条件:输入为合法 BCD 编码(高 4 位和低 4 位均 <= 9)
* 函数说明:高 4 位为十位,低 4 位为个位,分别乘 10 和加后返回
*/
uint8_t sd2506_bcd_to_dec(uint8_t bcd) {
return ((bcd >> 4) * 10) + (bcd & 0x0FU);
}
/*
* 函数功能:十进制转 BCD 码
* 入口参数:dec - 十进制数 uint8_t 0 - 99 */
uint8_t sd2506_dec_to_bcd(uint8_t dec) {
return ((dec / 10) << 4) | (dec % 10);
}
/*
* 函数功能:写单字节寄存器
* 入口参数:reg - 寄存器地址 uint8_t 0x00 - 0x79
* val - 写入数据 uint8_t 0x00 - 0xFF
* 返回值:0-成功,2-I2C 错误 int
* 限定条件:I2C 外设已初始化
* 函数说明:通过 I2C 向指定地址写入 1 字节数据
* 限定条件:I2C 外设已初始化
* 函数说明:通过 I2C 向指定地址写入 1 字节
*/
static int sd2506_write_reg(uint8_t reg, uint8_t val) {
if (HAL_I2C_Mem_Write(&hi2c1, SD2506_I2C_ADDR_WRITE, reg,
I2C_MEMADD_SIZE_8BIT, &val, 1,
SD2506_I2C_TIMEOUT_MS) != HAL_OK) {
return SD2506_I2C_ERROR;
}
return SD2506_OK;
}
/*
* 函数功能:读单字节寄存器
* 入口参数:reg - 寄存器地址 uint8_t 0x00 - 0x79
* p_val - 读取值指针 uint8_t*(非空)
* 返回值:0-成功,2-I2C 错误 int
* 限定条件:I2C 外设已初始化,p_val 为非空指针
* 函数说明:通过 I2C 从指定地址读取 1 字节数据
* 限定条件:I2C 外设已初始化,val 为非空指针函数说明:通过 I2C 从指定地址读取 1 字节
*/
static int sd2506_read_reg(uint8_t reg, uint8_t *p_val) {
if (HAL_I2C_Mem_Read(&hi2c1, SD2506_I2C_ADDR_READ, reg,
I2C_MEMADD_SIZE_8BIT, p_val, 1,
SD2506_I2C_TIMEOUT_MS) != HAL_OK) {
return SD2506_I2C_ERROR;
}
return SD2506_OK;
}
/*
* 函数功能:写多字节寄存器(连续写)
* 入口参数:reg - 起始寄存器地址 uint8_t 0x00 - 0x79
* p_data - 数据缓冲区指针 uint8_t*(非空)
* len - 数据长度 uint8_t 1 - N
* 返回值:0-成功,2-I2C 错误 int
* 限定条件:I2C 外设已初始化,p_data 为非空指针
* 函数说明:从 reg 开始连续写入 len 字节数据
* 限定条件:I2C 外设已初始化,data 为非空指针
*/
static int sd2506_write_regs(uint8_t reg, const uint8_t *p_data, uint8_t len) {
if (HAL_I2C_Mem_Write(&hi2c1, SD2506_I2C_ADDR_WRITE, reg,
I2C_MEMADD_SIZE_8BIT, (uint8_t *)p_data, len,
SD2506_I2C_TIMEOUT_MS) != HAL_OK) {
return SD2506_I2C_ERROR;
}
return SD2506_OK;
}
/*
* 函数功能:读多字节寄存器(连续读)
* 入口参数:reg - 起始寄存器地址 uint8_t 0x00 - 0x79
* p_data - 数据缓冲区指针 uint8_t*(非空)
* len - 数据长度 uint8_t 1 - N
* 返回值:0-成功,2-I2C 错误 int
* 限定条件:I2C 外设已初始化,p_data 为非空指针
* 函数说明:从 reg 开始连续读取 len 字节数据
* 限定条件:I2C 外设已初始化,data 为非空指针
*/
static int sd2506_read_regs(uint8_t reg, uint8_t *p_data, uint8_t len) {
if (HAL_I2C_Mem_Read(&hi2c1, SD2506_I2C_ADDR_READ, reg,
I2C_MEMADD_SIZE_8BIT, p_data, len,
SD2506_I2C_TIMEOUT_MS) != HAL_OK) {
return SD2506_I2C_ERROR;
}
return SD2506_OK;
}
/*
* 函数功能:开启写保护(允许写入 00H~71H 寄存器)
* 入口参数:无
* 返回值:0 - 成功 2 - I2C 错误
* 限定条件:I2C 外设已初始化
* 函数说明:顺序:先写 WRTC1=1, 再写 WRTC2=1 + WRTC3=1
*/
static int sd2506_write_enable(void) {
int ret = 0;
/* 写允许顺序(SD2506/SD24xx 手册要求):先置 WRTC1(CTR2 bit7)=1,
* 再置 WRTC2(CTR1 bit2) + WRTC3(CTR1 bit7)=1。顺序反了芯片不会解开写保护。 */
ret = sd2506_write_reg(SD2506_REG_CTR2, 0x80U);
if (ret != SD2506_OK) return ret;
ret = sd2506_write_reg(SD2506_REG_CTR1, 0x84U);
if (ret != SD2506_OK) return ret;
return SD2506_OK;
}
/*
* 函数功能:关闭写保护(禁止写入 00H~71H 寄存器)
* 入口参数:无
* 返回值:0 - 成功 2 - I2C 错误
* 限定条件:I2C 外设已初始化
* 函数说明:顺序:先写 WRTC2=0 + WRTC3=0, 再写 WRTC1=0
*/
static int sd2506_write_disable(void) {
int ret = 0;
/* 写禁止顺序(手册要求):先清 WRTC2/WRTC3(CTR1),再清 WRTC1(CTR2) */
ret = sd2506_write_reg(SD2506_REG_CTR1, 0x00U);
if (ret != SD2506_OK) return ret;
ret = sd2506_write_reg(SD2506_REG_CTR2, 0x00U);
if (ret != SD2506_OK) return ret;
return SD2506_OK;
}
/* ======================== 公共 API 实现 ======================== */
/*
* 函数功能:初始化 SD2506API-G RTC
* 入口参数:无
* 返回值:0-成功,-1-校验失败,-2-I2C 错误 int
* 限定条件:CubeMX 已完成 I2C1 初始化(PB6-SCL, PB7-SDA)
* 函数说明:1. 读取芯片 ID 验证通信
* 2. 充电寄存器 18H 回读校验(出厂 82H 非易失),值漂移时经写允许
* 窗口重置并回读验证(手册 §4.8:强烈建议每次上电重置 18H)
* 3. 上电即写禁止态(WRTC 全 0),无需再写 0FH
*/
int sd2506_init(void) {
int ret = 0;
uint8_t a_id[8] = {0};
/* 验证 I2C 通信: 尝试读取 8 字节 ID */
ret = sd2506_read_regs(SD2506_REG_ID_START, a_id, SD2506_ID_SIZE);
if (ret != SD2506_OK) {
/* 启动段可观测性(2026-10-02 S10):本函数原先所有失败路径均静默返回,
* 而它是启动死机最可疑的源头(I2C1 硬件不通即卡此步且无任何输出)。
* 日志字符串必须纯 ASCII(文件无 BOM,ARMCC 按 CP936 解码)。 */
DBG_ERROR("sd2506_init: ID read FAIL (I2C err=%d)", ret);
return ret;
}
/* 充电寄存器 18H:手册 §4.8"出厂均配置成 82H"(非易失),
* 先回读校验,正常路径(=82H)不再写;仅值漂移(长时掉电等)时
* 经写允许窗口重置并回读验证(手册强烈建议每次上电重置 18H)
* 0x82 = EN_Charge(Bit7) | Charge1(Bit1):开启充电,5K 电阻 */
uint8_t charge_val = 0;
ret = sd2506_read_reg(SD2506_REG_CHARGE, &charge_val);
if (ret != SD2506_OK) {
DBG_ERROR("sd2506_init: charge reg read FAIL (err=%d)", ret);
return ret;
}
if (charge_val != SD2506_CHARGE_INIT_VALUE) {
int ret_read = 0;
ret = sd2506_write_enable();
if (ret != SD2506_OK) {
DBG_ERROR("sd2506_init: write-enable FAIL (err=%d)", ret);
return ret;
}
ret = sd2506_write_reg(SD2506_REG_CHARGE, SD2506_CHARGE_INIT_VALUE);
if (ret != SD2506_OK) {
(void)sd2506_write_disable();
DBG_ERROR("sd2506_init: charge reg write FAIL (err=%d)", ret);
return ret;
}
ret_read = sd2506_read_reg(SD2506_REG_CHARGE, &charge_val);
ret = sd2506_write_disable();
if (ret != SD2506_OK) {
DBG_ERROR("sd2506_init: write-disable FAIL (err=%d)", ret);
return ret;
}
if (ret_read != SD2506_OK || charge_val != SD2506_CHARGE_INIT_VALUE) {
DBG_ERROR("sd2506_init: charge reg verify FAIL (read=%d val=0x%02X)",
ret_read, charge_val);
return SD2506_ERROR;
}
DBG_INFO("sd2506_init: charge reg 18H reset to 0x%02X (was drifted)",
SD2506_CHARGE_INIT_VALUE);
}
DBG_INFO("sd2506_init: OK");
return SD2506_OK;
}
/*
* 函数功能:设置 RTC 时间日期
* 入口参数:p_time - 时间结构体指针,包含要设置的时间
* 返回值:0 - 成功,2 - I2C 错误
* 限定条件:sd2506_init() 已调用成功
* 函数说明:1. 先开写保护
* 2. 一次性写入 7 字节时间数据 (00H~06H)
* 3. 关闭写保护
*/
int sd2506_set_time(const sd2506_time_t *p_time) {
int ret = 0;
uint8_t buf[7] = {0};
if (p_time == NULL) {
return SD2506_ERROR;
}
/* 组装 7 字节时间数据 (BCD 码) */
buf[0] = sd2506_dec_to_bcd(p_time->second); /* 00H: 秒 */
buf[1] = sd2506_dec_to_bcd(p_time->minute); /* 01H: 分 */
buf[2] = sd2506_dec_to_bcd(p_time->hour) | 0x80U; /* 02H: 时(bit7=1, 24小时制) */
buf[3] = sd2506_dec_to_bcd(p_time->week); /* 03H: 星期 */
buf[4] = sd2506_dec_to_bcd(p_time->day); /* 04H: 日 */
buf[5] = sd2506_dec_to_bcd(p_time->month); /* 05H: 月 */
buf[6] = sd2506_dec_to_bcd(p_time->year - 2000U); /* 06H: 年 */
/* 开启写保护 */
ret = sd2506_write_enable();
if (ret != SD2506_OK) return ret;
/* 一次性写入 7 字节时间数据 (00H~06H)
* 手册要求: 不可单独写某一个时间寄存器,否则可能引起错误进入 */
ret = sd2506_write_regs(SD2506_REG_SEC, buf, 7);
if (ret != SD2506_OK) return ret;
/* 关闭写保护 */
ret = sd2506_write_disable();
if (ret != SD2506_OK) return ret;
return SD2506_OK;
}
/*
* 函数功能:读取 RTC 时间日期
* 入口参数:p_time - 输出时间结构体指针 sd2506_time_t*(非空)
* 返回值:0-成功,2-I2C 错误 int
* 限定条件:sd2506_init() 已调用成功
* 函数说明:一次读取 7 字节时间数据 (00H~06H),所有实时数据被锁存避免错误
* note: sd2506_init() must be called first
*/
int sd2506_get_time(sd2506_time_t *p_time) {
int ret = 0;
uint8_t buf[7] = {0};
if (p_time == NULL) {
return SD2506_ERROR;
}
/* 一次读取 7 字节时间数据 (00H~06H)
* 手册说明: 读取时所有实时数据被锁存,避免错误 */
ret = sd2506_read_regs(SD2506_REG_SEC, buf, 7);
if (ret != SD2506_OK) {
return ret;
}
p_time->second = sd2506_bcd_to_dec(buf[0] & 0x7FU); /* 00H: 秒 */
p_time->minute = sd2506_bcd_to_dec(buf[1] & 0x7FU); /* 01H: 分 */
p_time->hour = sd2506_bcd_to_dec(buf[2] & 0x7FU); /* 02H: 屏蔽 bit7 (12/24标志) */
p_time->week = sd2506_bcd_to_dec(buf[3] & 0x07U); /* 03H: 星期 */
p_time->day = sd2506_bcd_to_dec(buf[4] & 0x3FU); /* 04H: 日 */
p_time->month = sd2506_bcd_to_dec(buf[5] & 0x1FU); /* 05H: 月 */
p_time->year = sd2506_bcd_to_dec(buf[6]) + 2000U; /* 06H: 年 */
return SD2506_OK;
}
/*
* 函数功能:读取内部温度
* 入口参数:p_temp - 输出温度值指针 int8_t*(非空)
* 返回值:0-成功,2-I2C 错误 int
* 限定条件:sd2506_init() 已调用成功
* 函数说明:读取寄存器 0x16,bit7 为符号位
* return: 0=OK, -2=I2C error
* note: reads register 0x16
*/
int sd2506_get_temperature(int8_t *p_temp) {
int ret = 0;
uint8_t val = 0;
if (p_temp == NULL) {
return SD2506_ERROR;
}
ret = sd2506_read_reg(SD2506_REG_TEMP, &val);
if (ret != SD2506_OK) {
return ret;
}
/* bit7 为符号位, 其余为温度值 */
if (val & 0x80U) {
/* 负温度 取补码 */
*p_temp = (int8_t)(val | 0xF0U);
} else {
/* 正温度 */
*p_temp = (int8_t)(val & 0x7FU);
}
return SD2506_OK;
}
/*
* 函数功能:读取电池电压(毫伏)
* 入口参数:p_voltage - 输出电压指针 uint16_t*(非空)
* 返回值:0-成功,2-I2C 错误 int
* 限定条件:sd2506_init() 已调用成功
* 函数说明:组合 9 位值 (bit8=BAT8_VAL, bit7~0=BAT_VL),转换为毫伏
* return: 0=OK, -2=I2C error
* note: combines 9-bit value
*/
int sd2506_get_battery_voltage(uint16_t *p_voltage) {
int ret = 0;
uint8_t val_high = 0;
uint8_t val_low = 0;
if (p_voltage == NULL) {
return SD2506_ERROR;
}
/* 读取 1AH bit7 (BAT8_VAL) 与 1BH (BAT_VL) */
ret = sd2506_read_reg(SD2506_REG_CTR5, &val_high);
if (ret != SD2506_OK) return ret;
ret = sd2506_read_reg(SD2506_REG_BAT_VAL, &val_low);
if (ret != SD2506_OK) return ret;
/* 组合 9 位值 bit8=BAT8_VAL(1AH bit7), bit7~0=BAT_VL(1BH)
* 例: 1AH=80H, 1BH=30H => 电压 = 0x130 = 304 => 3.04V => 3040mV */
uint16_t raw = ((val_high & 0x80U) << 1) | val_low;
*p_voltage = raw * 10; /* 转换为毫伏 (raw 单位 0.01V) */
return SD2506_OK;
}
/*
* 函数功能:读取 8 字节芯片 ID
* 入口参数:p_id - 输出缓冲区指针 uint8_t[8](非空)
* 返回值:0-成功,2-I2C 错误 int
* 限定条件:sd2506_init() 已调用成功
* 函数说明:读取寄存器 0x72~0x79
* return: 0=OK, -2=I2C error
* note: reads registers 0x72-0x79
*/
int sd2506_get_id(uint8_t p_id[8]) {
if (p_id == NULL) {
return SD2506_ERROR;
}
return sd2506_read_regs(SD2506_REG_ID_START, p_id, SD2506_ID_SIZE);
}
/*
* 函数功能:读取 SRAM 数据
* 入口参数:addr - 起始地址 uint8_t 0-69
* p_buf - 输出缓冲区指针 uint8_t*(非空)
* len - 读取长度 uint8_t 1-N
* 返回值:0-成功,-1=参数错误,-2=I2C 错误 int
* 限定条件:sd2506_init() 已调用成功;addr+len <= SD2506_SRAM_SIZE(70)
* 函数说明:SRAM 范围 0x2C~0x71
* return: 0=OK, -1=param err, -2=I2C err
* note: SRAM range 0x2C-0x71
*/
int sd2506_read_sram(uint8_t addr, uint8_t *p_buf, uint8_t len) {
if (p_buf == NULL || len == 0 || addr >= SD2506_SRAM_SIZE) {
return SD2506_ERROR;
}
if (addr + len > SD2506_SRAM_SIZE) {
return SD2506_ERROR;
}
return sd2506_read_regs(SD2506_REG_SRAM_START + addr, p_buf, len);
}
/*
* 函数功能:写入 SRAM 数据
* 入口参数:addr - 起始地址 uint8_t 0-69
* p_buf - 输入数据指针 uint8_t*(非空)
* len - 写入长度 uint8_t 1-N
* 返回值:0-成功,-1=参数错误,-2=I2C 错误 int
* 限定条件:sd2506_init() 已调用成功;addr+len <= SD2506_SRAM_SIZE(70)
* 函数说明:SRAM 写入需走写保护流程(虽 SRAM 本身无需)
* return: 0=OK, -1=param err, -2=I2C err
*/
int sd2506_write_sram(uint8_t addr, const uint8_t *p_buf, uint8_t len) {
if (p_buf == NULL || len == 0 || addr >= SD2506_SRAM_SIZE) {
return SD2506_ERROR;
}
if (addr + len > SD2506_SRAM_SIZE) {
return SD2506_ERROR;
}
/* SRAM 无需开写保护即可写入 (写保护仅对 00H~71H 有效, SRAM 为 2CH~71H)
* 但为安全起见, SRAM 写入也走写保护流程 */
int ret = 0;
ret = sd2506_write_enable();
if (ret != SD2506_OK) return ret;
ret = sd2506_write_regs(SD2506_REG_SRAM_START + addr, p_buf, len);
if (ret != SD2506_OK) return ret;
ret = sd2506_write_disable();
return ret;
}
/*
* 函数功能:设置闹钟中断
* 入口参数:p_time - 报警时间结构体指针 sd2506_time_t*(非空)
* mask - 报警匹配掩码 uint8_t
* 返回值:0-成功,-2=I2C 错误 int
* 限定条件:sd2506_init() 已调用成功
* 函数说明:写入 8 字节报警数据 (07H~0EH),使能 CTR2.INTAE+INTS0+IM
* return: 0=OK, -2=I2C error
*/
int sd2506_set_alarm(const sd2506_time_t *p_time, uint8_t mask) {
int ret = 0;
uint8_t buf[8] = {0};
if (p_time == NULL) {
return SD2506_ERROR;
}
/* 组装 8 字节报警数据 (07H~0EH) */
buf[0] = sd2506_dec_to_bcd(p_time->second) & 0x7FU; /* 07H: 秒报 */
buf[1] = sd2506_dec_to_bcd(p_time->minute) & 0x7FU; /* 08H: 分报 */
buf[2] = sd2506_dec_to_bcd(p_time->hour) & 0x3FU; /* 09H: 时报(最高位始终为0) */
buf[3] = 0x00U; /* 0AH: 星期报警 */
buf[4] = sd2506_dec_to_bcd(p_time->day) & 0x3FU; /* 0BH: 日报 */
buf[5] = sd2506_dec_to_bcd(p_time->month) & 0x1FU; /* 0CH: 月报 */
buf[6] = sd2506_dec_to_bcd(p_time->year - 2000U); /* 0DH: 年报 */
buf[7] = mask; /* 0EH: 报警允许 */
/* 开启写保护 */
ret = sd2506_write_enable();
if (ret != SD2506_OK) return ret;
/* 写入报警寄存器 (07H~0EH) */
ret = sd2506_write_regs(SD2506_REG_AL_SEC, buf, 8);
if (ret != SD2506_OK) return ret;
/* 使能报警中断: CTR2 中 INTAE=1, INTS1=0, INTS0=1, IM=1 (周期中断) */
ret = sd2506_write_reg(SD2506_REG_CTR2,
SD2506_CTR2_INTAE | SD2506_CTR2_INTS0 | SD2506_CTR2_IM);
if (ret != SD2506_OK) return ret;
/* 关闭写保护 */
ret = sd2506_write_disable();
if (ret != SD2506_OK) return ret;
return SD2506_OK;
}
/*
* 函数功能:清除闹钟中断标志
* 入口参数:无
* 返回值:0-成功,-2=I2C 错误 int
* 限定条件:sd2506_init() 已调用成功
* 函数说明:ARST 位于 CTR3(11H) bit7,本驱动从未写 CTR3 → ARST=0,
* 故读 CTR1 不会自动清 INTAF(手册 L519/L523),须手动写 CTR1 将 INTAF 置 0;
* 写 0FH 须在写允许窗口内且保持 WRTC2/WRTC3=1(手册 L521),
* 故写入值取写允许态 0xFF 清 INTAF 位后的 0xDF。
* return: 0=OK, -2=I2C error
*/
int sd2506_clear_alarm(void) {
int ret = 0;
int ret_off = 0;
/* 写 0FH 须在写允许窗口内(手册 L519),且 WRTC2/WRTC3 必须保持 1(L521) */
ret = sd2506_write_enable();
if (ret != SD2506_OK) {
return ret;
}
ret = sd2506_write_reg(SD2506_REG_CTR1,
(uint8_t)(SD2506_CTR1_WRITE_ON & (uint8_t)~SD2506_CTR1_INTAF));
ret_off = sd2506_write_disable();
if (ret == SD2506_OK) {
ret = ret_off;
}
return ret;
}
/*
* 函数功能:读取控制寄存器 1 (CTR1)
* 入口参数:p_val - 输出值指针 uint8_t*(非空)
* 返回值:0-成功,-2=I2C 错误 int
* 限定条件:sd2506_init() 已调用成功
* return: 0=OK, -2=I2C error
*/
int sd2506_read_ctr1(uint8_t *p_val) {
if (p_val == NULL) {
return SD2506_ERROR;
}
return sd2506_read_reg(SD2506_REG_CTR1, p_val);
}