没有DSP的浮点单元不能进行浮点运算?

简介: 没有DSP的浮点单元不能进行浮点运算?

最近在项目上需要控制直流无刷电机,使用到FOC及PID算法,进行FOC运算的时候需要用到三角函数和反三角函数,因此不可避免的就是浮点数的运算,而使用的MCU不带有浮点单元,因此需要使用Q格式来简化,提高计算速度。后期等项目结束后准备来详细分享一下FOC算法的实现,控制三相无刷直流电机,进而可以拓展使用机器人的关节电机及其驱动。今天的重点不在这里,还是回归主题介绍一Q格式以及其如何实现浮点数(定点数)的运算。


Q格式

Q格式是二进制的定点数格式,相对于浮点数,Q格式指定了相应的小数位数和整数位数,在没有浮点运算的平台上,可以更快地对浮点数据进行处理,以及应用在需要恒定分辨率的程序中(浮点数的精度是会变化的);需要注意的是Q格式是概念上小数定点,通过选择常规的二进制数整数位数和小数位数,从而达到所需要的数值范围和精度。

定点数:小数点位置为确定的。

浮点数:小数点位置可以改变。


Q数据的表示
a) 范围和精度

定点数通常表示为Qm.n,其中m为整数个数,n为小数个数,其中最高位位符号位并且以二进制补码的形式存储;

       

             


无符号的用UQm.n表示;

范围:[02m−2n]

精度:2n

b) 推导

无符号Q格式数据的推导
这里以一个16位无符号整数为例,UQ9.7所能表示的最大数据的二进制形式如下图所示;

所以不难看出,UQ9.7的范围大小和精度;
根据等比数列求和公式得到,整数域最大值如下:

Sumi=28+27+26+25+24+23+22+21+20=291

小数域最大值如下:

Sumf=21+22+23+24+25+26+27=127

因此UQ9.7的范围满足 [0,2927]

有符号Q格式数据的推导
这里以一个16位有符号整数为例,UQ9.7所能表示的最大数据的二进制形式如下图所示;

所以不难求出,UQ9.7的范围大小和精度;
根据等比数列求和公式得到,整数域最大值如下:

Sumi=27+26+25+24+23+22+21+20 = 281

小数域最大值如下:

Sumf=21+22+23+24+25+26+27 = 127

因此Q9.7最大能表示的数为:2827

Q9.7所能表示的最小数据的二进制形式如下图所示;

可以从图中看到,该数表示为28;

补充一下:负数在计算机中是补码的形式存在的,补码=反码+1,符号位为1则表示为负数;那么-4该如何表示呢?以8 bit数据为例,如下所示;
         原码:0B 0000 100
         反码:0B 1111 011
         补码:0B 1111 100

综上,可以得到有符号Q9.7的范围是:[28,2827]


1.9.3 Q数据的运算
a) 0x7FFF

最大数的十六进制为0x7FFF,如下图所示;

b) 0x8000

最小数的十六进制为0X8000,如下图所示;

上述这两种情况,下面都会用到。


c) 加法

加法和减法需要两个Q格式的数据定标相同,即Qm1.n1和Qm2.n2满足以下条件;

{m1=m2   n1=n2}

  int16_t q_add(int16_t a, int16_t b)  
  {  
     return a + b;  
  }

上面的程序其实并不安全,在一般的DSP芯片具有防止溢出的指令,但是通常需要做一下溢出检测,具体如下所示;

  int16_t q_add_sat(int16_t a, int16_t b)  
  {  
      int16_t result;  
      int32_t tmp;  
      tmp = (int32_t)a + (int32_t)b;  
      if (tmp > 0x7FFF)  
          tmp = 0x7FFF;  
      if (tmp < -1 * 0x8000)  
        tmp = -1 * 0x8000;  
    result = (int16_t)tmp;  
    return result;  
}

d) 减法

类似于加法的操作,需要相同定标的两个Q格式数进行相减,但是不会存在溢出的情况;

  int16_t q_sub(int16_t a, int16_t b)  
  {  
      return a - b;  
  }

e) 乘法

乘法同样需要考虑溢出的问题,这里通过sat16函数,对溢出做了处理;

  // precomputed value:  
  #define K   (1 << (Q - 1))  
  // saturate to range of int16_t  
  int16_t sat16(int32_t x)  
  {  
      if (x > 0x7FFF) return 0x7FFF;  
      else if (x < -0x8000) return -0x8000;  
      else return (int16_t)x;  
  }  
int16_t q_mul(int16_t a, int16_t b)  
{  
    int16_t result;  
    int32_t temp;  
   temp = (int32_t)a * (int32_t)b; // result type is operand's type  
    // Rounding; mid values are rounded up  
    temp += K;  
   // Correct by dividing by base and saturate result  
   result = sat16(temp >> Q);  
   return result;  
}

f) 除法
  int16_t q_div(int16_t a, int16_t b)  
  {  
      /* pre-multiply by the base (Upscale to Q16 so that the result will be in Q8 format) */  
      int32_t temp = (int32_t)a << Q;  
      /* Rounding: mid values are rounded up (down for negative values). */  
      /* OR compare most significant bits i.e. if (((temp >> 31) & 1) == ((b >> 15) & 1)) */  
      if ((temp >= 0 && b >= 0) || (temp < 0 && b < 0)) {     
          temp += b / 2;    /* OR shift 1 bit i.e. temp += (b >> 1); */  
      } else {  
        temp -= b / 2;    /* OR shift 1 bit i.e. temp -= (b >> 1); */  
    }  
    return (int16_t)(temp / b);  
}

1.9.4 常见Q格式的数据范围

定点数Xq和浮点数Xf转换的关系满足以下公式:

Xq=(int)Xf2n

Xf=(float)Xf2n

其中XqXq为Qm.nQm.n,m表示整数位数,n表示小数位数;

  #include <stdio.h>  
  #include <stdint.h>  
  #include <math.h>
  int main()  
  {  
      // 0111 1111 1111 1111  
      int16_t q_max = 32767; // 0x7FFF  
      // 1000 0000 0000 0000  
      int16_t q_min = -32768; // 0x8000  
    float f_max = 0;  
    float f_min = 0;  
    printf("\r\n");  
    for (int8_t i = 15; i>=0; i--) {  
        f_max = (float)q_max / pow(2,i);  
        f_min = (float)q_min / pow(2,i);  
       printf("\t| Q %d | Q %d.%d| %f | %f |\r\n",  
               i,(15-i),i,f_max,f_min);  
    }  
    return 0;  
}

运行得到结果如下所示:


格式

Qmn

Max

Min

Q 15

Q 0.15

0.999969

-1.000000

Q 14

Q 1.14

1.999939

-2.000000

Q 13

Q 2.13

3.999878

-4.000000

Q 12

Q 3.12

7.999756

-8.000000

Q 11

Q 4.11

15.999512

-16.000000

Q 10

Q 5.10

31.999023

-32.000000

Q 9

Q 6.9

63.998047

-64.000000

Q 8

Q 7.8

127.996094

-128.000000

Q 7

Q 8.7

255.992188

-256.000000

Q 6

Q 9.6

511.984375

-512.000000

Q 5

Q 10.5

1023.968750

-1024.000000

Q 4

Q 11.4

2047.937500

-2048.000000

Q 3

Q 12.3

4095.875000

-4096.000000

Q 2

Q 13.2

8191.750000

-8192.000000

Q 1

Q 14.1

16383.500000

-16384.000000

Q 0

Q 15.0

32767.000000

-32768.000000


注意在Q格式运算的时候,两者定标必须相同,对于数据的溢出检测也要做相应的处理。

相关文章
|
2天前
|
传感器 算法 机器人
定点 CPU 在哪些领域有应用
定点CPU主要应用于对成本和功耗敏感的嵌入式系统中,如消费电子、汽车电子、工业控制和物联网设备等,因其结构简单、效率高而受到青睐。
|
6月前
基于DSP的数字滤波器设计
基于DSP的数字滤波器设计
138 4
|
4月前
|
存储 算法 数据处理
LabVIEW FPGA开发NI sbRIO-9607高精度数字滤波器
LabVIEW FPGA开发NI sbRIO-9607高精度数字滤波器
47 5
|
6月前
|
算法 关系型数据库 计算机视觉
基于FPGA的9/7整数小波变换和逆变换verilog实现,包含testbench
基于FPGA的9/7整数小波变换和逆变换verilog实现,包含testbench
|
存储 算法 计算机视觉
m基于FPGA的各类存储器纯Verilog实现,包含testbench,包括RAM,SRAM等
m基于FPGA的各类存储器纯Verilog实现,包含testbench,包括RAM,SRAM等
398 2
不同CPU指令的指令集密度
不同CPU指令的指令集密度
131 0
不同CPU指令的指令集密度
|
异构计算
【ALU】32-bit低时延高速整数ALU的设计|超前进位加法器
【ALU】32-bit低时延高速整数ALU的设计|超前进位加法器
【ALU】32-bit低时延高速整数ALU的设计|超前进位加法器
|
存储 人工智能 BI
数字信号处理-05- FPGA常用运算模块-复数乘法器(二)
数字信号处理-05- FPGA常用运算模块-复数乘法器
712 0
数字信号处理-05- FPGA常用运算模块-复数乘法器(二)
|
异构计算
数字信号处理-05- FPGA常用运算模块-复数乘法器(一)
数字信号处理-05- FPGA常用运算模块-复数乘法器
988 0
数字信号处理-05- FPGA常用运算模块-复数乘法器(一)
|
存储 IDE 开发工具
数字信号处理-02- FPGA常用运算模块-加减法器和乘法器
数字信号处理-02- FPGA常用运算模块-加减法器和乘法器
1040 0
数字信号处理-02- FPGA常用运算模块-加减法器和乘法器