DA模块踩坑记录

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 对应的错误值)。

5ead2a2992da6622f785c43a5dbaef71

原因

一次函数取点时选了 (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 显式处理,而非依赖数学公式隐式限幅
1 个赞