文件
phonerail/firmware/main/ntc.c
T
zhou yang和Claude Opus 5.5 c37c08aa43 固件 A16:风扇闭环接进任务体 + NTC / TACH 真实采样(已上板)
- ntc.{h,c}(宿主机可测):分压端 mV → Ω → NCP18XH103F03RB 的 R-T 表插值;
  开路 / 短路 / 表外一律「读不到」(t_thermal 因此满速)
- thermal_esp.{h,c}(仅 IDF):ADC1 oneshot + 曲线校准读两路 NTC;两个 PCNT 单元数 TACH 边沿
- app_main:task_thermal 任务体、t_thermal_init 放在上电恢复之前、status 带热管理快照
- test_ntc.c 4 例;全工程 429 例全绿;版本 0.1.0-a16
- 板 B:两路 NTC 38.2 / 34.0 °C;风扇两路 rpm 0 报停转(拉满电流不涨,疑未插风扇,待确认)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 13:31:32 +08:00

54 行
2.3 KiB
C
原始文件 Blame 文件历史

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
/* NTC 换算。电路与出处见 ntc.h。 */
#include "ntc.h"
#include <stddef.h>
/* NCP18XH103F03RB 的 R-T 表(Murata 规格书,−40 ~ 125 °C,5 °C 一格),单位 Ω。
⚠️ 单调**递减**是这张表唯一不能破的性质 —— `test_ntc.c` 逐格查。
抽查:25 °C = 10000(标称);50 °C = 4161 与 B3380 公式算出的 4160 吻合。 */
#define NTC_T0_MC (-40000)
#define NTC_STEP_MC 5000
static const uint32_t k_ohm[] = {
195652, 148171, 113347, 87559, 68237, 53650, 42506, 33892, /* −40 … −5 */
27219, 22021, 17926, 14674, 12081, 10000, 8315, 6948, /* 0 … 35 */
5834, 4917, 4161, 3535, 3014, 2586, 2228, 1925, /* 40 … 75 */
1669, 1452, 1268, 1110, 974, 858, 758, 672, /* 80 … 115 */
596, 531, /* 120, 125 */
};
#define NTC_N ((int)(sizeof(k_ohm) / sizeof(k_ohm[0])))
_Static_assert(NTC_N == 34, "表应当覆盖 −40 ~ 125 °C,5 °C 一格");
bool ntc_mc_from_ohm(uint32_t ohm, int32_t *milli_c)
{
if (milli_c == NULL || ohm > k_ohm[0] || ohm < k_ohm[NTC_N - 1]) {
return false;
}
for (int i = 0; i < NTC_N - 1; i++) {
const uint32_t hi = k_ohm[i]; /* 较冷的一端,电阻大 */
const uint32_t lo = k_ohm[i + 1]; /* 较热的一端 */
if (ohm <= hi && ohm >= lo) {
/* 格内按电阻线性插值。分子最大 190000 × 5000 ≈ 9.5e8,int64 稳妥。 */
const int64_t frac = (int64_t)(hi - ohm) * NTC_STEP_MC / (int64_t)(hi - lo);
*milli_c = NTC_T0_MC + i * NTC_STEP_MC + (int32_t)frac;
return true;
}
}
return false; /* 走不到:上面的范围判断已经把表外挡掉了 */
}
bool ntc_mc_from_mv(int32_t mv, int32_t vref_mv, int32_t *milli_c)
{
if (milli_c == NULL || vref_mv <= 2 * NTC_RAIL_MARGIN_MV) {
return false;
}
if (mv < NTC_RAIL_MARGIN_MV || mv > vref_mv - NTC_RAIL_MARGIN_MV) {
return false; /* 贴地 = 短路,贴 +3V3 = 开路:都不是温度 */
}
/* 下臂分压:mv / vref = R / (Rpu + R) ⇒ R = Rpu × mv / (vref − mv)。 */
const uint64_t ohm = (uint64_t)NTC_PULLUP_OHM * (uint64_t)mv / (uint64_t)(vref_mv - mv);
if (ohm > 0xFFFFFFFFull) {
return false;
}
return ntc_mc_from_ohm((uint32_t)ohm, milli_c);
}