
在STM32的应用开发过程中,我们有时可能涉及到DSP应用,需要使用到相关DSP函数。这里基于STM32H743芯片的Nucleo开发板,做个有关矩阵运算应用的演示,简单的演示下两个矩阵相乘的实现过程。 ! j* C5 Y5 m$ a7 i+ [! R( v$ g 开发环境选择的是ARM MDK,当然你也可以选其它的,比方IAR, STM32CubeIDE等。4 E' P' b& o5 H' E, w 0 M& J4 z5 Q S1 [4 _6 B 2 A. G, j: l! m- o* ]2 _9 c 我们要用到ARM提供的DSP函数库,该库在STM32的Cube库或标准库里都可以找到。 以STM32CubeH7的库为例,相应的DSP函数库一般在下面位置:; S! b3 G8 d% b, f 1 ^, P E& Q. R : k* T$ U/ u; C0 B$ I9 x ![]() ( ^1 J T$ B/ F$ x # U' j7 K/ t) | 上图中绿色方框内的函数即为跟矩阵相关的函数库文件。5 h- i- k& p8 o+ E, r7 g 具体使用时,我们直接添加相应的lib库进来即可,不过,添加该lib库文件时要注意两点: 1 U( H* B7 E1 y$ ` 0 B. U- p6 S# _! m6 `0 E 你选择的库文件要跟你芯片类型一致,内核类型、大小端模式、是否支持浮点运算。 i9 p: l/ {2 m4 H' _ 3 Y7 m& C7 T& f- q( z) j# C 你选择的库文件还要跟你所使用的编译器匹配,即IDE是MDK还是IAR等。; z4 W& U* S' F1 K 6 J! T: E4 n% d- u1 e, U 基于上面两点我们添加arm_cortexM7lfdp_math.lib文件【corex M7、小端模式、支持硬件浮点单元】。 ![]() 在我们的main()文件里添加arm_math.h头文件。记得在IDE环境的配置里添加相应的搜索路径。启用硬件浮点运算单元。开启有关宏定义。【宏开关不用特别去记,缺少的话编译时会报错】 - c7 L/ `6 y' m , Q* z4 V" L3 t6 U ![]() 3 ^: H2 A; d/ C: X" D" u% G& J : ^" u, _0 h; x6 ~9 u* i7 ?# H' z 下面构造三个矩阵,A矩阵的数据表示某家芯片代理商为他的8个客户分别提供四种不同规格的芯片,数据以包为单位。不同型号的包装规格不一样。A矩阵为8X4矩阵。 % L2 M# F% H) c) b B矩阵表示A矩阵中各类包装每包的数量、价格、运费、重量,为4X4矩阵。 二者的矩阵乘积表示各个收货方收到芯片的总数、应付货款、运费、以及货物总重量,将构成8X4矩阵。矩阵里的数据使用浮点数,数据随意设计的。 我们知道,两个矩阵可乘有个前提,比方A*B,矩阵A的列数应该等于矩阵B的行数,相乘后所得的乘积矩阵的行数等于矩阵A的行数,其列数等于矩阵B的列数。 6 l2 `6 C* c, \- v2 @ 具体到这里,矩阵A的行数为8,列数为4,矩阵B的行数、列数均为4。A*B所得矩阵的行数为8,列数为4. , n) R- }' q, A* H ![]() ![]() / U6 a& O1 Q$ F6 @ E) A% a 5 m% ]8 X! t" v' @. G 下面做相关代码的准备。7 [0 ?7 L" @2 R 定义三个数组,pDataA[32]数组对应矩阵A, pDataB[16]数组对应矩阵B,第3个数组pDataC[32]对应矩阵AB乘积所得的新矩阵。 ' Q. j* ?6 ]9 G0 w r$ J " S; D/ V* b1 F! r- ^ ![]() 基于上面的3个数组定义3个如下矩阵变量: " o" I, b/ ?$ ?# K6 W % w5 @4 N2 Q8 c' S7 b( y ![]() 关于结构体arm_matrix_instance_f32的定义和说明,可以在arm_math.h中看到。; V. m+ c' D, o$ |9 V" p o9 q% g : c& c! n' B+ g5 G ![]() 接下来对3个矩阵进行初始化,注意行、列数别给错了。 1 @; c- ?+ N# t @# Y" Q ![]() 一切都准备好了,就可以进行矩阵乘法计算了,调用库函数中arm_mat_mult_f32()函数。 ![]() $ y) b4 {( c) j: R4 ~ 矩阵相乘后的运算结果存放在数组pDataC[32]里面,按8*4的矩阵摆放。& V: X8 e8 J4 B ![]() 8 D8 Z Y- ~8 U0 w/ M) h3 W( E2 L j ; D' l9 c6 r7 @' ? 上述运算结果跟使用MATLAB数学工具通过矩阵乘法得到的结果整体上非常一致。数据会稍有些小出入,毕竟是基于浮点运算所得结果。 我们知道,STM32H7是带Cache和FPU的。不妨基于该矩阵乘法应用比较不同情况下的运行时间。以定时器的计数时钟为单位。根据Cache和FPU的开启与关闭的不同组合进行测试,可以做些相对比较,让我们有些直观的感受。测试时ARM MDK的优化等级为-o3。顺便提醒下,如果不开启硬件FPU,调用的DSP库函数应选择另外一个不支持硬件浮点单元的函数库。 ![]() : z1 a; C$ x- C/ v. n, \ 下面数据是基于上面测试代码所得到的,其中红色数据为十进制数据。3 P' y! s" e6 v3 {$ y* V ] & R5 }9 [: }! [9 \3 ?# ~# @/ p" _# R , \7 J' S7 T g6 n* V ![]() : K9 Q/ M! y$ o' K; V , X% Y e" Q; r 从这里我们可以看出,同时开启硬件FPU和Cache与同时关闭二者,运行时间相差将近40倍;开启Cache与关闭Cache运行时间上相差4倍左右;使用FPU和不用FPU,运行时间相差8倍左右。当然,或许基于不同的应用,上述数据可能存在些差异,但可以肯定,开与不开Cache、启不启用硬件FPU,运行速度上的差别还是很明显的。+ u' e- i7 f% b# @1 J/ x 0 i+ y. U. ]# ]0 X 好,关于利用STM32及相关DSP函数库进行矩阵运算的演示就介绍到这里,请留意上文中谈到的那些提醒。其它更多细节,有兴趣的话可以进一步阅读和研究相关资料。) v: i2 L3 x9 P2 i0 l0 O: M |
拷打cubemx【003】——找不到的芯片包
【2025·STM32峰会】GUI解决方案实训分享5-调通板载的NRF24L01 SPI接口并使用模块进行无线通信(发送和接收)
【2025·STM32峰会】GUI解决方案实训分享4-使用MVP架构从硬件外设读取数据并显示到图形界面、从图形界面发送指令控制硬件外设
【2025·STM32峰会】GUI解决方案实训分享3-搭建空白TouchGFX例程并实现简单的功能(含硬件部分的串口打印)
【2025·STM32峰会】GUI解决方案实训分享2-编译运行TouchGFX咖啡机例程(含桌面仿真)
【2025·STM32峰会】+TouchGFX实现动态进度显示以及界面切换
【2025·STM32峰会】+使用TouchGFX快速创建GUI
【2025·STM32峰会】GUI解决方案实训分享1-对LVGL咖啡机例程的牛刀小试以及问题排查
MCSDK FOC应用详解
实战经验 | 关于STM32H7使用LL库生成ADC代码工作异常问题说明