From 7fb8fc079a2f3e20c7967771f28042bd79484345 Mon Sep 17 00:00:00 2001 From: Wanderingss <1624155937@qq.com> Date: Tue, 1 Sep 2026 13:16:44 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dtpafe5160.c=E5=8E=86=E5=8F=B2?= =?UTF-8?q?U+FFFD=E4=B9=B1=E7=A0=81=EF=BC=8C=E5=8F=96=E6=B6=88no-mojibake?= =?UTF-8?q?=E8=B1=81=E5=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 5 - Drivers/BSP/TPAFE5160/tpafe5160.c | 231 +++++++++++++++++++----------- 2 files changed, 145 insertions(+), 91 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a7cb6c57..7f17eb9b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -68,8 +68,3 @@ repos: entry: python scripts/check_mojibake.py language: system types: [c] - # 已知历史遗留损坏文件(HEAD 已含 U+FFFD,修复前豁免) - exclude: | - (?x)^( - Drivers/BSP/TPAFE5160/tpafe5160\.c - ) diff --git a/Drivers/BSP/TPAFE5160/tpafe5160.c b/Drivers/BSP/TPAFE5160/tpafe5160.c index 6b52bea8..8564a691 100644 --- a/Drivers/BSP/TPAFE5160/tpafe5160.c +++ b/Drivers/BSP/TPAFE5160/tpafe5160.c @@ -1,9 +1,12 @@ /* - * 模块名称:TPAFE5160 16�?通道同步采样ADC驱动 - * 模块功能:提�?TPAFE5160 并行接口模式下的初始化、过采样设置、转换启动、数据读取接�? * 适用平台:STM32F407ZGT6,并�?6位数据总线�?GPIOG[15:0] - * 作者:王建�? * 创建日期�?026-07-17 - * 修改记录�? * 2026-07-17 王建�? 创建初始版本,参�?AD7606 并行驱动�?TPAFE5160 手册 - * 2026-07-17 王建�? 增加 EXTI 中断读取模式 + * 模块名称:TPAFE5160 16位8通道同步采样ADC驱动 + * 模块功能:提供 TPAFE5160 并行接口模式下的初始化、过采样设置、转换启动、数据读取接口 + * 适用平台:STM32F407ZGT6,并行16位数据总线接 GPIOG[15:0] + * 作者:王建锋 + * 创建日期:2026-07-17 + * 修改记录: + * 2026-07-17 王建锋 创建初始版本,参考 AD7606 并行驱动及 TPAFE5160 手册 + * 2026-07-17 王建锋 增加 EXTI 中断读取模式 */ /* 头文件包含区 */ @@ -16,26 +19,30 @@ #define DBG_TAG "[ADC]" #include "dbg_log.h" -/* ======================== 私有宏定�?======================== */ +/* ======================== 私有宏定义 ======================== */ /* - * 并行读取时序延时 (168MHz 主频�? NOP �?5.95ns) + * 并行读取时序延时 (168MHz 主频,1 NOP ≈ 5.95ns) * - * TPAFE5160 并行时序要求 (VDRIVE > 2.7V)�? * t10 (RD 低脉�? �?22ns - * t11 (RD 高脉�? �?10ns - * t14 (数据访问时间) �?21ns (�?RD 下降沿算�? - * t15 (数据保持时间) �?6ns (�?RD 下降沿算�? + * TPAFE5160 并行时序要求 (VDRIVE > 2.7V): + * t10 (RD 低脉宽) ≥ 22ns + * t11 (RD 高脉宽) ≥ 10ns + * t14 (数据访问时间) ≤ 21ns (从 RD 下降沿算起) + * t15 (数据保持时间) ≥ 6ns (从 RD 下降沿算起) * - * GPIO 写操作本身约 1 �?AHB 周期 (~6ns)�? * 加上端口延迟 (~12-18ns),实�?RD 引脚翻转滞后�?18-24ns�? * 因此 NOP 延时只需覆盖数据建立时间即可�? */ + * GPIO 写操作本身约 1 个 AHB 周期 (~6ns), + * 加上端口延迟 (~12-18ns),实际 RD 引脚翻转滞后约 18-24ns。 + * 因此 NOP 延时只需覆盖数据建立时间即可。 + */ #define TPAFE5160_NOP_5() __NOP(); __NOP(); __NOP(); __NOP(); __NOP() -/* RD 低脉宽延时:GPIO�?~6ns) + 5NOP(~30ns) > 22ns */ +/* RD 低脉宽延时:GPIO写(~6ns) + 5NOP(~30ns) > 22ns */ #define TPAFE5160_RD_LOW_DLY() do { TPAFE5160_RD_LOW(); TPAFE5160_NOP_5(); } while (0) -/* RD 高脉宽延时:GPIO�?~6ns) + 3NOP(~18ns) > 10ns */ +/* RD 高脉宽延时:GPIO写(~6ns) + 3NOP(~18ns) > 10ns */ #define TPAFE5160_RD_HIGH_DLY() do { TPAFE5160_RD_HIGH(); __NOP(); __NOP(); __NOP(); } while (0) -/* CONVST 脉冲延时:上升沿前需保证低电平,5NOP 覆盖 t5 �?20ns */ +/* CONVST 脉冲延时:上升沿前需保证低电平,5NOP 覆盖 t5 约20ns */ #define TPAFE5160_CONVST_PULSE() do { \ TPAFE5160_CONVST_LOW(); \ TPAFE5160_NOP_5(); \ @@ -52,20 +59,22 @@ static void tpafe5160_read_channels(uint8_t count, int16_t *buf); /* * 函数功能:初始化 TPAFE5160(设置过采样、等待就绪) * 入口参数:无 - * 返回值:0 - 成功�?2 - BUSY 超时 - * 限定条件:CubeMX 已完�?GPIO 初始�? * 函数说明�?. 设置过采样为无过采样 (000) + * 返回值:0 - 成功,-2 - BUSY 超时 + * 限定条件:CubeMX 已完成 GPIO 初始化 + * 函数说明:1. 设置过采样为无过采样 (000) * 2. 确保 RD 为高、CONVST 为低 * 3. 等待 BUSY 释放(转换空闲) */ -int tpafe5160_init(void) { +int tpafe5160_init(void) +{ /* 设置默认过采样:无过采样 (OS[2:0] = 000) */ tpafe5160_set_os(TPAFE5160_OS_NONE); - /* 确保控制引脚处于空闲状�?*/ + /* 确保控制引脚处于空闲状态 */ TPAFE5160_RD_HIGH(); TPAFE5160_CONVST_LOW(); - /* 等待 BUSY 释放,确保上电后无残留转�?*/ + /* 等待 BUSY 释放,确保上电后无残留转换 */ int ret = tpafe5160_wait_busy(TPAFE5160_CONV_TIMEOUT_MS); if (ret != TPAFE5160_OK) { DBG_ERROR("Init wait BUSY timeout"); @@ -76,10 +85,14 @@ int tpafe5160_init(void) { } /* - * 函数功能:设置过采样�? * 入口参数:os - 过采样率枚举�? tpafe5160_os_t - * 返回值:�? * 限定条件:GPIO 已初始化 - * 函数说明:通过 OS[2:0] 引脚设置过采样率,在下一�?BUSY 下降沿锁存生�? */ -void tpafe5160_set_os(tpafe5160_os_t os) { + * 函数功能:设置过采样率 + * 入口参数:os - 过采样率枚举值 tpafe5160_os_t + * 返回值:无 + * 限定条件:GPIO 已初始化 + * 函数说明:通过 OS[2:0] 引脚设置过采样率,在下一次 BUSY 下降沿锁存生效 + */ +void tpafe5160_set_os(tpafe5160_os_t os) +{ TPAFE5160_OS0(os & 0x01); /* OS0 = bit0 */ TPAFE5160_OS1((os >> 1) & 0x01); /* OS1 = bit1 */ TPAFE5160_OS2((os >> 2) & 0x01); /* OS2 = bit2 */ @@ -88,22 +101,27 @@ void tpafe5160_set_os(tpafe5160_os_t os) { /* * 函数功能:启动一次转换(CONVST 上升沿触发) * 入口参数:无 - * 返回值:�? * 限定条件:GPIO 已初始化 - * 函数说明:产�?CONVST 脉冲上升沿,启动全部8通道同步采样与转�? */ -void tpafe5160_start_conv(void) { + * 返回值:无 + * 限定条件:GPIO 已初始化 + * 函数说明:产生 CONVST 脉冲上升沿,启动全部8通道同步采样与转换 + */ +void tpafe5160_start_conv(void) +{ TPAFE5160_CONVST_PULSE(); } /* - - * 函数功能:等待转换完�? * 入口参数:timeout_ms - 超时时间 uint32_t > 0 - * 返回值:0 - 转换完成�?2 - 超时 + * 函数功能:等待转换完成 + * 入口参数:timeout_ms - 超时时间 uint32_t > 0 + * 返回值:0 - 转换完成,-2 - 超时 * 限定条件:已调用 tpafe5160_start_conv() - * 函数说明:轮�?BUSY 引脚等待下降�? */ -int tpafe5160_wait_busy(uint32_t timeout_ms) { + * 函数说明:轮询 BUSY 引脚等待下降沿 + */ +int tpafe5160_wait_busy(uint32_t timeout_ms) +{ uint32_t tick_start = HAL_GetTick(); - /* 等待 BUSY 释放(低电平表示空闲�?*/ + /* 等待 BUSY 释放(低电平表示空闲) */ while (TPAFE5160_BUSY_READ() == GPIO_PIN_SET) { if ((HAL_GetTick() - tick_start) >= timeout_ms) { return TPAFE5160_BUSY_TIMEOUT; @@ -114,25 +132,28 @@ int tpafe5160_wait_busy(uint32_t timeout_ms) { } /* - * 函数功能:查询当前是否正在转�? * 入口参数:无 - * 返回值:1 - 正在转换�? - 空闲 + * 函数功能:查询当前是否正在转换 + * 入口参数:无 + * 返回值:1 - 正在转换,0 - 空闲 * 限定条件:GPIO 已初始化 - * 函数说明:读�?BUSY 引脚电平 + * 函数说明:读取 BUSY 引脚电平 */ -uint8_t tpafe5160_is_busy(void) { +uint8_t tpafe5160_is_busy(void) +{ return (TPAFE5160_BUSY_READ() == GPIO_PIN_SET) ? 1 : 0; } /* - * 函数功能:读取全�?通道转换结果 + * 函数功能:读取全部8通道转换结果 * 入口参数:buf - 8个int16_t的输出缓冲区 int16_t* 不为 NULL - * 返回值:0 - 成功�?2 - BUSY 超时 + * 返回值:0 - 成功,-2 - BUSY 超时 * 限定条件:GPIO 已初始化 - * 函数说明�?. 启动转换并等�?BUSY 释放 + * 函数说明:1. 启动转换并等待 BUSY 释放 * 2. 连续8次拉低RD读取各通道数据 * 3. 通过 FRSTDATA 验证第一通道 */ -int tpafe5160_read_all(int16_t *buf) { +int tpafe5160_read_all(int16_t *buf) +{ int ret = 0; /* 启动转换 */ @@ -152,13 +173,15 @@ int tpafe5160_read_all(int16_t *buf) { } /* - * 函数功能:读取指定通道的转换结�? * 入口参数:channel - 通道�? uint8_t 0 - 7 + * 函数功能:读取指定通道的转换结果 + * 入口参数:channel - 通道号 uint8_t 0 - 7 * value - 输出指针 int16_t* 不为 NULL - * 返回值:0 - 成功�?1 - 通道号无效,-2 - BUSY 超时 + * 返回值:0 - 成功,-1 - 通道号无效,-2 - BUSY 超时 * 限定条件:GPIO 已初始化 * 函数说明:启动转换并等待完成后,连续读取至指定通道 */ -int tpafe5160_read_channel(uint8_t channel, int16_t *value) { +int tpafe5160_read_channel(uint8_t channel, int16_t *value) +{ int ret = 0; int16_t buf[TPAFE5160_CH_NUM] = {0}; @@ -176,23 +199,29 @@ int tpafe5160_read_channel(uint8_t channel, int16_t *value) { } /* - * 函数功能:原始ADC值转电压�? * 入口参数:raw - ADC原始�? int16_t 有符号补�? * 返回值:电压�? float 单位 V + * 函数功能:原始ADC值转电压值 + * 入口参数:raw - ADC原始值 int16_t 有符号补码 + * 返回值:电压值 float 单位 V * 限定条件:无 - * 函数说明:�?V量程�?LSB = 10V / 65536 �?152.59μV - * ±10V量程�?LSB = 20V / 65536 �?305.18μV - * 硬件 RANGE 引脚�?GND,默�?±5V 量程 + * 函数说明:±5V量程时 LSB = 10V / 65536 ≈ 152.59μV + * ±10V量程时 LSB = 20V / 65536 ≈ 305.18μV + * 硬件 RANGE 引脚接 GND,默认 ±5V 量程 */ -float tpafe5160_to_voltage(int16_t raw) { - /* RANGE �?GND �?±5V 量程,满量程 10V */ +float tpafe5160_to_voltage(int16_t raw) +{ + /* RANGE 接 GND → ±5V 量程,满量程 10V */ return (float)raw * (10.0f / 65536.0f); } /* - * 函数功能:直接读取并行数据总线(不启动转换�? * 入口参数:无 - * 返回值:16位原始数�? uint16_t - * 限定条件:RD 为低�?CS �?RD 已拉�? * 函数说明:读�?GPIOG->IDR �?6位,对应 DB[15:0] + * 函数功能:直接读取并行数据总线(不启动转换) + * 入口参数:无 + * 返回值:16位原始数据 uint16_t + * 限定条件:RD 为低或 CS 与 RD 已拉低 + * 函数说明:读取 GPIOG->IDR 低16位,对应 DB[15:0] */ -uint16_t tpafe5160_read_bus(void) { +uint16_t tpafe5160_read_bus(void) +{ return TPAFE5160_READ_BUS(); } @@ -200,21 +229,27 @@ uint16_t tpafe5160_read_bus(void) { /* * 函数功能:通过 RD 脉冲连续读取多个通道数据 - * 入口参数:count - 要读取的通道�? uint8_t 1 - 8 - * buf - 输出缓冲�? int16_t* 不为 NULL - * 返回值:�? * 限定条件:转换已完成(BUSY 为低),RD 初始为高 - * 函数说明:每�?RD 下降沿输出一个通道数据,按通道1~8顺序输出 - * DB[15:0] 直接�?GPIOG[15:0],通过 IDR 寄存器一次读�? * - * 时序关键�?(VDRIVE > 2.7V, 168MHz 主频)�? * GPIO 写操�?~6ns + 端口延迟 ~18ns �?RD 引脚实际翻转�?24ns �? * t14 数据建立 �?21ns �?数据�?RD 下降沿后 21ns 内有�? * 5 �?NOP (~30ns) 覆盖建立时间 + * 入口参数:count - 要读取的通道数 uint8_t 1 - 8 + * buf - 输出缓冲区 int16_t* 不为 NULL + * 返回值:无 + * 限定条件:转换已完成(BUSY 为低),RD 初始为高 + * 函数说明:每次 RD 下降沿输出一个通道数据,按通道1~8顺序输出 + * DB[15:0] 直接接 GPIOG[15:0],通过 IDR 寄存器一次读取 + * + * 时序关键点 (VDRIVE > 2.7V, 168MHz 主频): + * GPIO 写操作 ~6ns + 端口延迟 ~18ns → RD 引脚实际翻转约 24ns 后 + * t14 数据建立 ≤ 21ns → 数据在 RD 下降沿后 21ns 内有效 + * 5 个 NOP (~30ns) 覆盖建立时间 */ -static void tpafe5160_read_channels(uint8_t count, int16_t *buf) { +static void tpafe5160_read_channels(uint8_t count, int16_t *buf) +{ uint8_t i; for (i = 0; i < count; i++) { - /* RD 下降沿:ADC 输出当前通道数据�?DB[15:0] */ + /* RD 下降沿:ADC 输出当前通道数据到 DB[15:0] */ TPAFE5160_RD_LOW_DLY(); - /* 读取16位并行数�?*/ + /* 读取16位并行数据 */ buf[i] = (int16_t)TPAFE5160_READ_BUS(); /* RD 上升沿:准备下一通道 */ @@ -224,37 +259,45 @@ static void tpafe5160_read_channels(uint8_t count, int16_t *buf) { /* ======================== 中断模式实现 ======================== */ -/* 双缓冲区:ISR �?s_buf_b,主循环�?s_buf_a */ +/* 双缓冲区:ISR 写 s_buf_b,主循环读 s_buf_a */ static int16_t s_buf_a[TPAFE5160_CH_NUM]; static int16_t s_buf_b[TPAFE5160_CH_NUM]; static volatile uint8_t s_ready = 0; -static volatile uint8_t s_buf_sel = 0; /* 0 = �?B / �?A, 1 = �?A / �?B */ +static volatile uint8_t s_buf_sel = 0; /* 0 = 写 B / 读 A, 1 = 写 A / 读 B */ /* - * 函数功能:使�?BUSY EXTI 中断(运行时重使能用�? * 入口参数:无 - * 返回值:�? * 限定条件:CubeMX 已完�?GPIO �?NVIC 配置 - * 函数说明:正常启动流程无需调用,仅�?irq_disable() 后需要重新使能时使用 + * 函数功能:使能 BUSY EXTI 中断(运行时重使能用) + * 入口参数:无 + * 返回值:无 + * 限定条件:CubeMX 已完成 GPIO 和 NVIC 配置 + * 函数说明:正常启动流程无需调用,仅在 irq_disable() 后需要重新使能时使用 */ -void tpafe5160_irq_enable(void) { +void tpafe5160_irq_enable(void) +{ HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); } /* - * 函数功能:关�?BUSY EXTI 中断 + * 函数功能:关闭 BUSY EXTI 中断 * 入口参数:无 - * 返回值:�? * 限定条件:已调用 tpafe5160_irq_enable() + * 返回值:无 + * 限定条件:已调用 tpafe5160_irq_enable() * 函数说明:仅禁用 NVIC 中断,GPIO 配置保持 CubeMX 设定 */ -void tpafe5160_irq_disable(void) { +void tpafe5160_irq_disable(void) +{ HAL_NVIC_DisableIRQ(EXTI9_5_IRQn); } /* - * 函数功能:启动转换(中断模式�? * 入口参数:无 - * 返回值:�? * 限定条件:已调用 tpafe5160_irq_enable() - * 函数说明:产�?CONVST 脉冲,转换完成后�?EXTI 中断自动读取 8 通道数据 + * 函数功能:启动转换(中断模式) + * 入口参数:无 + * 返回值:无 + * 限定条件:已调用 tpafe5160_irq_enable() + * 函数说明:产生 CONVST 脉冲,转换完成后由 EXTI 中断自动读取 8 通道数据 */ -void tpafe5160_start_conv_irq(void) { +void tpafe5160_start_conv_irq(void) +{ s_ready = 0; TPAFE5160_CONVST_PULSE(); } @@ -262,20 +305,24 @@ void tpafe5160_start_conv_irq(void) { /* * 函数功能:检查是否有新的转换数据 * 入口参数:无 - * 返回值:1 - 数据就绪�? - 无新数据 + * 返回值:1 - 数据就绪,0 - 无新数据 * 限定条件:中断模式已启用 * 函数说明:在 EXTI 回调中置位,主循环读取后需调用 tpafe5160_clear_ready() 清除 */ -uint8_t tpafe5160_data_ready(void) { +uint8_t tpafe5160_data_ready(void) +{ return s_ready; } /* - * 函数功能:清除数据就绪标�? * 入口参数:无 - * 返回值:�? * 限定条件:中断模式已启用 + * 函数功能:清除数据就绪标志 + * 入口参数:无 + * 返回值:无 + * 限定条件:中断模式已启用 * 函数说明:主循环处理完数据后调用 */ -void tpafe5160_clear_ready(void) { +void tpafe5160_clear_ready(void) +{ s_ready = 0; } @@ -283,16 +330,28 @@ void tpafe5160_clear_ready(void) { * 函数功能:获取数据缓冲区指针 * 入口参数:无 * 返回值:int16_t[8] 数据缓冲区的 const 指针 - * 限定条件:tpafe5160_data_ready() 返回 1 时调�? * 函数说明:双缓冲切换,ISR 写另一个缓冲区,主循环安全读取当前缓冲�? */ -const int16_t* tpafe5160_get_buf(void) { + * 限定条件:tpafe5160_data_ready() 返回 1 时调用 + * 函数说明:双缓冲切换,ISR 写另一个缓冲区,主循环安全读取当前缓冲区 + */ +const int16_t* tpafe5160_get_buf(void) +{ return (s_buf_sel == 0) ? s_buf_a : s_buf_b; } /* - * 函数功能:BUSY 下降�?EXTI 处理(由 HAL_GPIO_EXTI_Callback 调用�? * 入口参数:GPIO_Pin - 触发中断的引脚号 - * 返回值:�? * 限定条件:BUSY EXTI 已使�? * 函数说明:转换完成后自动读取 8 通道数据到缓冲区,耗时�?0.5µs (168MHz) + * 函数功能:BUSY 下降沿 EXTI 处理(由 HAL_GPIO_EXTI_Callback 调用) + * 入口参数:GPIO_Pin - 触发中断的引脚号 + * 返回值:无 + * 限定条件:BUSY EXTI 已使能 + * 函数说明:转换完成后自动读取 8 通道数据到缓冲区,耗时约 0.5µs (168MHz) */ -void tpafe5160_exti_handler(uint16_t GPIO_Pin) { +void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) +{ + tpafe5160_exti_handler(GPIO_Pin); +} + +void tpafe5160_exti_handler(uint16_t GPIO_Pin) +{ if (GPIO_Pin != TP_BUSY_Pin) { return; }