feat(adc): 1 kHz 采样节拍改由 TIM6 硬件定时器触发

- CubeMX 加 TIM6(PSC=83 / ARR=999 / ARR 预装载 / NVIC 抢占优先级 6)
- Src/main.c 回调加 TIM6 分支触发 CONVST(USER CODE 区)
- app_main.c 用 HAL_TIM_Base_Start_IT(&htim6) 替换单次触发
- adc_task.c 退化为纯消费者(1 ms 轮询仅作消费节奏)
- @build 0 错 0 警;台架 @test 验收待做
- 同步 ADC采样节拍设计说明 / 继电保护复现规划 / AGENTS / TPAFE README
This commit is contained in:
2026-10-10 15:24:02 +08:00
parent f0300761ae
commit 970e574433
18 changed files with 4427 additions and 74 deletions
+5 -2
View File
@@ -17,6 +17,7 @@
#include "main.h" /* ST_DIR4_GPIO_Port / ST_DIR4_Pin 等 CubeMX 宏 */
#include "stm32f4xx_it.h" /* fault_handler_enable() */
#include "usart.h" /* huart5 */
#include "tim.h" /* htim6:1 kHz 采样节拍(TIM6 更新中断触发 CONVST) */
#include "rs485.h"
#include "sd2506.h"
#include "sys_clock.h"
@@ -209,8 +210,10 @@ int app_main_init(void) {
sd_vbat / 1000, (sd_vbat % 1000) / 10);
}
/* 6) 启动第一次转换(CubeMX 已配置 BUSY EXTI 中断) */
tpafe5160_start_conv_irq();
/* 6) 启动 1 kHz 采样节拍:TIM6 更新中断 → ISR 内触发 CONVST(Src/main.c)。
* ⚠ 必须在 tpafe5160_init() 成功之后启动,否则 ISR 会在驱动首帧自检
* (E-44 有效性探针)期间乱发 CONVST。消费端 adcTask 退化为纯消费者。 */
(void)HAL_TIM_Base_Start_IT(&htim6);
DBG_INFO("App init OK");
return 0;
+19 -17
View File
@@ -1,12 +1,14 @@
/*
* 模块名称:ADC Sampling Task
* 模块功能:TPAFE5160 8 通道同步采样——1ms 采样节拍 + 原子快照消费 + 帧统计
* 模块功能:TPAFE5160 8 通道同步采样——帧消费 + 帧统计(节拍由 TIM6 硬件定时器提供)
* 状态说明:**B1 已落地(2026-10-10)**——本任务从空桩转为真实消费者:
* 每 1ms 触发一次 CONVST,用 tpafe5160_snapshot() 原子取数(AGENTS 铁律),
* 统计帧数/无新帧次数,并纳入看门狗 required_mask(TASK_WD_ADC)。
* ⚠ B1 阶段用**任务周期软触发**(osDelayUntil)产生采样节拍,满足 L1-1
* 判据(BUSY 连续脉冲 + frame_seq 持续递增);**精确 1 kHz / 等周波调频**
* 的硬件定时器触发为后续(需 CubeMX 加 TIM)。
* 用 tpafe5160_snapshot() 原子取数(AGENTS 铁律),统计帧数/无新帧次数,
* 并纳入看门狗 required_mask(TASK_WD_ADC)。
* **采样节拍(v2.2,2026-10-10)**:由 **TIM6 更新中断(1 kHz)** 硬件触发——
* ISR 内调 tpafe5160_start_conv_irq()(Src/main.c 的
* HAL_TIM_PeriodElapsedCallback);本任务**不再自行触发**,退化为**纯消费者**,
* 1ms 轮询(osDelayUntil)仅作消费节奏。详见
* docs/子系统设计/ADC采样节拍设计说明.md。
* V0.1 上只有 TPAFE 三路(UA/UN/IA)测量有效;本任务只取数,不做保护运算。
* 接入前必读:取数只用 tpafe5160_snapshot()(临界区原子快照,仅任务上下文;
* 旧的 get_buf/data_ready/clear_ready 已删除);接消费者前的强制门禁
@@ -24,6 +26,8 @@
* 为真后落日志。写者未注册时控制台走无锁直发,与
* defaultTask 的存储初始化日志字节级交错(台架实测);
* 就绪前挂起上报,就绪后补报最近一帧。
* v2.2 2026-10-10 王建锋 采样节拍改由 TIM6 更新中断(1 kHz)硬件触发;本任务
* 删除自行触发,退化为纯消费者(见文件头"采样节拍")。
*/
#include "adc_task.h"
@@ -35,7 +39,7 @@
#define DBG_TAG "[ADC_TASK]"
#include "dbg_log.h"
/* 采样节拍周期(ms)。B1:任务周期软触发;硬件定时器方案见文件头说明 */
/* 消费轮询周期(ms)。采样节拍由 TIM6(1 kHz)提供,本周期仅作消费节奏 */
#define ADC_TASK_BEAT_MS 1U
/* 心跳日志周期(ms):周期性上报帧统计,作为采集链路存活的观测面 */
#define ADC_TASK_REPORT_MS 10000U
@@ -65,10 +69,10 @@ int adc_task_init(void) {
* 入口参数:arg - FreeRTOS 传入参数(未使用)
* 返 回 值:无
* 限定条件:adc_task_init() 已调用;内核已启动
* 函数说明:每 1ms 触发一次 CONVST(采样节拍),随后原子快照取最新一帧并统计。
* 首拍无帧属正常(本次转换尚未完成);之后每拍消费上一拍触发的帧,
* 故稳态下 consumed 每拍 +1、idle 不再增长。idle 持续增长 = EXTI 未在
* 读帧(异常),由周期心跳日志暴露。
* 函数说明:每 1ms 原子快照取最新一帧并统计。采样节拍由 TIM6 硬件定时器提供
* (ISR 内触发 CONVST),本任务不再触发。稳态下 consumed 每拍 +1、
* idle 不再增长;idle 持续增长 = EXTI 未在读帧或 TIM6 未启动(异常),
* 由周期心跳日志暴露。
*/
void adc_task_func(void *arg) {
uint32_t next = osKernelGetTickCount();
@@ -80,10 +84,8 @@ void adc_task_func(void *arg) {
for (;;) {
int r;
/* 1) 采样节拍:触发一次 CONVST(B1:任务周期软触发) */
tpafe5160_start_conv_irq();
/* 2) 原子快照消费最新一帧(仅任务上下文;1=有新帧 0=无新帧 -1=参数错) */
/* 1) 原子快照消费最新一帧(仅任务上下文;1=有新帧 0=无新帧 -1=参数错)。
* 采样节拍由 TIM6 更新中断提供(ISR 内触发 CONVST),本任务不触发。 */
r = tpafe5160_snapshot(s_frame, (uint8_t)TPAFE5160_CH_NUM);
if (r == 1) {
s_frames_consumed++;
@@ -93,7 +95,7 @@ void adc_task_func(void *arg) {
/* r == -1:参数错。调用点 count 为常量,不可达;不计入 idle 以区分异常 */
}
/* 2b) 首帧码值上报:**写者就绪后**才落日志。写者未注册时 con_append 走
/* 2) 首帧码值上报:**写者就绪后**才落日志。写者未注册时 con_append 走
* 无锁直发路径,与 defaultTask 的存储初始化日志会字节级交错
* (2026-10-10 台架实测);此时挂起上报,就绪后补报最近一帧。
* 只报 TPAFE 三路(UA=buf[6] UN=buf[5] IA=buf[2]),验证取数契约 */
@@ -108,7 +110,7 @@ void adc_task_func(void *arg) {
task_wd_beat(TASK_WD_ADC);
/* 4) 周期心跳日志:帧统计 + 驱动侧 FRSTDATA 错误计数。
* 写者就绪前抑制(同 2b 的交错理由);到点无论是否落日志都推进下个上报点 */
* 写者就绪前抑制(同 2) 的交错理由);到点无论是否落日志都推进下个上报点 */
{
uint32_t now = osKernelGetTickCount();