/* A16:NTC 换算(ntc.h)。两条最要紧的: ⭐ 方向 —— NTC 在下臂,**越热电压越低**;写反了闭环照样有数,只是反着转; ⭐ 开路 / 短路判「读不到」—— 读不到时 t_thermal 会满速(§10.10), 而把开路算成 −40 °C 的后果是「风扇按最低速转、机器在烤」。 */ #include "ntc.h" #include "unity.h" void setUp(void) {} void tearDown(void) {} /* 分压端电压(与 ntc.c 的反算互为逆运算,单独写一遍免得自己证明自己)。 */ static int32_t mv_at(uint32_t ohm) { return (int32_t)(3300ull * ohm / (NTC_PULLUP_OHM + ohm)); } static void test_table_points(void) { int32_t mc = 0; TEST_ASSERT_TRUE(ntc_mc_from_ohm(10000, &mc)); TEST_ASSERT_EQUAL_INT32(25000, mc); TEST_ASSERT_TRUE(ntc_mc_from_ohm(4161, &mc)); TEST_ASSERT_EQUAL_INT32(50000, mc); TEST_ASSERT_TRUE(ntc_mc_from_ohm(195652, &mc)); TEST_ASSERT_EQUAL_INT32(-40000, mc); TEST_ASSERT_TRUE(ntc_mc_from_ohm(531, &mc)); TEST_ASSERT_EQUAL_INT32(125000, mc); /* 格内插值:10000 与 8315 的正中间 ≈ 27.5 °C。 */ TEST_ASSERT_TRUE(ntc_mc_from_ohm((10000 + 8315) / 2, &mc)); TEST_ASSERT_INT32_WITHIN(20, 27500, mc); } /* ⭐ 方向:电压从高扫到低,温度必须一路**不降**;电阻从大到小同理。 */ static void test_hotter_means_lower_voltage(void) { int32_t prev = -1000000, mc = 0; int n = 0; for (int32_t mv = 3300 - NTC_RAIL_MARGIN_MV - 1; mv > NTC_RAIL_MARGIN_MV; mv -= 7) { if (ntc_mc_from_mv(mv, 3300, &mc)) { TEST_ASSERT_TRUE_MESSAGE(mc >= prev, "电压降低时温度必须升高(NTC 在下臂)"); prev = mc; n++; } } TEST_ASSERT_TRUE(n > 300); /* 两个现实点:25 °C 正好一半(1650 mV);60 °C ≈ 0.76 V。 */ TEST_ASSERT_TRUE(ntc_mc_from_mv(1650, 3300, &mc)); TEST_ASSERT_INT32_WITHIN(100, 25000, mc); TEST_ASSERT_TRUE(ntc_mc_from_mv(mv_at(3014), 3300, &mc)); TEST_ASSERT_INT32_WITHIN(200, 60000, mc); } /* ⭐ 开路(贴 +3V3)/ 短路(贴地)/ 表外:一律「读不到」,而且不动输出。 */ static void test_open_and_short_are_not_temperatures(void) { int32_t mc = 12345; TEST_ASSERT_FALSE(ntc_mc_from_mv(3300, 3300, &mc)); TEST_ASSERT_FALSE(ntc_mc_from_mv(3290, 3300, &mc)); TEST_ASSERT_FALSE(ntc_mc_from_mv(0, 3300, &mc)); TEST_ASSERT_FALSE(ntc_mc_from_mv(10, 3300, &mc)); TEST_ASSERT_FALSE(ntc_mc_from_mv(-5, 3300, &mc)); TEST_ASSERT_FALSE(ntc_mc_from_mv(1650, 0, &mc)); TEST_ASSERT_FALSE(ntc_mc_from_ohm(200000, &mc)); /* < −40 °C */ TEST_ASSERT_FALSE(ntc_mc_from_ohm(500, &mc)); /* > 125 °C */ TEST_ASSERT_EQUAL_INT32(12345, mc); TEST_ASSERT_FALSE(ntc_mc_from_mv(1650, 3300, NULL)); } /* 比例式:+3V3 偏 1 %(3.267 V),只要把实际值传进来,读数不变; 传错成 3300 时误差约 0.6 °C(25 °C 附近)—— 对风扇闭环无所谓。 */ static void test_ratiometric(void) { int32_t a = 0, b = 0; TEST_ASSERT_TRUE(ntc_mc_from_mv(1650, 3300, &a)); TEST_ASSERT_TRUE(ntc_mc_from_mv(1634, 3267, &b)); TEST_ASSERT_INT32_WITHIN(50, a, b); TEST_ASSERT_TRUE(ntc_mc_from_mv(1634, 3300, &b)); TEST_ASSERT_INT32_WITHIN(700, a, b); } int main(void) { UNITY_BEGIN(); RUN_TEST(test_table_points); RUN_TEST(test_hotter_means_lower_voltage); RUN_TEST(test_open_and_short_are_not_temperatures); RUN_TEST(test_ratiometric); return UNITY_END(); }