Files
STM32F4-Base/App/algo/adc_cal.c
T
wandering1 8c72698666 feat(运行参数): 卡10 run_par真源收编+104段0x8020~0x8058读写映射(道D M6-①)
新增 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 逐文件自查通过。
2026-10-25 13:15:41 +08:00

397 lines
17 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.
/*
* 模块名称:通道标定与量纲折算(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(&reg, 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(&reg) != 0) {
DBG_ERROR("register '%s' FAIL (dup/full?) - calibration file values inactive",
ADC_CAL_SEC_K);
}
(void)memset(&reg, 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(&reg) != 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;
}