ARM CMSIS-DSP Q格式

一、来源

Q 格式的 "Q" 最早源于 TI 的定点数表示法,ARM 在 CMSIS 中标准化,成为嵌入式定点运算的通用规范。

Q 格式是嵌入式领域的定点数表示方法 ,本质是用整数来模拟小数运算 ------ 通过预先约定小数点在二进制数中的固定位置,让普通整数具备表示小数的能力。

对比易理解的浮点数(如 float/double),Q 格式的核心是 "定点":小数点位置一旦约定就不再改变,而浮点数是"浮点":小数点位置随指数位动态变化。

浮点数的二进制存储科普:

一、先从十进制科学计数法入手:指数和尾数的通俗类比

我们平时用的十进制科学计数法,就是把任意数拆成「尾数 + 指数」的形式,这是浮点数指数 / 尾数的原型:

通用形式:

数值尾数基数指数

  • 十进制基数是10 ,二进制浮点数基数是2
  • 尾数 :表示数的有效数字,通常归一化为「1.xxxxx」的形式(保证精度最高);
  • 指数 :表示小数点的移动位数 / 缩放倍数,正指数右移小数点,负指数左移小数点。
直观例子:
  • 123.45=1.2345×102 → 尾数 = 1.2345,指数 = 2(小数点右移 2 位);
  • 0.00105=1.05×10−3 → 尾数 = 1.05,指数 =-3(小数点左移 3 位);
  • 5=1.0×101 → 尾数 = 1.0,指数 = 1(整数也归一化)。

核心尾数决定数的精度,指数决定数的大小 / 小数点位置,浮点数的二进制存储,就是把这个逻辑搬到二进制中,并做了硬件适配的优化。

二、二进制浮点数的指数和尾数(以嵌入式最常用的32 位单精度 float为例)

32 位 float 是 IEEE 754 标准的核心类型,嵌入式 MCU(STM32/N32 等)的浮点数均遵循此标准,它将 32 位二进制严格划分为 3 部分,其中后两部分就是指数和尾数,整体结构:

plaintext

复制代码
32位float:[符号位(S)·1位] + [指数位(E)·8位] + [尾数位(M)·23位]
各部分作用(结合二进制科学计数法):

二进制浮点数的通用表示公式:数值逐个拆解符号位、指数位、尾数位 的实际含义,重点讲指数尾数

1. 符号位(S):仅表示正负,和指数 / 尾数无关
  • S=0 → 正数,S=1 → 负数;
  • 作用:通过(−1)S实现正负表示,无需给指数 / 尾数单独加符号位,简化硬件设计。
2. 指数位(E):8 位无符号数,代表二进制的指数偏移量

浮点数的实际指数 并非直接存指数位的二进制值,而是做了 **+127 的偏移 **(也叫偏置值 ,8 位指数的偏置值固定为 127),原因是为了用无符号数表示正负指数(硬件处理无符号数更高效)。

  • 实际指数 真实存储的指数位二进制值;
  • 指数位范围:0~255 → 实际指数范围:−127 +128;
  • 作用:决定二进制小数点的浮动位置,对应十进制科学计数法中「10 的几次方」,是浮点数 "浮点" 的核心。
3. 尾数位(M):23 位无符号数,代表二进制尾数的小数部分

这是最容易理解偏差的点:浮点数的尾数采用 **「隐藏最高位 1」的归一化设计(也叫 隐含位 **),目的是用 23 位存储 24 位有效精度,提升硬件利用率。

  • 二进制尾数的完整形式是 1.M(1 是隐藏位,M 是尾数位的 23 位小数);
  • 尾数位 M 的范围:000...000 ~ 111...111 → 完整尾数范围:1.000...000 1.111...111(二进制);
  • 作用:表示数的有效二进制数字尾数位的位数决定浮点数的精度(23 位 + 1 位隐藏位 = 24 位有效精度)。

二、为什么需要Q格式?

Q 格式的诞生完全是为了适配嵌入式 MCU 的硬件特性,解决浮点数在嵌入式场景中的致命问题,这也是 ARM 官方为 Cortex-M 系列专门定义 Q 格式的原因,核心解决的问题有 3 个:

痛点 1:多数低端 MCU 无硬件浮点单元(FPU),浮点数运算效率极低

Cortex-M0/M0+/M3等低端 MCU无硬件 FPU ,浮点数(float/double)运算完全依靠软件模拟 ------ 编译器将浮点数运算拆解为数十条整数运算指令,耗时是整数运算的几十倍甚至上百倍

而 Q 格式本质是整数运算 :所有 Q 格式的小数计算,最终都能转换为普通的整数加减乘除,仅需在运算后根据 Q 格式规则做简单的移位 / 归一化,运算效率和整数完全一致,无需任何硬件 FPU 支持。

痛点 2:浮点数占用更多内存,不符合嵌入式 "资源紧缺" 的特点

  • 浮点数(float)占4 字节 ,double 占8 字节
  • Q15 仅占2 字节,Q31(32 位定点数,31 位小数)也仅占 4 字节,和 float 相同但运算效率更高。

嵌入式 MCU 的 RAM/Flash 通常以 KB 为单位(如 STM32F103 仅 20KB RAM、64KB Flash),Q 格式能大幅节省内存占用,尤其适合批量存储数据(如 Q15 正弦表 256 点仅 512 字节)。

痛点 3:浮点数的 "非确定性",不适合嵌入式实时控制系统

浮点数运算存在精度漂移、舍入误差不可控 的问题,且软件模拟的浮点数运算耗时不固定(不同数值的运算指令数不同)。

而嵌入式实时系统(如电机 FOC、工业控制、信号调制)对运算耗时的确定性精度的可预测性要求极高:

  • Q 格式的误差是量化误差(由小数位位数决定,如 Q15 的量化步长1/32767≈3.05×10−5),固定且可预测;
  • Q 格式运算的耗时完全固定,和运算数值无关,能保证实时系统的时序稳定性。

三、ARM CMSIS-DSP Q格式定义

Q 完整格式表示为:Qm.n,表示数据用 m 比特表示整数部分,n 比特表示小数部分,共需要 m+n+1 位来表示这个数据,多余的一位用作符合位。

ARM CMSIS-DSP中,一般整数部分m都是0,因此,一般简记为Qn。

所有 Q 格式均为有符号数 ,最高位固定为符号位(0 正 1 负),剩余位数按 Qn 表示n 位小数的定点数格式,如 Q7=7 位小数,Q15=15 位小数,Q31=31 位小数;

Qn 格式的实际物理值 = 整数存储值 / 2^n

Q15 的实际值 = 存储值 / 2^15 = 存储值 / 32768(注:因有符号数补码特性,实际用 32767 近似,误差可忽略);

Q7 的实际值 = 存储值 / 2^7 = 存储值 / 128。

ref:

https://arm-software.github.io/CMSIS-DSP/latest/index.html

相关推荐
s_daqing5 小时前
arm的ubuntu启动node
linux·arm开发·ubuntu
CQ_YM16 小时前
ARM之I2C
arm开发·单片机·嵌入式硬件·嵌入式
BigALiang18 小时前
再探ARMimxu6ll
arm开发
2401_859049081 天前
lvgl移植到Linux踩坑
linux·运维·arm开发·elasticsearch·嵌入式·ubantu
s09071361 天前
基于ZYNQ-7000 ARM端的水声声呐图像压缩方案
arm开发·zynq·图像压缩·水声工程
飞易通2 天前
WIFI6 SOC模块介绍解析
arm开发·wifi模块·soc模块
松涛和鸣2 天前
DAY66 SPI Driver for ADXL345 Accelerometer
linux·网络·arm开发·数据库·驱动开发
代码游侠2 天前
学习笔记——LCD技术详解
arm开发·笔记·嵌入式硬件·学习·架构
切糕师学AI2 天前
ARM汇编器与GNU汇编器:详细介绍与核心区别
arm开发·gnu·汇编器