当前位置: 首页 > news >正文

BLDC中的Q15

介绍一下Q15格式化是什么,其目的是为了什么,最好举例,并能用易懂的方式表述

好的,我用一个非常易懂的方式来解释 Q15格式化


一句话理解 Q15

Q15 是一种在整数上“假装”有小数的方法,它让只能处理整数的CPU(比如很多单片机)也能进行高效的小数运算。


为什么需要 Q15?

  1. 硬件限制:很多微控制器(MCU)或数字信号处理器(DSP)没有硬件浮点运算单元(FPU),直接计算像 0.008 * 0.5 这样的浮点数会非常慢,消耗大量CPU资源。

  2. 效率需求:电机控制(如FOC算法)需要极高的实时性,运算必须在微秒级别完成。整数运算的速度远远快于软件模拟的浮点运算。

Q15 就是为了解决这个矛盾而生的:用快速的整数运算,来得到近似的小数结果


Q15 的具体规则是什么?

规则很简单:把一个数乘以 32768(即 2¹⁵),然后取整。

  • “Q15” 这个名字的由来

    • Q 表示 “Quotient”(商),代表这是一个定点数格式。

    • 15 表示 小数点后有15位二进制数

  • 数值范围:由于我们使用一个有符号的16位整数(int16_t,范围从 -32768 到 +32767)来存储这个数,所以Q15能表示的范围大约是 -1.0 到 +0.999969

    • 32767 / 32768 ≈ 0.999969

    • -32768 / 32768 = -1.0


举例说明

让我们用你代码中的例子来演算一下。

例子1:定义阶段

你的代码中有:

c
 
 
#define Q15(A) A*32767   // 注意:这里用的是32767,而不是32768,是为了防止溢出,是常见做法
#define D_CURRCNTR_PTERM Q15(0.008)
  1. 转换0.008 * 32767 = 262.136

  2. 取整:由于宏定义是直接替换,编译器在预处理后会看到 262(或 263,取决于编译器如何处理小数)。

  3. 存储:所以,常数 D_CURRCNTR_PTERM 在单片机内存中实际存储的值就是整数 262

这个 262 就是 0.008 的 Q15格式表示


例子2:使用阶段(乘法运算)

假设我们的电流误差(error)也是Q15格式,值为 0.5 的Q15格式,也就是 0.5 * 32767 = 16384(取整)。

现在,我们要计算比例项输出:output = Kp * error,其中 Kp 就是我们的 D_CURRCNTR_PTERM (262)。

  • 浮点运算(我们想要的)0.008 * 0.5 = 0.004

  • Q15整数运算(实际在MCU里发生的)
    output = 262 * 16384; // 两个Q15格式的数相乘

    这个乘法的结果是:262 * 16384 = 4,292,608

  • 关键步骤:重新调整小数点
    两个Q15数(可以理解为 Q15.15)相乘,结果会变成一个 Q30.30 格式的数(小数点后有30位)。我们需要把它变回 Q15.15
    方法就是:将结果右移15位(相当于除以 32768)。

    output = 4292608 >> 15 = 4292608 / 32768 ≈ 131

  • 解读结果
    现在我们得到了 131。这个 131 在Q15世界里代表多大呢?
    将它转换回浮点数:131 / 32768 ≈ 0.003998

  • 对比

    • 浮点运算结果:0.004

    • Q15运算结果:~0.003998

看到了吗?它们几乎相等! 这个微小的误差在电机控制中是完全可接受的。


总结与类比

你可以把 Q15 格式想象成一种 “货币兑换”

  • 浮点数世界:就像不同的货币(美元、欧元、人民币)。

  • Q15整数世界:就像大家都统一使用 “分” 作为单位来计算。

    • 1美元 = 100美分

    • 1欧元 = 100欧分

    • 0.5美元 = 50美分

    • 0.008 美元 = 0.8 美分,但我们没有“0.8美分”的硬币,所以四舍五入成 1 美分(这就像我们的取整过程)。

当你要计算 0.008美元 * 0.5 时:

  1. 先把它们都换成“分”:1分 * 50分

  2. 得到 50(单位变成了“分²”)。

  3. 再换回正常的“元”:50 / 100 = 0.5分,也就是 0.005元

目的:在整个计算过程中,我们只用了整数运算,避免了慢速的“汇率计算”(浮点运算),最终结果又基本正确。

在电机控制中的目的

  • 性能:极大地加快了PID控制器、Clark/Park变换等算法的计算速度。

  • 确定性:整数运算的时间是固定的,而浮点运算可能不稳定,这对于实时系统至关重要。

  • 便携性:可以在任何低端MCU上实现复杂控制算法。

http://www.hskmm.com/?act=detail&tid=27717

相关文章:

  • 华为 AP hw_manage 离线管理 Wi-Fi 密码
  • 雪落 - L
  • 251009
  • Mybatis笔记
  • PluginMonitor - Typecho 插件监控工具
  • LibreChat-图文并茂手把手教你搭建自己的AI机器人 Step-by-step guide to building your own chatbot
  • NOISG 2025 Prelim
  • STM32 教程
  • 先进反应堆:BWRX-300
  • ch58x/ch59x系列芯片Indication添加
  • Lab 4 Challenge - Sum of Proper Elements
  • perl经典hash解决问题
  • LCR 129. 字母迷宫
  • Ignite3 竟然变成分布式数据库了!
  • NUIST 《程序设计基础》 实验1
  • 10.9总结
  • [MIT 6.828] Lab 1 C, Assembly, Tools, and Bootstrapping
  • WCH低功耗蓝牙系列芯片usb烧录故障排查
  • 使用docker构建.net api镜像及nginx反向代理 - binzi
  • 利用sprintf与snprintf巧妙实现数值变量转换为字符串型
  • Helmholtz-Gibbs自由能与熵弹性
  • 日志|电话号码的字母组合|子集|回溯
  • Docker实用篇(初识Docker,Docker的基本操作,Dockerfile自定义镜像,Docker-Compose,Docker镜像仓库) - a
  • ROIR 2023
  • Rust 的验证码图像识别系统设计与实现
  • 【题解】P12992 [GCJ 2022 #1C] Intranets
  • ysyx:pa3.1批处理系统
  • C 语言的验证码图像识别系统实现
  • Nginx典型流控配置示例
  • 基于 C 语言的验证码图像识别系统实现