一句话: Cortex-M3 没有硬件浮点float 算一次几十条指令。定点数用整数存小数——像用分代替元——加减直接算乘法多一步移位。3 条指令干完 float 几十条指令的活。适合谁读适合嵌入式开发者、单片机初学者及遇到类似问题的工程师故事收银员不用元算账你去超市买了三样东西薯片 3.50 元 可乐 2.25 元 纸巾 1.25 元收银员不会列竖式3.50 2.25 1.25 ─────── 7.00他算的是350 分 225 分 125 分 700 分 7.00 元先把小数全转成整数用整数算完最后再转回去。计算机做定点运算干的就是同一件事——只不过它放大的是 256 倍、65536 倍这种 2 的幂次因为 CPU 移位比除法快一万倍。为什么要折腾直接用 float 不行吗你的 ADuCM431 是 Cortex-M3没有硬件 FPU。// 你写这一行 float current adc_code * 0.000389f;编译器背后干了什么它调了软浮点库调用 __aeabi_fmul浮点乘法约 20 条指令 调用 __aeabi_f2uiz浮点转整数约 10 条指令一行代码 几十条指令。主循环每 100ms 跑一次8 路通道 × 3 个公式 24 次浮点运算 好几百条指令。CPU 的时间全在算 0.000389。换成定点// 0.000389 ≈ 255 / 65536 uint32_t current (adc_code * 255U) 16;一行代码 1 条乘法 1 条移位 2 条指令。核心原理约定小数点在哪用一个 16 位整数代表小数约定前 8 位是整数后 8 位是小数存的值: 384 把它当成元和分来读: 384 ÷ 256 1 → 整数部分 384 % 256 128 → 128/256 0.5 实际值 1.5就这么简单。存的是普通整数 384但你和程序约定好了——读的时候要 ÷ 256。UQ 格式命名UQm.nU 无符号m 整数位数n 小数位数。格式放大倍数范围精度UQ12.4×160 ~ 4095.93750.0625UQ8.8×2560 ~ 255.9960.0039UQ0.16×655360 ~ 0.999980.000015UQ16.16×655360 ~ 65535.999980.000015小数位越多精度越高但整数范围越小。你的项目里 ADC 是 12 位0~4095用 UQ16.1632 位最合适——又装得下、又够精确。四个基本运算规定所有值都先 ×65536 变成整数算完再 ÷65536。加法直接加// 1.5 2.25 3.75 uint32_t a 1.5f * 65536; // 98304 uint32_t b 2.25f * 65536; // 147456 uint32_t c a b; // 245760 float r c / 65536.0f; // 3.75 ✓乘法乘完要缩回来两个 ×65536 的数相乘结果被放大了 65536×65536 倍所以要除掉一次// 1.5 × 2.25 3.375 uint32_t a 1.5f * 65536; // 98304 uint32_t b 2.25f * 65536; // 147456 uint32_t c ((uint64_t)a * (uint64_t)b) 16; // 乘完右移 16 位 float r c / 65536.0f; // 3.375 ✓关键点乘积用 64 位存uint64_t因为 32 位 × 32 位 64 位 16是除以 65536把多放大的部分消掉除法被除数先放大// 1.5 ÷ 2.25 0.6667 uint32_t a 1.5f * 65536; // 98304 uint32_t b 2.25f * 65536; // 147456 uint32_t c ((uint64_t)a 16) / b; // 先左移再除 float r c / 65536.0f; // 0.6667 ✓被除数先左移放大再做整数除法结果才够精度。不然整数除法会截断小数部分。Q 格式转换不同模块可能用不同 Q 格式切换只需移位// Q12 → Q16: 左移 4 位 uint32_t q16 q12 4; // Q16 → Q12: 右移 4 位 uint32_t q12 q16 4;实战ADC 算偏置电流你的项目里偏置电流公式是I_bias (A) ADC_CODE × 0.000389CMIS 要求单位是 100μA所以还要 ×10000// 浮点写法慢 float bias_A adc_code * 0.000389f; uint16_t bias_100uA (uint16_t)(bias_A * 10000.0f); // 定点写法快 // 系数 0.000389 ≈ 25 / 65536 // bias_100uA adc_code × 25 / 65536 × 10000 // adc_code × 250000 / 65536 // adc_code × 15625 / 4096 uint32_t bias_100uA ((uint32_t)adc_code * 15625UL) 12;一条乘法 一条移位。没有浮点没有除法的延迟。再举个例子ADC 算电压电路VREF(2.5V) → 10KΩ 固定电阻 → ADC → NTC → GNDR_ntc 10000 × ADC / (4095 - ADC)定点版// 用 UQ16.16放大 65536 倍 uint32_t r_ntc_uq16 (10000UL * (uint32_t)adc_code * 65536UL) / (4095UL - (uint32_t)adc_code); // 读数: r_ntc r_ntc_uq16 / 65536总结类比定点运算收银员用分记账程序用整数存小数350 分 3.50 元× 256 整数加减分直接加减同 Q 格式直接加减乘法(分×分)÷100乘完再右移 n 位除法(分×100)÷分先左移 n 位再除三句话存的时候小数 × 65536 → 整数算的时候加减直接算乘法多一步右移读的时候整数 ÷ 65536 → 小数没有浮点单元不是问题——用整数假装小数又快又准。有用的话点个收藏下次调试直接用。有问题欢迎评论区交流看到了都会回。