特别说明:完整45期数字信号处理教程,原创高性能示波器代码全开源地址:链接; v/ ~& p) }' Q, w! c& x
第10章 FastMathFunctions的使用
' Y2 G/ z3 Z0 A 本期教程开始,我们将不再专门的分析DSP函数的源码,主要是有些DSP函数的公式分析较麻烦,有兴趣的同学可以自行研究,本期教程开始主要讲解函数如何使用。 10.1 三角函数Cosine 10.2 三角函数Sine 10.3 平方根Sqrt 10.4 实例讲解(Matlab验证) 10.5 总结
1 g8 u u; F; y5 n5 H10.1 三角函数Cosine 三角函数cosine的计算是通过查表并配合三次插补实现的。具体的实现方法大家可以查阅相关资料进行了解。 10.1.1 arm_cos_f32 此函数的使用比较简单,函数定义如下: float32_t arm_cos_f32(float32_t x) 注意输入参数x是弧度制即可,也就是说cos函数的一个周期对应于弧度[ 0 2*PI)。下面我们先通过Matlab绘制一个周期的cos曲线。新建一个.m格式的脚本文件,并写入如下函数: x = 0:0.01:2*pi; plot(x, cos(x)) 运行后显示效果如下: 点击上面截图中的Tools->Data statistics,获取数据的分析结果,我们主要看Y轴。 最大值和最小值分别对应1和-1,这个与我们所学的理论知识是相符的。 10.1.2 arm_cos_q31 函数定义如下: q31_t arm_cos_q31(q31_t x) 使用中只需注意参数x的数值范围[0 2^31)相当于弧度[0 2*PI)即可。 10.1.3 arm_cos_q15 函数定义如下: q31_t arm_cos_q15(q15_t x) 使用中只需注意参数x的数值范围[0 2^15)相当于弧度[0 2*PI)即可。 10.2 三角函数Sine 三角函数sine的计算是通过查表并配合三次插补实现的。具体的实现方法大家可以查阅相关资料进行了解。 10.2.1 arm_sine_f32 此函数的使用比较简单,函数定义如下: float32_t arm_sin_f32(float32_t x) 注意输入参数x是弧度制即可,也就是说sine函数的一个周期对应于弧度[ 0 2*PI)。下面我们先通过Matlab绘制一个周期的sine曲线。新建一个.m格式的脚本文件,并写入如下函数: x = 0:0.01:2*pi; plot(x, sine(x)) 运行后显示效果如下: 点击上面截图中的Tools->Data statistics,获取数据的分析结果,我们主要看Y轴。 最大值和最小值分别对应1和-1,这个与我们所学的理论知识是相符的。 10.2.2 arm_sin_q31 函数定义如下: q31_t arm_sin_q31(q31_t x) 使用中只需注意参数x的数值范围[0 2^31)相当于弧度[0 2*PI)即可。 10.2.3 arm_sin_q15 函数定义如下: q31_t arm_sin_q15(q15_t x) 使用中只需注意参数x的数值范围[0 2^15)相当于弧度[0 2*PI)即可。 10.3 平方根sqrt 浮点数的平方根计算只需调用一条浮点指令即可,而定点数的计算要稍显麻烦。 10.3.1 arm_sqrt_f32 对于CM4带FPU的处理器来说,浮点数的平方根求解很简单,只需调用指令__sqrtf,仅需要14个时钟周期就可以完成。函数定义如下(在arm_math.h里面): static __INLINE arm_status arm_sqrt_f32(float32_t in, float32_t * pOut) 10.3.2 arm_sqrt_q31 函数的定义如下: arm_status arm_sqrt_q31(q31_t in, q31_t * pOut) 这里in的输入范围是0x00000000 到 0x7FFFFFFF,转化成浮点数范围就是[0 +1)。在使用这个函数的时候有一点要特别的注意,比如我们要求1000的平方根,而获得结果是1465429,这是为什么呢,分析如下: 定点数1000 = 浮点数 1000 /(2^31) = 4.6566e-07 (用Q31表示)。 对4.6566e-07求平方根可得 6.8239e-04。 定点数1465429 = 浮点数 1465429/(2^31) = 6.8239e-04。 简单的总结下上面的意思就是说,求定点数1000的平方根,实际是求浮点数4.6566e-07 (用Q31表示)的平方根。 10.3.3 arm_sqrt_q15 函数的定义如下: arm_status arm_sqrt_q15(q15_t in, q15_t * pOut) 这里in的输入范围是0x0000 到 0x7FFF,转化成浮点数范围就是[0 +1) 10.4 实例讲解(Matlab验证)实验目的: 1. 学习FastMathFunctions中的Sine,Cosine和Sqrt,并配合Matlab进行验证结果 实验内容: 1. 按下按键K1, 串口打印函数DSP_Cosine的输出结果 2. 按下按键K2, 串口打印函数DSP_Sine的输出结果 3. 按下按键K3, 串口打印函数DSP_Sqrt的输出结果 实验现象: 通过窗口上位机软件SecureCRT(V5光盘里面有此软件)查看打印信息现象如下(以按下K1为例): 程序设计: - /*2 D1 V! O( w2 F! _* h- }
- *********************************************************************************************************
: N: |9 M9 E( a& Z, h0 C9 ~ - * 函 数 名: DSP_Cosine: l; A" w- ^- \& u4 X
- * 功能说明: 求cos函数
+ t2 E. O3 ]' A; g5 G2 } - * 形 参:无+ m0 A8 `& H* n; e3 J7 e
- * 返 回 值: 无5 p9 |6 F8 J- B- t% M
- *********************************************************************************************************
4 h& k& k! A0 l - */9 ~. R" ~. d6 V* y
- static void DSP_Cosine(void)+ Y0 I; z& p; a: V g; i; Q
- {1 t* W9 @8 B. p& B
- q31_t pOut;2 X* j4 [) ~$ Z' g3 [
- float32_t pOut1;
! c! w( G x5 k9 U/ G7 Z% B0 V - uint16_t i;2 w# {+ a! C2 Y1 c( O$ }2 W
- /***************************cos函数*****************************************/+ i" ^! I1 P4 c7 {+ Q' H
- for(i = 0; i < 256; i++) (1)
: @6 I! D, P" L) a' c# Z - {
" o: E* e5 B0 t( j- J# c - /* 参数的输入范围是[0 2*pi) */
& ]+ S6 E, h" u1 X2 j: L - printf("%f\r\n", arm_cos_f32(i * PI / 128));
9 v) l* T3 n# n - }
& {9 Z8 c: v4 i% d# ?' l - printf("***************************************************************\r\n");
3 W: g. I% j; }: w1 q4 S8 X/ _3 G - for(i = 0; i < 256; i++)
$ a9 D/ _5 n3 F# u7 Q! q h7 j - {
& h; f; f7 C$ p) l. F - /* 这里是0 到 32767 对于[0 2*pi) */
+ Y g. T4 L+ b) [6 o - printf("%d\r\n", arm_cos_q15(i*128));" ]/ R- c) B, g( x% m$ h) [- b
- }- J, @# l7 d( w5 O/ ?6 L
- printf("***************************************************************\r\n");2 h% b0 k% k& Y: x' e* x4 h
- for(i = 0; i < 256; i++)0 b5 d# z9 I# Z
- {) j9 _0 F, I# c8 m
- /* 这里是0 到 2^31 - 1对应于[0 2*pi) */" M8 c \5 G# I! r) p, C# d
- printf("%d\r\n", arm_cos_q31(i*8388608));
9 k+ S& K3 U' f- `7 i - }: A/ H+ r8 L6 `6 l$ h
- printf("***************************************************************\r\n");7 x9 W5 k5 j$ z R
- }
4 d4 ]3 Z, M X7 v6 y -
2 P+ D1 v+ d7 `4 \ - /*, L$ `* k, P* q/ L% _! |
- *********************************************************************************************************" f3 F" [# |& u
- * 函 数 名: DSP_Sine
6 F$ U G* K: V7 [7 L3 \ - * 功能说明: 求sine函数
9 ?( \; ]; ?- k/ ~6 W' c - * 形 参:无* q: q* n* J+ Y! }- ?% F$ \' L D0 S
- * 返 回 值: 无
/ ?8 @! t5 O. y - *********************************************************************************************************
' V5 W& \1 A) E - */
7 J# ~$ D( P8 D/ I X D - static void DSP_Sine(void)
. B+ T! ~ L# M/ x! T+ Z0 J; S - {
6 z8 p" x# E$ P. l9 k) v/ o% O2 O# f - q31_t pOut;
& h$ X0 @/ P* M- R F$ g# _ - float32_t pOut1;1 `! v. C" G. P* Y2 \
- uint16_t i;
9 ^; Z4 d* U0 y8 {# |9 v6 Q& \! M - /***************************sin函数*****************************************/
- n% r$ P" z6 g, r( A9 s9 J4 k7 V - for(i = 0; i < 256; i++) (2) W8 f$ G4 a0 ?/ j6 ^9 O% c
- {7 J. L S# x: W
- /* 参数的输入范围是[0 2*pi) */
' T0 X. U8 n* J1 B; y+ K8 | - printf("%f\r\n", arm_sin_f32(i * PI / 128));
- g; }) o v6 L, ~ - }- ?2 U, M4 ?1 C! |& o3 x- m: b
- printf("***************************************************************\r\n");
! h; q' O1 y" R - for(i = 0; i < 256; i++)3 b/ k4 `6 X- u- I0 T5 g |. k
- {. u, K; A& C; X+ U5 ?( u
- /* 这里是0 - 32767 对于[0 2*pi) */
3 i+ W F- n2 K/ V - printf("%d\r\n", arm_sin_q15(i*128));6 `5 Z2 L7 r8 n; N. X" G8 d
- }' \0 k. L( W. j2 l U% }
- printf("***************************************************************\r\n");5 u8 P& u4 R+ Y0 m% g: Q
- for(i = 0; i < 256; i++)
2 Z5 m1 J- v/ `7 o' k0 e" ?! X/ N - {, x4 d) e) v8 N g
- /* 这里是0 - (pow(2, 31) - 1)对应于[0 2*pi) */: Z9 a/ D4 [# G* h3 z
- printf("%d\r\n", arm_sin_q31(i*8388608));, u @: C/ H2 ^6 c1 V
- }
8 ^ ]) b; c5 A - printf("***************************************************************\r\n");! K h: ~$ p8 @! v* C: M/ h7 _
- }
5 ^! C% S$ N) B - 2 i8 p. W1 E2 e5 G# |9 f6 R
- /** X; z0 _* g( ^( ~0 z% T3 x
- *********************************************************************************************************
: \; F2 [7 l# @9 P - * 函 数 名: DSP_Sqrt/ Q F: }, E6 K5 F2 Z; I
- * 功能说明: 求平方根$ f5 a& b' v6 ?+ N
- * 形 参:无
1 j" ?" J$ u1 Y+ @3 f2 z; d - * 返 回 值: 无
- J4 c$ }' l6 t9 q# d- w. j: N - *********************************************************************************************************
; e5 s% ?+ U# O# Z1 c* r+ ^ - */
$ ?: h* S/ P0 s' |- [ - static void DSP_Sqrt(void)7 H/ C3 ^- B% ]4 b4 i
- {- ]% u# } z. B+ J- o# z
- q31_t pOut;5 q" } v1 `& ~7 z6 N# q' T: h
- float32_t pOut1;6 o. P7 E4 n( Z3 |" f# k" ?
- /* 求平方根 */
8 I: d8 x% r }( N$ B* v D) k8 }0 v - arm_sqrt_q31(1000, &pOut); (3)
0 d4 t. Y2 ^' \$ l, z - printf("Value = %d\r\n", pOut);; J1 p0 T0 v( z5 B% l4 `6 o! ?1 X
- arm_sqrt_f32(1000, &pOut1);
8 t' l3 P2 I+ V3 `! u: ` - printf("Value = %f\r\n", pOut1);2 r. O6 X! v' @; h* _* u
- }
复制代码1. 这里我们采样了cos曲线一个周期中的256个点。为了验证结果是否正确,我们可以将这些数据保存到txt文档中,复制这256个数据即可,然后保存并关闭文档。通过matlab加载这个txt文档,加载方法如下: 打开后出现如下界面,点击按钮Next > 出现如下界面后点击按钮Finish,即可 然后再看工作区(Workspace)就能看到添加的数组变量了: 现在我们通过matlab中的plot功能绘制下这些数据,绘制方法如下: 绘制后的结果如下: 从波形上看基本是一个周期的cos函数曲线。下面我们在把cos_q31和cos_q15函数分别绘制一下。 (这里要特别的注意Y轴,这个数值要除以2^31才是实际的cos数值) # J$ l i* N6 m
(这里要特别的注意Y轴,这个数值要除以2^15才是实际的cos数值) 2. sin和cos基本是一样的,这里就不再赘述了。 3. 平方根的含义在10.3.1已经详细讲解了。 10.5 总结 本期教程就跟大家讲这么多,有兴趣的可以深入研究这些函数源码的实现。
8 B, m2 S8 y# K) | |