请选择 进入手机版 | 继续访问电脑版

你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32G4_CORDIC与定点带符号整数数据格式

[复制链接]
STMCU小助手 发布时间:2022-5-27 19:47
STM32G4_CORDIC与定点带符号整数数据格式

2019年ST推出的G4系列芯片是STM32系列第一款带有CORDIC协同处理器的芯片。CORDIC协同处理器提供某些数学函数的硬件加速,尤其是三角函数。它能加快这些函数的运算,释放处理器以执行其他任务。通常用于电机控制、测量、信号处理和许多其他应用。

7 L  ^5 j4 x/ \

1. 关于CORDIC

CORDIC(coordinate rotation digital computer坐标旋转数字计算机)是一种用于计算三角函数和双曲线函数的低成本逐次逼近算法。最初由Jack Volder在1959年提出,它被广泛用于早期计算器当中。CORDIC算法通过基本的加和移位运算代替乘法运算,具体原理不在此赘述。

& C6 w4 p. b( d% @1 c

640 (7).png 坐标旋转算法示意图
' E, s, u9 r& g2 ?+ s, a
6 O. d$ a4 ]/ H* ]2. STM32G4中使用CORDIC2.1 初始配置

使用STM32CubeMX激活CORDIC,再按需选择配置NVIC或者DMA。生成代码支持HAL库和LL库。此时代码包含了CORDIC的初始化(CORDIC_Initialize),不包括CORDIC的配置(CORDIC_Configure)。需要用户自行实例化结构体CORDIC_ConfigTypeDef:

3 t$ x2 W) G+ G" a  i( e  x

640 (6).png 2 ]. n+ X" k# s) }
结构体成员变量2 k6 u) N, Q' S, n( I

( b3 x1 {  ]9 z! g$ c7 v. }6 [

Function包含共10种函数:余弦、正弦、方位角、取模、反正切、双曲余弦、双曲正弦、双曲反正切、自然对数、开平方。

Scale指缩放因子;CORDIC要求输入数值在[-1,1]区间内;设输入值为x,缩放因子为n,则会先对输入数值做运算x=x·2^-n,CORDIC计算完成后输出结果y再做运算y=y·2^n;缩放因子取值范围视所选函数规定,在[0,7]区间内;缩放因子可能会导致运算精度的丢失。(可查阅ST官方文档:RM0440)

InSizeOutSize:提供两种输入输出数据格式Q1.31和Q1.15;每次向CORDIC输入数据时,会发送一个32位的数据,当选择Q1.31数据格式时,CORDIC一次运算一个数据;当选择Q1.15数据格式时,将两个数据封装在一个32位数据中,CORDIC一次运算两个数据;选择Q1.15数据格式能提高运算速度,但牺牲了运算精度;有关Q1.31和Q1.15数据格式的内容下文会讲到。

NbWriteNbRead:写入写出的参数数量;有些函数,比如求方位角、取模,需要输入x,y两个参数才能进行运算;有些函数,比如余弦、正弦,CORDIC运算后可以输出两个结果,例如进行余弦函数运算时,可以输出一个余弦结果和一个正弦结果;两个数据以交替的形式进行输入输出;输入时若次要参数一直保持不变,可在第一次计算开始后将NbWrite设置为1个参数输入模式。(可查阅ST官方文档:RM0440)

Precision指迭代周期;取值范围为1到13;迭代周期越多,运算精度越高,运算速度越低;当运算精度到达数据格式所能表达的精度极限时,继续增加迭代周期毫无意义,例如迭代6周期运算已经达到Q1.31数据格式正弦函数运算所能表达的精度极限,继续增加迭代周期的运算结果与迭代6周期的运算结果无异;对于大多数函数,迭代周期推荐3到6周期。

配置完结构体变量,后使用CORDIC_Configure函数将数据写入CORDIC_CSR寄存器,CORDIC的初始化和配置完成。

640 (5).png

函数输入与输出) \, }) \( b5 D2 ]' h+ J0 B+ n

2 G6 m! ^' N- C) S, d) ~, x) s

640 (4).png

. G2 a! Z3 l/ w. f4 V+ [7 }5 y# n

CORDIC_CSR寄存器

' C3 P% h' K5 t1 w7 _: i
- ~  z6 l  v5 h+ C
: }! j+ P  n3 [) N8 U
2.2 CORDIC的读写操作步骤
  • 零开销模式(Zero-overhead mode)

    该模式下CORDIC运算效率最高,上一个结果被读取后即刻开始下一次运算,期间没有空闲时间;该模式中CPU的占用率为100%。


      ?- L0 X8 ^4 k( B, m  }

    9 A* a" C2 H& k- `5 \) ]4 l2 F6 Z" ?
  • 配置CORDIC_CSR寄存器,也就是初始化和配置CORDIC;
  • 向CORDIC_WDATA寄存器写入参数,写入完成后CORDIC将会开始第一次计算;
  • 如果需要,为下一次计算重新配置CORDIC_CSR寄存器,此时不论上一个计算是否完成,重新配置CSR寄存器不会对上一次计算结果产生影响;
  • 向CORDIC_WDATA寄存器写入下一次计算所需参数;
  • 从CORDIC_RDATA寄存器读取上一次计算的结果,读取结果的操作完成后会触发下一次计算的开始;一旦开始计算,读取CORDIC_RDATA寄存器的操作都会插入AHB总线等待状态,直到计算结束才返回结果;因此,即使CORDIC未运算出结果,也可以进行读操作,当计算结果返回时读操作完成;
  • 重复第3至第6步骤;
  • 从CORDIC_RDATA寄存器读取最后一个结果,完成计算。0 u$ q# b+ ^1 u
" E2 f+ D4 L$ M( P! g
640 (3).png
- B4 x! N" U* E7 E  ~- X零开销模式示意图
7 [$ v3 i+ \1 `& z% O2 w
# u: h7 F6 C% R) c( e- w
  • 轮询模式(Polling mode)

    该模式会轮询CORDIC_CSR寄存器的RRDY标志位以判断运算完成;该模式不会使CPU处于100%的占用率,使CPU可以处理其他任务;轮询模式会比零开销模式消耗稍长时间,因为计算完成后结果不会立即被读取,需要等待下一个轮询周期到来,且读取RRDY标志位后再读取结果会产生延迟。

    ! @$ x. P7 d5 Z9 Y. ~4 {
    4 k0 I" s& t% t: V
  • 配置CORDIC_CSR寄存器,也就是初始化和配置CORDIC;
  • 向CORDIC_WDATA寄存器写入参数,写入完成后CORDIC将会开始第一次计算;
  • 如果需要,为下一次计算重新配置CORDIC_CSR寄存器,此时不论上一个计算是否完成,重新配置CSR寄存器不会对上一次计算结果产生影响;
  • 向CORDIC_WDATA寄存器写入下一次计算所需参数;
  • 轮询CORDIC_CSR寄存器的RRDY标志位,直到该位被置1;
  • RRDY标志位置1时,从CORDIC_RDATA寄存器读取上一次计算的结果,读取结果的操作完成后会触发下一次计算的开始;
  • 重复第3至第7步骤;
  • 从CORDIC_RDATA寄存器读取最后一个结果,完成计算。
    " z& B+ Q9 ?1 G9 R" F
    * y8 O8 M! x) N- U( s

  • 1 F/ Z; |; d& E  t
  • 中断模式(Interrupt mode)

    当RRDY标志位被置1时产生中断信号,该位被置0时会清除中断标志位;该模式下使得结果的读取具有优先级;因此会比零开销模式和轮询模式消耗更长时间。


      d* d5 J. b2 h* C5 V

    ! ]( ?# y6 F% j9 ?: Z9 y% o6 T
  • 配置CORDIC_CSR寄存器,也就是初始化和配置CORDIC,并且设置IEN位为1;可以直接在STM32CubeMX中设置为中断模式;
  • 向CORDIC_WDATA寄存器写入参数,写入完成后CORDIC将会开始第一次计算;
  • 如果需要,为下一次计算重新配置CORDIC_CSR寄存器,此时不论上一个计算是否完成,重新配置CSR寄存器不会对上一次计算结果产生影响;
  • 向CORDIC_WDATA寄存器写入下一次计算所需参数;
  • 当计算完成,RRDY位被置1,产生中断信号;在中断服务函数中读取CORDIC_RDATA寄存器上一次计算的结果,读取结果的操作完成后会触发下一次计算的开始;读取CORDIC_RDATA的操作会清除RRDY位和中断信号;;
  • 从CORDIC_RDATA寄存器读取最后一个结果,完成计算。( O, t9 a+ B- K1 n" b
      j8 \4 C4 h, c; h

  • ) T7 H# D& j2 Y
  • 直接存储器访问模式(DMA mode)

    该模式下CPU占用率为0%;DMA请求不能对CORDIC_CSR寄存器进行读写操作,因此DMA模式只适用于相同模式下的运算,比如使用相同的函数、相同的缩放因子、相同的迭代周期等;DMA模式下,数据的来源与输出目的地不一定是片上内存,可以是其他外设,比如DAC和ADC;

    & n0 l" P  ?1 b8 X: ]2 m

    ; z0 o" U- E! z& d3 K6 K
  • 配置CORDIC_CSR寄存器,也就是初始化和配置CORDIC;在STM32CubeMX中设置DMA模式;

  • 使用CORDIC_Calculate_DMA函数启动DMA运算,入口参数中配置数据源的地址以及输出地址,并且设置DMAWEN位和DMAREN位;

    注意事项:当DMAWEN置1时会产生DMA写请求,当DMAREN置1且RRDY置1时会产生DMA读请求,因此要暂停DMA读写只需将DMAWEN和DMAREN置0即可;在DMA模式运行中应避免对CORDIC_WDATA寄存器做写操作和CORDIC_RDATA寄存器做读操作,否则可能会产生DMA阻塞。


    + m, V+ r) ?1 G. o
  T7 N: p) q2 q
3. 定点带符号整数数据格式(Q1.31,Q1.15)3.1 定义

在q1.31格式中,数字由一个符号位和31个小数位(二进制位)表示;数值范围是-1(0x80000000)到1 - 2^-31(0x7fffffff);精度是2^-31(大约5 x 10^-10)。

640 (2).png
/ i0 [- u0 j. I2 x# q2 }
% p) ?, i; {& v 6{1P){WKOQU0ABX~1ELO1.png
! t+ k  X% r- {( W

在q1.15格式中,数字由一个符号位和15个小数位(二进制位)表示;数值范围是-1(0x8000)到1 - 2^-15(0x7fff);

, k& w9 X0 z- {/ U

640 (1).png - u: S) `% Q$ T

6 E6 V$ W" T' I- l 5J~BNAAMTUAV20R%J8213.png 6 U# n/ D% s- T) P

这种格式的优点是可以将两个输入参数打包到一个32位的数据中,并且可以在一个32位的读操作中获取两个结果;但精度降低到2^-15(大约3 × 10^-5)。

640.png
( i. a( ?6 a9 a* o: M6 X8 t$ _$ u, m! y7 @& N+ ]+ d# F6 n4 H; H
3.2 带符号浮点格式的转换

Q1.31或Q1.15格式对开发者而言不够直观,以下提供四条函数,可将Q1.31和Q1.15格式转换成带符号浮点数。


* r- l0 S* n* N( e% m; O4 Y

将带符号浮点数转换成Q1.31格式:

  1. /*** i8 W/ c$ `$ }$ k! ?: F% w
  2.   * @brief  将数据转换成CORDIC要求的Q1.31整型数据格式。! k+ m! Q4 U! p( q) c% D4 j
  3.   * @param  需要转换的数据,取值可以为负数。7 D; D7 L7 \, |
  4.   * @param  比例系数;数据除以比例系数之后再转换格式;
    ) l9 {7 ^" h) J" Q
  5.         *         CORDIC的输入参数数值在[-1,1]之间,故需要先除以一个比例系数。
    ' |( _) i) n4 N5 I+ j
  6.   *            @ref STM32G4 Series advanced Arm-based 32-bit MCUs - Reference Manual
    & b' z/ Y" U% O% z. C
  7.   * @retval Q1.31整型数据3 h# I: L6 Y6 q2 W& C" |! W: F
  8.   */& P. S; F3 H' E9 A4 r
  9. int Value_To_CORDIC31(float Value, float Coefficient)# O. {, D0 e% j* N1 ~
  10. {7 d  b0 J& {) P2 G0 f& {
  11.         int CORDIC31;/ H  F. a8 [# I2 e5 c- N" S. V
  12.         CORDIC31 = (int)((Value/Coefficient)*0x80000000);# M4 T8 W/ E- @* G
  13.         return CORDIC31;
    4 Y2 |3 Q0 b3 ~& U# b  M3 l
  14. }
复制代码

将带符号浮点数转换成Q1.15格式:

  1. /**7 e& M2 @" y- {# {
  2.   * @brief  将数据转换成CORDIC要求的Q1.15整型数据格式。
    5 y9 V% q. z7 p* e  B
  3.   * @param  需要转换的数据,取值可以为负数;该数据存放在高16位。
    - n. M- `0 e) x8 g
  4.   * @param  需要转换的数据,取值可以为负数;该数据存放在低16位。2 P( J$ V$ ~% l. W
  5.   * @param  比例系数;数据除以比例系数之后再转换格式;) r$ ?! t4 z2 [; y) U1 X+ U) m5 x2 y
  6.         *         CORDIC的输入参数数值在[-1,1]之间,故需要先除以一个比例系数。* b2 J2 ?7 c; G6 r# i6 f
  7.   *            @ref STM32G4 Series advanced Arm-based 32-bit MCUs - Reference Manual
    ) d+ e: U# S" ~6 U2 i, |+ L7 h9 L
  8.   * @retval Q1.15整型数据( x: E" |: |* }4 ~' e4 }2 n6 |
  9.   */+ F" K$ `' A0 F5 D3 e' O
  10. int Value_To_CORDIC15(float ValueA, float ValueB, float Coefficient)
    ! f) k' z  d9 {: W3 [& e
  11. {% |. b0 K+ G" `4 m7 }0 e/ w
  12.         int CORDIC15;' F7 ]# Q2 O! ]! o  v$ \
  13.         CORDIC15 = (int)((ValueA/Coefficient)*0x8000) << 16;) N9 _( E" r8 s7 }
  14.         CORDIC15 = CORDIC15|(int)((ValueB/Coefficient)*0x8000);
    & o8 [% K" R# P, b* o7 `0 h; ?
  15.         return CORDIC15;8 B/ u. L$ |1 W' b% x( {; p
  16. }
复制代码

" q7 g5 F, {2 ]5 o
1 i, s/ [( o2 {* Z

将Q1.31格式转换成带符号浮点数:

  1. /**
    6 O6 }" n3 O. J$ P
  2.   * @brief  将CORDIC输出的Q1.31整型数据转换成带符号的浮点数值格式。
    , q+ Q' S2 x8 V' V- i
  3.   * @param  需要转换的数据。. u# H0 d0 ]! i2 A( u7 n
  4.   * @param  存放输出数据的地址。
    * u( `( [3 N9 ~5 S# T
  5.   * @note   转换无精度损失;
    ( U+ n; n" q" g* P& A
  6.   *         精度要求不高时,可以将double类型换成float类型以节约RAM空间;此时精度将下降至1/10000000。9 f0 ~) w0 {3 k. J6 M- h; K
  7.   */
    ) I. h" \3 J2 J# t2 j3 e7 x
  8. void CORDIC31_To_Value(int CORDIC31, double        *RES)
    ; j8 G2 t; i" H9 Z; J$ T
  9. {! a- ]+ e; O! v. [0 x
  10.         if (CORDIC31&0x80000000)* D% a8 ^9 n( R6 c
  11.         { /*为负数*/
      V* u1 B5 e( S7 b
  12.                 CORDIC31 = CORDIC31&0x7FFFFFFF;
    " C; N! [: Y$ I/ ]; Y: m
  13.                 *RES = (((double)(CORDIC31)-0x80000000)/0x80000000);
    , ]: r! V! T) N+ y: E# J9 Y. `
  14.         }) ^8 E! V1 L) f. j9 ]/ ]' w1 [
  15.         else: A, `7 h; Z4 G! n
  16.         {/*为正数*/* ^0 }0 t$ D* A! F3 l" G' r! K2 `) Y
  17.                 *RES = (double)(CORDIC31)/0x80000000;
    : Z+ O$ s  c2 z  G
  18.         }5 p, G! N- u2 s5 C
  19. <font size="2">}</font>
复制代码

) _- U; N  P/ l6 a
/ ^* B0 n9 R1 @. A8 a2 R; K4 U3 z
6 M2 U4 z( S+ a5 |

将Q1.15格式转换成带符号浮点数:

  1. /**
    ! A* v/ A- B& p
  2.   * @brief  将CORDIC输出的Q1.15整型数据转换成两个带符号的浮点数值格式。
    6 D, [& K& h0 g4 k* w% \
  3.   * @param  需要转换的数据。3 P, P# g/ z' p: ?2 t2 c7 z, E
  4.   * @param  存放输出数据的地址;输出高位数据。. h9 X! W" E4 [+ K, r2 F
  5.   * @param  存放输出数据的地址;输出低位数据。8 M# ^" o9 A; J8 f
  6.   */
    1 `0 g* `- \! G& ~, ~, w
  7. void CORDIC15_To_Value(int CORDIC15, float *REA, float *REB)& I! G! q) I; n7 `( @* Y0 H' E
  8. {; g$ z* n  n5 r' ?! z: b/ K- p
  9.         if (CORDIC15&0x80000000)//处理高16位
    & o& e& C2 A; q
  10.         {/*为负数*/6 D8 Y* u& R  l) }  p
  11.                 *REA = ((float)((CORDIC15>>16)&0x7FFF)-0x8000)/0x8000;: T! u' T0 z) h$ H) \. z
  12.         }- F$ U6 J  L# w1 N
  13.         else
    1 ~- P1 S. R' w8 s( L
  14.         {/*为正数*/8 J* f9 h, {8 m2 ]6 G
  15.                 *REA = (float)((CORDIC15>>16)&0xFFFF)/0x8000;. @- t+ z' I% W
  16.         }
    $ O& Q/ n% h8 O0 [' F3 P. }
  17.         if (CORDIC15&0x8000)//处理低16位
    " G- P8 ?& N' X
  18.         {/*为负数*/
      ], c- L1 ?2 L" X
  19.                 *REB = ((float)(CORDIC15&0x7FFF)-0x8000)/0x8000;; k. V" L: c$ f
  20.         }
    3 A; e& v: L5 v9 _9 ^& D( p
  21.         else; p( y1 C7 u6 G) _) b
  22.         {/*为正数*/
    ) f; Z1 ~) q- Z, M; E3 |
  23.                 *REB = (float)(CORDIC15&0xFFFF)/0x8000;1 |" [* U( v' ]7 A
  24.         }  r  C+ o9 }$ m
  25. }
复制代码

( r. u* z$ W+ j. D% G
3 e( c. ?. S$ w/ W. t
收藏 评论2 发布时间:2022-5-27 19:47

举报

2个回答
1316096865@qq.c 回答时间:2024-3-20 16:47:57

关于迭代次数有些问题,原文中“对于大多数函数,迭代周期推荐3到6周期。”,实际cordic精度在迭代20次左右时q1.15的误差才趋于稳定(来源RM0440 16.3.5图)。

1316096865@qq.c 回答时间:2024-3-20 18:16:58

1316096865@qq.c 发表于 2024-3-20 16:47
关于迭代次数有些问题,原文中“对于大多数函数,迭代周期推荐3到6周期。”,实际cordic精度在迭代20次 ...

[md]补充一下,CSR寄存器的PRECISION位表示的是“迭代次数/4”,因此原文中应该是配置PRECISION为3-6,对应迭代次数为12-24次

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版