特别说明:完整45期数字信号处理教程,原创高性能示波器代码全开源地址:链接$ @5 n8 `5 t( J7 M" r: _0 W2 P
第10章 FastMathFunctions的使用 8 T. ~5 i, @& p3 `
本期教程开始,我们将不再专门的分析DSP函数的源码,主要是有些DSP函数的公式分析较麻烦,有兴趣的同学可以自行研究,本期教程开始主要讲解函数如何使用。 10.1 三角函数Cosine 10.2 三角函数Sine 10.3 平方根Sqrt 10.4 实例讲解(Matlab验证) 10.5 总结 : T( j0 d0 u% \' ~1 ]; A/ v5 N) u
10.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为例): 程序设计: - /*
+ _6 b3 G6 h, b' a - *********************************************************************************************************
' K$ M, J8 n e8 ~8 P3 C - * 函 数 名: DSP_Cosine. H) m4 u- Y r) M- R* H
- * 功能说明: 求cos函数
! o9 K0 ]- l' c: e+ ? - * 形 参:无
* X& {+ m$ c! }% R - * 返 回 值: 无( J; l& }( ]% A9 Y+ q1 @
- *********************************************************************************************************: o& L3 s5 P% y( g% z
- */; T$ B, ~4 R* D! T8 w
- static void DSP_Cosine(void)
, N' d1 J; v. t% f - {
; G1 z1 c" B( Q# U! L - q31_t pOut;# G* a" B. a, y/ P. i: p" f+ B
- float32_t pOut1;
) }0 x- W' d; b$ Z6 ~. P' [/ I, Q - uint16_t i;3 y' c0 |7 ^% ~) ?' E
- /***************************cos函数*****************************************/
3 a2 Y! P) g* g: D6 Y2 r' D - for(i = 0; i < 256; i++) (1). \3 v# T: T/ k1 n2 n# Q, i/ L ~
- {
; X( z& v. n; r" I: u3 w# F - /* 参数的输入范围是[0 2*pi) */$ A- D K3 _7 g; {
- printf("%f\r\n", arm_cos_f32(i * PI / 128));: @; y* Y' p" a* G! _
- }$ b# v; k B O0 J- P
- printf("***************************************************************\r\n");( d+ W% g* w5 i$ n! p
- for(i = 0; i < 256; i++)$ D4 ~* n- n+ n4 ]0 d
- {
+ v# w. Q+ E3 \4 F3 s5 s - /* 这里是0 到 32767 对于[0 2*pi) */* N5 H) S1 v6 J l! X
- printf("%d\r\n", arm_cos_q15(i*128));8 N) {& W% U- V3 O( a, R/ r* q
- }, }7 O7 Z; T+ e: J: A7 R, E& V0 Y( j0 Q
- printf("***************************************************************\r\n");
: H5 c1 t% | b* ~' } - for(i = 0; i < 256; i++)
' H$ j% |/ h" Z* K - {
/ E. Z* |- h" T7 ~$ }1 N# ? - /* 这里是0 到 2^31 - 1对应于[0 2*pi) */
7 n. q6 v8 p* L0 a3 A% [+ m0 w# E - printf("%d\r\n", arm_cos_q31(i*8388608));
; _5 r+ V8 \0 i- U# B1 w7 I - }4 E) ]3 h' K6 M& h/ b
- printf("***************************************************************\r\n");
4 a' k# X {. _5 p( @9 U, n+ z - }/ [9 @' j# R8 E3 L! \8 r+ I, C4 R
- * F: r8 C$ F8 L v9 o
- /*
# \2 @- ?1 ?: [! ^% [ - *********************************************************************************************************
7 a6 l- t) J* r/ l a - * 函 数 名: DSP_Sine
1 F/ e' e- V. p) f! Y- b - * 功能说明: 求sine函数
2 u% E% o( Z6 m' E, \ - * 形 参:无
! Y- a h! Q1 Y2 a0 X6 s - * 返 回 值: 无
# l( k) s$ i; k% L6 } - *********************************************************************************************************
' c: @- W( Z1 P1 n, v - */
8 Q- x) U0 n% X1 x& }5 _7 ?, r6 j3 s - static void DSP_Sine(void)) a' @) s+ |7 `" H# B3 c h
- {
! a1 k" l& z \" x* E1 j m" h - q31_t pOut; y+ m3 @3 ~; j
- float32_t pOut1;& E& X7 t# I# w8 ~7 `/ h
- uint16_t i;/ m* a# [3 [) {+ D" D4 \" {( `# g" j
- /***************************sin函数*****************************************/
0 l1 U) C$ Q0 F% ] - for(i = 0; i < 256; i++) (2)
2 O6 Z& o! r. u, b# X9 H - {4 i3 _# `* j, d6 `" n* E s3 e
- /* 参数的输入范围是[0 2*pi) */
" p; b6 M) V! |$ j7 e1 u; o# t - printf("%f\r\n", arm_sin_f32(i * PI / 128));
( E5 g0 s' A0 l - }+ f4 n2 k. T( ~) N5 U1 E# a
- printf("***************************************************************\r\n");
8 u3 h( M0 s q" f) a% E( X& c - for(i = 0; i < 256; i++)
4 M! h' G" w' k" l0 q* P4 b/ C - {
# F( \& Q9 S& r0 \0 A0 Y - /* 这里是0 - 32767 对于[0 2*pi) */4 \- i, A |( y8 T
- printf("%d\r\n", arm_sin_q15(i*128));% T1 y, b1 ^ P+ }. r
- }
; `" q2 R8 [/ B3 P' L - printf("***************************************************************\r\n");
5 t3 \$ s0 t) b, o p - for(i = 0; i < 256; i++)
' h- }3 p- U X4 b$ F - {9 G% O% S/ b: Z8 ?8 Y! p4 m
- /* 这里是0 - (pow(2, 31) - 1)对应于[0 2*pi) */
$ H L+ a* u2 D# A- ^( e% S - printf("%d\r\n", arm_sin_q31(i*8388608));! p& `) m+ c9 E1 y
- }* j+ J% B0 s; B r2 C
- printf("***************************************************************\r\n");5 ^7 I2 d3 ?. ~ d" Y, w$ K2 c6 C
- }) N: O% c( a L- b) l2 y/ ^
-
+ H- `4 L, S4 j u& f - /*
( o# I% l( y- i) h" U1 @/ B - ********************************************************************************************************** E) g; W! y" `. J: Q* v, _6 z
- * 函 数 名: DSP_Sqrt( T" ?; D7 r3 d
- * 功能说明: 求平方根
/ n$ i ?( Z0 ?9 b7 ~- Y1 V K7 Q - * 形 参:无
0 x3 d# b6 _- v8 b, b - * 返 回 值: 无) r1 D, a( E. H
- *********************************************************************************************************4 v/ r$ V+ M' ~, X) d* Y
- */
2 k0 v8 q" F* u& h8 `* j% j4 H - static void DSP_Sqrt(void)* |( z0 R7 n* v$ E2 W8 X# \* y4 A q; t
- {
) q3 K5 E4 F* F9 ?& D# v0 P" M - q31_t pOut;
- o3 a- m/ m- R - float32_t pOut1;8 c8 r2 Y1 \9 D& `3 P
- /* 求平方根 */
8 r* b5 S, _( \+ K - arm_sqrt_q31(1000, &pOut); (3)
3 m& @* h/ a. {3 k& T: w - printf("Value = %d\r\n", pOut);; c* r3 p7 Q+ _- `$ k
- arm_sqrt_f32(1000, &pOut1);
7 L1 K, v3 f% m0 _ f5 w, ] - printf("Value = %f\r\n", pOut1);. |; d- e+ O3 G; b8 N! L2 z
- }
复制代码1. 这里我们采样了cos曲线一个周期中的256个点。为了验证结果是否正确,我们可以将这些数据保存到txt文档中,复制这256个数据即可,然后保存并关闭文档。通过matlab加载这个txt文档,加载方法如下: 打开后出现如下界面,点击按钮Next > 出现如下界面后点击按钮Finish,即可 然后再看工作区(Workspace)就能看到添加的数组变量了: 现在我们通过matlab中的plot功能绘制下这些数据,绘制方法如下: 绘制后的结果如下: 从波形上看基本是一个周期的cos函数曲线。下面我们在把cos_q31和cos_q15函数分别绘制一下。 (这里要特别的注意Y轴,这个数值要除以2^31才是实际的cos数值) 1 e$ R( B; B* m2 x" r+ h _. S, K+ s
(这里要特别的注意Y轴,这个数值要除以2^15才是实际的cos数值) 2. sin和cos基本是一样的,这里就不再赘述了。 3. 平方根的含义在10.3.1已经详细讲解了。 10.5 总结 本期教程就跟大家讲这么多,有兴趣的可以深入研究这些函数源码的实现。 ; M6 U7 A7 c# [& p0 Q+ K+ b
|