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

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

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

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


3 N  c% ]# y: k% @  S

1. 关于CORDIC

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

" j* ]/ S4 X9 \$ W3 N# v

640 (7).png 坐标旋转算法示意图/ V7 c; P" W3 X3 |: _- ^
2 \2 S+ T0 o+ X4 H$ e
2. STM32G4中使用CORDIC2.1 初始配置

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

  K. A7 @0 j4 S5 x0 g

640 (6).png
+ {/ V$ o0 _' r/ j* \. S8 j结构体成员变量0 n/ w4 F+ i7 X5 E
. w! C. R! L& B/ _* n

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

函数输入与输出* f; Q- j9 Z: l9 @


. M9 J& h0 u* L5 M* o

640 (4).png
3 e; l% _. u( d. E2 V$ [

CORDIC_CSR寄存器
" z  m2 Z" m/ j  w4 `' y; ^
0 a6 G4 X7 c# f  O
( j5 f5 p; |- }/ d
2.2 CORDIC的读写操作步骤
  • 零开销模式(Zero-overhead mode)

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

      M: A9 j* Q2 N7 c. p
    - z. P7 T9 O6 f; O( ]6 e  b
  • 配置CORDIC_CSR寄存器,也就是初始化和配置CORDIC;
  • 向CORDIC_WDATA寄存器写入参数,写入完成后CORDIC将会开始第一次计算;
  • 如果需要,为下一次计算重新配置CORDIC_CSR寄存器,此时不论上一个计算是否完成,重新配置CSR寄存器不会对上一次计算结果产生影响;
  • 向CORDIC_WDATA寄存器写入下一次计算所需参数;
  • 从CORDIC_RDATA寄存器读取上一次计算的结果,读取结果的操作完成后会触发下一次计算的开始;一旦开始计算,读取CORDIC_RDATA寄存器的操作都会插入AHB总线等待状态,直到计算结束才返回结果;因此,即使CORDIC未运算出结果,也可以进行读操作,当计算结果返回时读操作完成;
  • 重复第3至第6步骤;
  • 从CORDIC_RDATA寄存器读取最后一个结果,完成计算。
    7 \# m$ h5 I6 q" V/ s  F& {
3 j/ p5 T0 L" r! {( o
640 (3).png / C9 u) d0 q( V
零开销模式示意图7 z& Q0 ]. q: R
( M& J. D2 Z% m" ]# g8 g5 R  G
  • 轮询模式(Polling mode)

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


    , d0 ]9 g) ?- ]4 e) m2 S
    6 |* l/ i& m" ]9 f2 q
  • 配置CORDIC_CSR寄存器,也就是初始化和配置CORDIC;
  • 向CORDIC_WDATA寄存器写入参数,写入完成后CORDIC将会开始第一次计算;
  • 如果需要,为下一次计算重新配置CORDIC_CSR寄存器,此时不论上一个计算是否完成,重新配置CSR寄存器不会对上一次计算结果产生影响;
  • 向CORDIC_WDATA寄存器写入下一次计算所需参数;
  • 轮询CORDIC_CSR寄存器的RRDY标志位,直到该位被置1;
  • RRDY标志位置1时,从CORDIC_RDATA寄存器读取上一次计算的结果,读取结果的操作完成后会触发下一次计算的开始;
  • 重复第3至第7步骤;
  • 从CORDIC_RDATA寄存器读取最后一个结果,完成计算。
    , V: i: D2 K- E0 `/ U! p

    1 ^: P6 N$ n6 J2 X# C6 a

  • & Y9 [; R; T( U" B
  • 中断模式(Interrupt mode)

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


    , `. k+ P4 N4 W8 A. `
    7 T6 t+ q4 Q% Q
  • 配置CORDIC_CSR寄存器,也就是初始化和配置CORDIC,并且设置IEN位为1;可以直接在STM32CubeMX中设置为中断模式;
  • 向CORDIC_WDATA寄存器写入参数,写入完成后CORDIC将会开始第一次计算;
  • 如果需要,为下一次计算重新配置CORDIC_CSR寄存器,此时不论上一个计算是否完成,重新配置CSR寄存器不会对上一次计算结果产生影响;
  • 向CORDIC_WDATA寄存器写入下一次计算所需参数;
  • 当计算完成,RRDY位被置1,产生中断信号;在中断服务函数中读取CORDIC_RDATA寄存器上一次计算的结果,读取结果的操作完成后会触发下一次计算的开始;读取CORDIC_RDATA的操作会清除RRDY位和中断信号;;
  • 从CORDIC_RDATA寄存器读取最后一个结果,完成计算。) n3 a2 Y* z* ?. e* Y& H6 j

    4 D6 y* s' |) T4 j

  • ' N5 P. |. X7 ]/ q0 g
  • 直接存储器访问模式(DMA mode)

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

    ) y1 o- F0 o9 I/ r  G
    6 T% M% g! X  d" _# B4 U- J
  • 配置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阻塞。


    $ ?2 V; ^0 W" ?( H5 w, y9 f

6 Q' J" T( @6 K* |" V6 j) W2 E3. 定点带符号整数数据格式(Q1.31,Q1.15)3.1 定义

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

640 (2).png
* g' n1 h6 R1 }  Q9 j! f
: K7 M" Q+ g4 S7 C4 ?8 \ 6{1P){WKOQU0ABX~1ELO1.png
7 j0 m' n, v9 [; S3 p# x

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


+ w# h0 ^7 c3 N) ]4 }

640 (1).png 6 `+ z4 m  V7 x+ d3 P. M

: P8 b3 m* Y7 y" t3 G 5J~BNAAMTUAV20R%J8213.png
' S; }8 s( E& n# b$ q

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

640.png , u5 G; S, _: ?' J
9 H$ z$ s8 _" X- m7 B& G
3.2 带符号浮点格式的转换

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

1 Y' O1 O9 Q+ c

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

  1. /**$ L  p' b/ n# U( j# b7 K% y
  2.   * @brief  将数据转换成CORDIC要求的Q1.31整型数据格式。
    6 Z1 o& X0 q. N& u& A' x1 t- i7 u
  3.   * @param  需要转换的数据,取值可以为负数。+ K2 k! l0 w+ W+ J
  4.   * @param  比例系数;数据除以比例系数之后再转换格式;. h1 Z: i% z+ \
  5.         *         CORDIC的输入参数数值在[-1,1]之间,故需要先除以一个比例系数。
    5 P0 I8 P* B2 P9 t
  6.   *            @ref STM32G4 Series advanced Arm-based 32-bit MCUs - Reference Manual
    0 a: M2 k& ]& e  m
  7.   * @retval Q1.31整型数据9 U$ A* S. B4 z1 A: u8 X
  8.   */4 p- J; }: r8 D. h: i
  9. int Value_To_CORDIC31(float Value, float Coefficient)" c- Y2 ^/ V* n& e/ ?, v# [
  10. {
    2 H) P: V7 j( }4 A; o
  11.         int CORDIC31;! a7 j: a7 z+ j6 a, A9 j
  12.         CORDIC31 = (int)((Value/Coefficient)*0x80000000);
    ; Q) ]  ?- d1 {  ~/ ~$ T
  13.         return CORDIC31;
    : F% }: O4 p- j3 N
  14. }
复制代码

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

  1. /**
    ) C4 P& ]4 c4 D/ x: F% n
  2.   * @brief  将数据转换成CORDIC要求的Q1.15整型数据格式。
    9 c, p' A% N* C+ Z, i: v' G, m
  3.   * @param  需要转换的数据,取值可以为负数;该数据存放在高16位。% v: j$ W7 t- u% Y
  4.   * @param  需要转换的数据,取值可以为负数;该数据存放在低16位。
      n0 j  w; ?$ p3 Y- c% S$ D# M: E
  5.   * @param  比例系数;数据除以比例系数之后再转换格式;% u+ B/ {* i6 B5 W' c- E
  6.         *         CORDIC的输入参数数值在[-1,1]之间,故需要先除以一个比例系数。
    7 u0 B3 W" ?) e1 S8 Y# j0 J1 q# M
  7.   *            @ref STM32G4 Series advanced Arm-based 32-bit MCUs - Reference Manual' M- v2 s9 }; \2 c: k5 g
  8.   * @retval Q1.15整型数据
    + A0 S2 f+ v8 F/ D  M
  9.   */
    , j" P5 A) [, J
  10. int Value_To_CORDIC15(float ValueA, float ValueB, float Coefficient)
    5 w: F2 w& l8 q' |4 F* d
  11. {
    ) }  `+ e- E( q" s
  12.         int CORDIC15;4 f. R0 \, L5 J- X' \9 Q; a
  13.         CORDIC15 = (int)((ValueA/Coefficient)*0x8000) << 16;) n; f1 ?/ B3 V8 t  z; b7 a/ g
  14.         CORDIC15 = CORDIC15|(int)((ValueB/Coefficient)*0x8000);3 u8 m2 e" L& Z
  15.         return CORDIC15;
    % R& y, h0 y( B' B2 e. G1 `) P( w
  16. }
复制代码

) I8 c* d1 ^3 O! h
( {4 z; {/ Z6 W3 I

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

  1. /**
    ( C; n( ~, B7 S/ {' d6 Z" y
  2.   * @brief  将CORDIC输出的Q1.31整型数据转换成带符号的浮点数值格式。
    / D. _. ?+ j, Z
  3.   * @param  需要转换的数据。% `3 c+ o2 G" K
  4.   * @param  存放输出数据的地址。
    . v9 r% P+ h  G) s- r, \; k4 g* P
  5.   * @note   转换无精度损失;
    % O7 j" a0 ]7 Y
  6.   *         精度要求不高时,可以将double类型换成float类型以节约RAM空间;此时精度将下降至1/10000000。
    2 a5 M6 w9 [3 N
  7.   */  g+ g: v, Q' ~6 a
  8. void CORDIC31_To_Value(int CORDIC31, double        *RES)4 I, N7 E& w. G& Y* @' |
  9. {3 b! }# R( y6 d9 x
  10.         if (CORDIC31&0x80000000)$ }3 I) h% ^. h4 e3 T4 s
  11.         { /*为负数*/
    7 z# N0 s7 e' a! z6 ^' n- q- Y
  12.                 CORDIC31 = CORDIC31&0x7FFFFFFF;& P/ \3 {2 R+ U! a, ~0 v# ^
  13.                 *RES = (((double)(CORDIC31)-0x80000000)/0x80000000);2 N* }! t' \1 H( S$ Q: B
  14.         }
    ; O! |% y& p( s' {& a
  15.         else. `( I8 D' y& k' j
  16.         {/*为正数*/
    + N+ M. s! C( v: G% K
  17.                 *RES = (double)(CORDIC31)/0x80000000;$ E/ C0 W7 B2 W. F
  18.         }; c6 p+ W; |# }3 P* Y$ L
  19. <font size="2">}</font>
复制代码

5 L* E" E, c0 d. O+ q# ~( d

* c2 P6 P% j) a) g4 F. s1 D  D
$ F& Q) C' P  P

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

  1. /**; F5 m6 v0 W- @" t' W+ x6 C
  2.   * @brief  将CORDIC输出的Q1.15整型数据转换成两个带符号的浮点数值格式。
    . g9 w3 A$ I3 P) p" v
  3.   * @param  需要转换的数据。
    9 a5 S( v7 t2 b. e' @- l
  4.   * @param  存放输出数据的地址;输出高位数据。
    # C- y# d3 b# w! |4 C! g  t
  5.   * @param  存放输出数据的地址;输出低位数据。. I+ ^* `9 Y% Y; D/ Q
  6.   */6 R# I, u+ K# c/ Z, M
  7. void CORDIC15_To_Value(int CORDIC15, float *REA, float *REB)
    ; t' F# j; u- u9 [+ }
  8. {5 ~1 b3 `) Y) W* i4 c, C( \8 r
  9.         if (CORDIC15&0x80000000)//处理高16位, X7 K9 S4 d! \) ]6 @, W0 p
  10.         {/*为负数*/$ C# W- Q0 U2 ^# R; b# _
  11.                 *REA = ((float)((CORDIC15>>16)&0x7FFF)-0x8000)/0x8000;9 \& A1 w$ Y. M
  12.         }
    ! c) Q: y' V2 R+ W
  13.         else
    3 s/ n2 a- x2 @9 y3 D6 }
  14.         {/*为正数*/# n( q8 q4 E( D# \. A
  15.                 *REA = (float)((CORDIC15>>16)&0xFFFF)/0x8000;+ [0 W7 f" s0 h& N! j/ B
  16.         }
    * Z- p$ D# A( P0 |' ?7 B1 X) h
  17.         if (CORDIC15&0x8000)//处理低16位: a: v/ d+ N8 N7 V' M  \
  18.         {/*为负数*/
    1 ?. ?# R! I" S- \
  19.                 *REB = ((float)(CORDIC15&0x7FFF)-0x8000)/0x8000;
    2 E& a0 z# B# f0 J* m
  20.         }) `5 ~, K$ r' K. ^: c. U- W: Q# X4 J
  21.         else' p  C& U& G" m+ j" o
  22.         {/*为正数*/
    ) x: q, X( U4 A, |6 z. P2 H
  23.                 *REB = (float)(CORDIC15&0xFFFF)/0x8000;5 m' g1 P: b/ ]9 C5 ?+ c$ D
  24.         }
    5 |$ N: F$ `5 K( F) {1 R( Q
  25. }
复制代码

! g9 t: q+ C' G3 {& i* g6 u, O
& E3 R( E; l" [
收藏 评论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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版