DA 模块踩坑
坑 1:整数除法导致小数精度丢失
第十四届国赛 · 发现者:Water
现象
DA 输出值全部偏低或异常,明显与预期不符。
原因
调用 da_mix_10x(uchar) 时直接用整数除以 10,C 语言整数除法会截断小数部分:
// 错误写法:结果为整数,小数全部丢失
da_mix_10x(value / 10);
解决方法
强制转换为浮点数再做除法:
// 正确写法:保留小数部分
da_mix_10x(value / 10.0f);
举一反三
只要参与除法的两个操作数都是整型,结果就是整型。需要浮点结果时,至少让一侧是浮点数(写 10.0f 或显式强转 (float)value)。
坑 2:uint 类型算术下溢导致 DA 值异常
第十四届国赛 · 发现者:Water
现象
DA 输出值在某些测评点严重偏大(如本应输出 -50 相关结果,实际输出接近 65486 对应的错误值)。

原因
一次函数取点时选了 (90, 5),公式为 y = k * (x - 90) + 5。
测评时 x 的实际值往往小于 90,而 x 是 unsigned int 类型,x - 90 发生算术下溢:
unsigned int x = 40;
// 错误:40 - 90 在 uint 下不是 -50,而是 65486
y = k * (x - 90) + 5;
解决方法
方法一(推荐):取点时选 x 轴最小值那个点,保证 x - x0 永远为正:
// 取 (10, Vol),测评时 x >= 10,不会下溢
y = k * (x - 10) + Vol;
方法二:对 x 强制转换为有符号整型:
y = k * ((int)x - 90) + 5;
举一反三
uint / uchar 类型做减法时,只要被减数可能小于减数,就会下溢。常见于:
- 一次函数插值取点
- 传感器量程映射
- 时间差计算(如 TH/TL 拼合后做差)
建议:一次函数取点时,永远取 x 轴最小的那个已知点。
坑 3:ADC 满量程时缺少钳位保护导致 DA 输出边界异常
第十三届国赛 · 发现者:左岚
现象
传感器 ADC 读数接近满量程时,DA 输出值不符合题目要求的最大值钳位,或输出行为与预期不一致。
原因
ADC 原始值 ≥ 255 时,直接用浮点公式计算湿度,数学上不会超过 100,但缺少对满量程的明确钳位,边界语义不清晰,实测时存在隐患:
// 缺少钳位保护:依赖浮点公式隐式限幅,满量程行为未明确定义
Shidu = temp * 20 / 51.0f;
解决方法
在 ADC 读值后加显式钳位判断:
// 正确写法:ADC 满量程时强制钳位为 100
if (AD_3_Data >= 255)
Shidu = 100;
else
Shidu = AD_3_Data * 20 / 51.0f;
举一反三
- ADC 做量程映射时,务必同时处理满量程(255)和零点(0)两个边界
- 钳位保护不仅防止数值越界,也让代码对边界行为的意图一目了然
- 题目若规定某阈值以上输出固定值,应优先用
if显式处理,而非依赖数学公式隐式限幅