8c72698666
新增 App/algo/run_par.c/h(「数据可信」卡 10,lead 四裁落地): - [run_par] cfg 段:遥测死区 9 键 int32 毫单位(db_ua…db_freq),工厂默认 = 卡 6 额定 0.5% 档(500mV×4 / 5mA×4 / 500mHz);注册走 adc_cal 同款内核前 契约(app_main_init),不挂回调 = 引擎副本即生效值;键数 9≤16 不拆段 - 真源收编(裁③):pts 层 s_yc_db 运行时副本删除,COV 每拍实时读 run_par (协议→算法向下依赖,同 meas 先例;无投递无缓存 = 顺序/幂等平凡成立); iec104_pts_yc_set_deadband()/deadband() 保留为转发壳,壳内保留"成功清 半截确认计数"语义并由 TC-IEC104-027 追加断言钉住(裁⑤) - 104 地址映射(裁①):0x8030~0x8038 死区 9 点 / 0x8040~0x8047 k 覆盖 / 0x8048~0x804F b 覆盖(逐项地址本仓自定——复现规划 §5.4 权威表不在仓, 送检点表到位后替换 run_par.c 顶部常量段一处;已在 IEC104 §3.4 表头挂账); 路由顺序 = run_par 表先、未命中落 prot_set——0x8027~0x802A 属 prot_set 告警段永不覆盖,TC-IEC104-029 双向往返钉死;空隙地址自然 COT14/PN - 通道系数覆盖 = adc_cal_set 代理(裁②a):合法带/越带 [ERR] 留痕全复用, run_par 不存第二份系数(防双真源);单侧写 RMW 用另一侧当前生效值; 回显 = 生效值视图(文件坏值被哨兵回退 ROM 时主站看到的就是下游吃到的); adc_cal 配套:+adc_cal_b_codes() 读取口(回显/RMW 用)+ set() 授权写者 注记扩至 iec104Task 直通路径(单字原子契约同「数据可信」§4.4) - 持久化(裁②b):新事件位 SYS_EVT_RUN_PAR_SAVE(1<<8);iec104Task 主循环 peek 投递 → defaultTask run_par_store_save() 一条事件一趟 cfg_file_save 整档外科(覆盖 [run_par] 9 键 + 联动 [adc_cal] 两段);失败脏保留 = 天然 重试(B7 prot_set 同款)。C_SE 现行无"暂停/测试态"门控——文档现行如此 不造新语义,送检若要求接线点已写进 §3.4 注(裁④) 测试:新建 test/host/run_par(TC-RUNPAR-001~008,67 断言,真实 cfg 引擎 + 真实 adc_cal + 内存虚拟盘同 adc_cal 套件先例;[run_par] 注册契约/落盘往返/ 外改文件即副本生效/两段式不提交不置脏/合法带拒+RMW+生效值回显/init 幂等 重注册留痕);iec104 套扩真链 TU(cfg_file+adc_cal+run_par 非桩,141 断言: +TC-IEC104-029 路由 + 壳清确认计数 3 断言);meas 套静态更名 s_snap*→ s_ms_snap*(与 cfg_file.c s_snap 同 TU 相撞,D1 同款改名法,226 断言不变); iec104_serv 套补 run_par_dirty_peek 假件。id_registry 建族 TC-HOST-RUNPAR (游标 008)+ TC-HOST-IEC104 游标 028→029;新钩子 run-par-unit-test + iec104 钩子触发面随真链扩;uvprojx +run_par.c(合法入库)+ SIM_EXEMPT 登记 (模拟器不编 104 协议,已核实 CMake 面)。 文档:IEC104 §3.4 运行参数段表(含送检替换账/门控未来条件/代理声明)、§7、 §8 第 4 条、变更记录;网络配置说明新增 §3.5 [run_par] 键表;复现规划 §5.4 补运行参数段落实进度。**遗留(交 lead)**:数据可信 §4.4 "引擎 RAM 副本" 一节当时的措辞对象含 pts 侧副本,s_yc_db 删除后该句过时(裁③b 点名,§4.4 在写域外未动)。 gate:@build 0/0(Code=219620 RO=22036 RW=1280 ZI=132864);vs 0cbae7d: Flash +1912B、RAM(RW+ZI) +8B(37B 新静态被链接器并洞吸收);iec104Task 栈 1456B/margin 43%、defaultTask 3032B 不变;id-check/doc-links/cppcheck/ coding-standard 实跑过;--all-files 全量 45 钩子实跑(43 绿 + 仅 mem-budget / mem-numbers 两红 = 台账受管区 vs .map 漂移,回填属 lead 单写者区,批 1/道D-1 /D2 同口径):gate: only mem-budget/mem-numbers pending lead ledger backfill BOM/CR/U+FFFD/字面量 ASCII 逐文件自查通过。
397 lines
17 KiB
C
397 lines
17 KiB
C
/*
|
||
* 模块名称:通道标定与量纲折算(L1.5)——实现
|
||
* 模块功能:见 adc_cal.h。折算模型(工程量 = (code + b) × k × 1e-6,k 为 Q16
|
||
* µV/码)与两段 cfg 布局([adc_cal]:k_* + valid 位图;[adc_cal_ofs]:
|
||
* b_*)照 docs/任务规划/数据可信.md §4.1 / §4.4 落地;系数口径
|
||
* (ROM 默认 = 卡 1 定死的引脚侧 LSB)见 docs/硬件平台/ADC通道映射说明.md
|
||
* §7.1。
|
||
* 并发契约:cfg RAM 副本属主 = 配置引擎(defaultTask 的 load/poll 原地
|
||
* 改写),本层逐点折算现读——int32 对齐字在 Cortex-M4 上读写原子,
|
||
* poll 重载「复位默认 + 逐键解析」存在 µs 级窗口,撞上则该拍该通道
|
||
* 为默认值/半新值(相量 20 点窗摊薄,且触发面 = 用户改文件后 4 s
|
||
* 沉降一次性事件)——「数据可信」§4.4 明载此设计(不挂回调)。
|
||
* 合法带哨兵(防损坏文件/错误标定把假电压送进下游):k ∉ ROM×[0.5,2.0]
|
||
* 或 |b| > ADC_CAL_B_MAX → 该通道折算回退 ROM + b=0,flags 不报
|
||
* VALID,每通道每次开机首见沿打一条 [ERR](adc_cal_init 重置留痕)。
|
||
* 适用平台:STM32F407ZGTx(Cortex-M4F,硬件 FPU)
|
||
* 作者:DTU 项目组
|
||
* 创建日期:2026-10-25(道A 卡 2/卡 4)
|
||
* 修改记录:
|
||
* v1.0 2026-10-25 DTU 项目组 创建:Q16 系数/零点两段落盘 + 折算 + 三态 flags
|
||
* v1.1 2026-10-25 DTU 项目组 卡 10(道D):新增 adc_cal_b_codes() 生效零点
|
||
* 读取口;set() 授权写者扩至 iec104Task 直通路径
|
||
* (run_par 0x8040~/0x8048~,契约同 §4.4)
|
||
* + 合法带哨兵回退 + 两点标定公式(台架注入待跑)
|
||
*/
|
||
|
||
/* 头文件包含区 */
|
||
#include <stddef.h>
|
||
#include <string.h>
|
||
|
||
#include "adc_cal.h"
|
||
|
||
#include "cfg_file.h"
|
||
|
||
#define DBG_TAG "[CAL]"
|
||
#include "dbg_log.h"
|
||
|
||
/* 常量定义区 */
|
||
|
||
/* 段名(≤ CFG_FILE_MAX_NAME_LEN)与键名(k_ua…b_in,均 4/5 字符)
|
||
* ——「数据可信」§4.4 布局;键的书写顺序按该表,存储下标按语义枚举 */
|
||
#define ADC_CAL_SEC_K "adc_cal"
|
||
#define ADC_CAL_SEC_B "adc_cal_ofs"
|
||
|
||
/* Q16 → V 的合并比例因子:1e-6 / 65536(float 常量,精确到 1 ulp 以内即可:
|
||
* 系数本身 Q16 舍入误差 < 0.001 %,见「数据可信」§4.1) */
|
||
#define ADC_CAL_K_SCALE (1.52587890625e-11f)
|
||
|
||
/* 静态变量定义区 */
|
||
|
||
/* [adc_cal] 段 RAM 副本:k 按语义下标 0..7,valid 位图 bit=语义下标。
|
||
* data_size 取 offsetof(valid)+1 = 33(尾随对齐填充不属于引擎视图,
|
||
* 引擎「复位默认」按 data_size memcpy,必须覆盖 valid,见单测 TC-ADCCAL-001) */
|
||
typedef struct {
|
||
int32_t k[8];
|
||
uint8_t valid;
|
||
} adc_cal_kcfg_t;
|
||
|
||
/* [adc_cal_ofs] 段 RAM 副本:b 按语义下标 0..7(int32 有符号,卡 3 的
|
||
* CFG_VAL_INT 是负零点偏移能干净落盘的前提) */
|
||
typedef struct {
|
||
int32_t b[8];
|
||
} adc_cal_bcfg_t;
|
||
|
||
static adc_cal_kcfg_t s_kcfg; /* 生效系数副本(引擎原地更新) */
|
||
static adc_cal_bcfg_t s_bcfg; /* 生效零点副本 */
|
||
|
||
/* 工厂默认(ROM 理论系数,卡 1 定死,「数据可信」§4.4):**下标 = 语义枚举**
|
||
* (UA0 / UB1 / UC2 / UN3 / IA4 / IB5 / IC6 / IN7)——UA/UN/IA 走 TPAFE
|
||
* (16 位 ±5 V 档),UB/UC/IB/IC/IN 走 STM32 ADC1;逐路对过
|
||
* docs/硬件平台/ADC通道映射说明.md §3(IN=ADC11/STM32,勿再按分组顺序误写)。
|
||
* ROM 表按**当前 V0.1 来源排布**显式书写(不查 desc 运行期派生),因为它是
|
||
* 卡 1 定稿的存档事实;V0.2(N-18)改版时本表与 adc_input 映射表同步改,
|
||
* 上层语义与 API 不动。CLIPPED 位则**运行期按来源派生**(见 adc_cal_flags) */
|
||
static const adc_cal_kcfg_t s_kcfg_rom = {
|
||
/* idx0 UA / idx1 UB / idx2 UC / idx3 UN */
|
||
{ ADC_CAL_K_Q16_TPAFE, ADC_CAL_K_Q16_STM32, ADC_CAL_K_Q16_STM32,
|
||
ADC_CAL_K_Q16_TPAFE,
|
||
/* idx4 IA / idx5 IB / idx6 IC / idx7 IN */
|
||
ADC_CAL_K_Q16_TPAFE, ADC_CAL_K_Q16_STM32, ADC_CAL_K_Q16_STM32,
|
||
ADC_CAL_K_Q16_STM32 },
|
||
0u /* 出厂未标定:VALID 全 0 */
|
||
};
|
||
static const adc_cal_bcfg_t s_bcfg_rom = { { 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L } };
|
||
|
||
/* 合法带哨兵留痕位(bit=语义下标;每通道每次开机只打一条 [ERR],
|
||
* adc_cal_init 清零 = 新一轮观测窗) */
|
||
static uint8_t s_err_latched;
|
||
|
||
/* 键表:offset 用 offsetof 取真值(k[0]@0 / k[1]@4 … valid@32) */
|
||
static const cfg_key_def_t s_k_keys_tbl[9] = {
|
||
{ "k_ua", CFG_VAL_INT, offsetof(adc_cal_kcfg_t, k[0]), 4u },
|
||
{ "k_un", CFG_VAL_INT, offsetof(adc_cal_kcfg_t, k[3]), 4u },
|
||
{ "k_ia", CFG_VAL_INT, offsetof(adc_cal_kcfg_t, k[4]), 4u },
|
||
{ "k_ub", CFG_VAL_INT, offsetof(adc_cal_kcfg_t, k[1]), 4u },
|
||
{ "k_uc", CFG_VAL_INT, offsetof(adc_cal_kcfg_t, k[2]), 4u },
|
||
{ "k_ib", CFG_VAL_INT, offsetof(adc_cal_kcfg_t, k[5]), 4u },
|
||
{ "k_ic", CFG_VAL_INT, offsetof(adc_cal_kcfg_t, k[6]), 4u },
|
||
{ "k_in", CFG_VAL_INT, offsetof(adc_cal_kcfg_t, k[7]), 4u },
|
||
{ "valid", CFG_VAL_UINT, offsetof(adc_cal_kcfg_t, valid), 1u },
|
||
};
|
||
static const cfg_key_def_t s_b_keys_tbl[8] = {
|
||
{ "b_ua", CFG_VAL_INT, offsetof(adc_cal_bcfg_t, b[0]), 4u },
|
||
{ "b_un", CFG_VAL_INT, offsetof(adc_cal_bcfg_t, b[3]), 4u },
|
||
{ "b_ia", CFG_VAL_INT, offsetof(adc_cal_bcfg_t, b[4]), 4u },
|
||
{ "b_ub", CFG_VAL_INT, offsetof(adc_cal_bcfg_t, b[1]), 4u },
|
||
{ "b_uc", CFG_VAL_INT, offsetof(adc_cal_bcfg_t, b[2]), 4u },
|
||
{ "b_ib", CFG_VAL_INT, offsetof(adc_cal_bcfg_t, b[5]), 4u },
|
||
{ "b_ic", CFG_VAL_INT, offsetof(adc_cal_bcfg_t, b[6]), 4u },
|
||
{ "b_in", CFG_VAL_INT, offsetof(adc_cal_bcfg_t, b[7]), 4u },
|
||
};
|
||
|
||
/* 函数定义区 */
|
||
|
||
/*
|
||
* 函数功能:判定语义通道是否 STM32 源(经 adc_input 权威映射表,不另立第二份表)
|
||
* 入口参数:sem - 语义通道 unsigned
|
||
* 返 回 值:1 - STM32;0 - TPAFE(含 desc 取不到时的保守分支) int
|
||
* 限定条件:无
|
||
*/
|
||
static int s_rom_k_stm32(unsigned sem) {
|
||
const adc_channel_desc_t *d = adc_input_desc((adc_semantic_t)sem);
|
||
|
||
return ((d != NULL) && (d->source == ADC_SRC_STM32)) ? 1 : 0;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:取语义通道的 ROM 默认系数(合法带/回退参照)
|
||
* 入口参数:sem - 语义下标(0..7) unsigned
|
||
* 返 回 值:Q16 系数 int32_t
|
||
* 限定条件:sem < 8(调用方已先行拦截 TEMP/越界)
|
||
* 函数说明:直接读出厂表本体——保证「哨兵合法带基准」与「引擎工厂默认」
|
||
* 永远同一份数(两者若靠重复表达式各算各的,改一处漏一处就是暗雷)
|
||
*/
|
||
static int32_t s_rom_k(unsigned sem) {
|
||
return s_kcfg_rom.k[sem];
|
||
}
|
||
|
||
/*
|
||
* 函数功能:k/b 合法带检查(ROM×[0.5,2.0] / |b| ≤ ADC_CAL_B_MAX)
|
||
* 入口参数:sem - 语义下标(0..7) unsigned
|
||
* k - 待检系数 Q16 int32_t
|
||
* b - 待检零点 码值 int32_t
|
||
* 返 回 值:1 - 合法;0 - 越带 int
|
||
* 限定条件:sem < 8
|
||
*/
|
||
static int s_kband_ok(unsigned sem, int32_t k, int32_t b) {
|
||
const int32_t rom = s_rom_k(sem);
|
||
|
||
if (k < (rom >> 1) || k > (rom << 1)) {
|
||
return 0;
|
||
}
|
||
if (b > ADC_CAL_B_MAX || b < -ADC_CAL_B_MAX) {
|
||
return 0;
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:越带留痕(每通道每次开机首见沿一条 [ERR],init 重置)
|
||
* 入口参数:sem - 语义下标 0..7;k/b - 现场值
|
||
* 返 回 值:无
|
||
* 限定条件:仅 adc_cal_apply/set 内部
|
||
*/
|
||
static void s_note_bad(unsigned sem, int32_t k, int32_t b) {
|
||
const uint8_t bit = (uint8_t)(1u << sem);
|
||
|
||
if ((s_err_latched & bit) == 0u) {
|
||
s_err_latched |= bit;
|
||
DBG_ERROR("ch=%u k_q16=%ld b=%ld out of ROM band [0.5x,2x]/|b|<=%ld -> ROM fallback",
|
||
(unsigned)sem, (long)k, (long)b, (long)ADC_CAL_B_MAX);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* 函数功能:读通道「当前生效且合法」的 k/b(越带就地回退 ROM)
|
||
* 入口参数:sem - 语义下标 0..7;p_k/p_b - 输出
|
||
* 返 回 值:1 - 用了合法值;0 - 已回退 ROM
|
||
* 限定条件:sem < 8
|
||
*/
|
||
static int s_eff_kb(unsigned sem, int32_t *p_k, int32_t *p_b) {
|
||
const int32_t k = s_kcfg.k[sem];
|
||
const int32_t b = s_bcfg.b[sem];
|
||
|
||
if (s_kband_ok(sem, k, b) != 0) {
|
||
*p_k = k;
|
||
*p_b = b;
|
||
return 1;
|
||
}
|
||
s_note_bad(sem, k, b);
|
||
*p_k = s_rom_k(sem);
|
||
*p_b = 0L;
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:标定层初始化——RAM 副本置 ROM 默认 + 注册两段进 cfg 引擎(幂等)
|
||
* 入口参数:无
|
||
* 返 回 值:无
|
||
* 限定条件:内核启动前调用(app_main_init);注册必须先于 cfg_file_load
|
||
* 函数说明:完整契约见 adc_cal_init() 同名声明(adc_cal.h);注册失败(段名重复/
|
||
* 段数超限)打 [ERR] 后继续——ROM 默认系数照常生效,仅文件整定失效
|
||
*/
|
||
void adc_cal_init(void) {
|
||
cfg_section_reg_t reg;
|
||
|
||
(void)memcpy(&s_kcfg, &s_kcfg_rom, sizeof(s_kcfg));
|
||
(void)memcpy(&s_bcfg, &s_bcfg_rom, sizeof(s_bcfg));
|
||
s_err_latched = 0u;
|
||
|
||
(void)memset(®, 0, sizeof(reg));
|
||
reg.name = ADC_CAL_SEC_K;
|
||
reg.p_data = &s_kcfg;
|
||
reg.p_defaults = &s_kcfg_rom;
|
||
reg.data_size = (offsetof(adc_cal_kcfg_t, valid) + 1u); /* 33:覆盖到 valid */
|
||
reg.p_keys = s_k_keys_tbl;
|
||
reg.key_count = 9u;
|
||
reg.p_cb = NULL; /* 不挂回调:RAM 副本即生效值(「数据可信」§4.4) */
|
||
if (cfg_file_register(®) != 0) {
|
||
DBG_ERROR("register '%s' FAIL (dup/full?) - calibration file values inactive",
|
||
ADC_CAL_SEC_K);
|
||
}
|
||
|
||
(void)memset(®, 0, sizeof(reg));
|
||
reg.name = ADC_CAL_SEC_B;
|
||
reg.p_data = &s_bcfg;
|
||
reg.p_defaults = &s_bcfg_rom;
|
||
reg.data_size = sizeof(s_bcfg); /* 32 */
|
||
reg.p_keys = s_b_keys_tbl;
|
||
reg.key_count = 8u;
|
||
reg.p_cb = NULL;
|
||
if (cfg_file_register(®) != 0) {
|
||
DBG_ERROR("register '%s' FAIL (dup/full?) - zero-offset file values inactive",
|
||
ADC_CAL_SEC_B);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* 函数功能:码值 → 工程量折算(「数据可信」§4.1 模型)
|
||
* 入口参数:sem - 语义通道;code - 原始码值 adc_semantic_t / int32_t
|
||
* 返 回 值:工程量浮点(未标定 = ADC 引脚电压 V;TEMP/越界 = 原样透传码值) float
|
||
* 限定条件:无(任意上下文,纯读)
|
||
* 函数说明:见 adc_cal.h 同名声明;k/b 经 s_eff_kb 合法带哨兵(越带回退 ROM)
|
||
*/
|
||
float adc_cal_apply(adc_semantic_t sem, int32_t code) {
|
||
int32_t k;
|
||
int32_t b;
|
||
|
||
if ((unsigned)sem >= (unsigned)ADC_SEM_TEMP) {
|
||
return (float)code; /* TEMP/越界:不纳入线性标定(决策 5),原样透传 */
|
||
}
|
||
(void)s_eff_kb((unsigned)sem, &k, &b);
|
||
return ((float)(code + b)) * ((float)k) * ADC_CAL_K_SCALE;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:读通道可用性标志(消费者判「能不能信」的唯一入口)
|
||
* 入口参数:sem - 语义通道 adc_semantic_t
|
||
* 返 回 值:ADC_CAL_F_VALID / ADC_CAL_F_CLIPPED 组合;TEMP/越界恒 0 uint32_t
|
||
* 限定条件:无
|
||
* 函数说明:VALID 需文件位图与 k 合法带**同时**成立(哨兵压制说谎位图,见文件头)
|
||
*/
|
||
uint32_t adc_cal_flags(adc_semantic_t sem) {
|
||
uint32_t f = 0u;
|
||
|
||
if ((unsigned)sem >= (unsigned)ADC_SEM_TEMP) {
|
||
return 0u;
|
||
}
|
||
/* VALID = 文件位图置位 且 k 合法(哨兵不落共享状态,随重载自愈) */
|
||
if (((s_kcfg.valid & (uint8_t)(1u << (unsigned)sem)) != 0u) &&
|
||
(s_kband_ok((unsigned)sem, s_kcfg.k[sem], s_bcfg.b[sem]) != 0)) {
|
||
f |= ADC_CAL_F_VALID;
|
||
}
|
||
/* CLIPPED 由**来源**派生(R5:STM32 侧单极性无偏置 → 负半周削顶)——
|
||
* V0.2 改版(N-18,8 路全接 TPAFE)后本位自动恒 0,无需改码,
|
||
* 对应「数据可信」§10「页面与 104 绑定零改动」的要求 */
|
||
if (s_rom_k_stm32((unsigned)sem) != 0) {
|
||
f |= ADC_CAL_F_CLIPPED;
|
||
}
|
||
return f;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:读通道当前生效系数(µV/码,回退后口径)
|
||
* 入口参数:sem - 语义通道 adc_semantic_t
|
||
* 返 回 值:k[µV/码];TEMP/越界返 0 float
|
||
* 限定条件:无
|
||
* 函数说明:Q16 现值 ÷ 65536 浮点还原;勿据其反推二次值(可用性看 flags)
|
||
*/
|
||
float adc_cal_k_uv(adc_semantic_t sem) {
|
||
int32_t k;
|
||
int32_t b;
|
||
|
||
if ((unsigned)sem >= (unsigned)ADC_SEM_TEMP) {
|
||
return 0.0f;
|
||
}
|
||
(void)s_eff_kb((unsigned)sem, &k, &b);
|
||
return ((float)k) / 65536.0f;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:读通道当前生效零点偏移(码值,浮点)——adc_cal_k_uv 孪生入口
|
||
* 入口参数:sem - 语义通道 adc_semantic_t
|
||
* 返 回 值:b[码值](越带时 s_eff_kb 已回 0);TEMP/越界返 0 float
|
||
* 限定条件:无(任意上下文,纯读)
|
||
* 函数说明:卡 10 的 104 b 覆盖回显 + k 单侧改写 RMW 读侧(App/algo/run_par.c)
|
||
*/
|
||
float adc_cal_b_codes(adc_semantic_t sem) {
|
||
int32_t k;
|
||
int32_t b;
|
||
|
||
if ((unsigned)sem >= (unsigned)ADC_SEM_TEMP) {
|
||
return 0.0f;
|
||
}
|
||
(void)s_eff_kb((unsigned)sem, &k, &b);
|
||
return ((float)b);
|
||
}
|
||
|
||
/*
|
||
* 函数功能:整定入口——写通道系数与零点,并置位 VALID(「数据可信」卡 4)
|
||
* 入口参数:sem - 语义通道;k_q16 - 系数(µV/码×65536);b_codes - 零点(码值)
|
||
* 返 回 值:0 - 成功;-1 - 参数非法/越出合法带(RAM 不动,[ERR] 留痕) int
|
||
* 限定条件:整定路径上下文(defaultTask 整定/标定链;iec104Task 经 run_par
|
||
* 直通为卡 10 授权写者,单字原子契约同 §4.4);落盘由属主经 cfg_file_save
|
||
* 函数说明:见 adc_cal.h 同名声明
|
||
*/
|
||
int adc_cal_set(adc_semantic_t sem, int32_t k_q16, int32_t b_codes) {
|
||
if ((unsigned)sem >= (unsigned)ADC_SEM_TEMP) {
|
||
return -1;
|
||
}
|
||
if (s_kband_ok((unsigned)sem, k_q16, b_codes) == 0) {
|
||
DBG_ERROR("set ch=%u rejected: k_q16=%ld b=%ld out of ROM band [0.5x,2x]/|b|<=%ld",
|
||
(unsigned)sem, (long)k_q16, (long)b_codes, (long)ADC_CAL_B_MAX);
|
||
return -1;
|
||
}
|
||
s_kcfg.k[sem] = k_q16;
|
||
s_bcfg.b[sem] = b_codes;
|
||
s_kcfg.valid |= (uint8_t)(1u << (unsigned)sem);
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:两点标定公式(卡 12 的算术核,纯函数无状态)
|
||
* 入口参数:c_lo/c_hi、v_lo_uv/v_hi_uv、p_k_q16/p_b 见 adc_cal.h 同名声明
|
||
* 返 回 值:0 成功 / -1 参数或斜率非法 / -2 零点越 ±B_MAX int
|
||
* 限定条件:无(int64 中间量,主机可测;台架注入待跑)
|
||
*/
|
||
int adc_cal_two_point(int32_t c_lo, int32_t c_hi, int32_t v_lo_uv, int32_t v_hi_uv,
|
||
int32_t *p_k_q16, int32_t *p_b) {
|
||
long long dc;
|
||
long long dv;
|
||
long long kq;
|
||
long long bb;
|
||
|
||
if ((p_k_q16 == NULL) || (p_b == NULL)) {
|
||
return -1;
|
||
}
|
||
dc = (long long)c_hi - (long long)c_lo;
|
||
dv = (long long)v_hi_uv - (long long)v_lo_uv;
|
||
if ((dc <= 0LL) || (dv <= 0LL)) {
|
||
return -1; /* 斜率必须为正:码与电压同向,反向 = 映射/接线错 */
|
||
}
|
||
kq = ((dv << 16) + (dc >> 1)) / dc; /* (v_hi−v_lo)×65536/dc,四舍五入(dc>0) */
|
||
if ((kq <= 0LL) || (kq > 100000000LL)) {
|
||
return -1; /* 绝对合理域上界 1526 µV/code:越界 = 单位/量级错 */
|
||
}
|
||
bb = (((long long)v_lo_uv) << 16) / kq - (long long)c_lo;
|
||
if ((bb > (long long)ADC_CAL_B_MAX) || (bb < -(long long)ADC_CAL_B_MAX)) {
|
||
return -2; /* 零点异常 → 先查前端,别用系数凑(§8 风险表) */
|
||
}
|
||
*p_k_q16 = (int32_t)kq;
|
||
*p_b = (int32_t)bb;
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:通道码值域贴轨带门限(L5-2 判定的门限来源,按 FS 百分比)
|
||
* 入口参数:sem - 语义通道;p_lo_th/p_hi_th - 输出下/上轨带界 int32_t *
|
||
* 返 回 值:0 - 已给出门限;-1 - TEMP/越界/参数空(不做贴轨监视) int
|
||
* 限定条件:无
|
||
* 函数说明:状态机在 adc_health_rail_watch();本函数只供门限,无状态
|
||
*/
|
||
int adc_cal_rail_ths(adc_semantic_t sem, int32_t *p_lo_th, int32_t *p_hi_th) {
|
||
if ((p_lo_th == NULL) || (p_hi_th == NULL) ||
|
||
((unsigned)sem >= (unsigned)ADC_SEM_TEMP)) {
|
||
return -1; /* TEMP(热敏非线性,不判「轨」)与越界不做监视 */
|
||
}
|
||
if (s_rom_k_stm32((unsigned)sem) != 0) {
|
||
*p_hi_th = (int32_t)((4095L * 98L) / 100L); /* 4013 = 98 % FS */
|
||
*p_lo_th = (int32_t)((4095L * 2L) / 100L); /* 81 = 触底带(削顶签名) */
|
||
} else {
|
||
*p_hi_th = 32112L; /* +98 % 半量程 */
|
||
*p_lo_th = -32112L; /* -98 % 半量程 */
|
||
}
|
||
return 0;
|
||
}
|