65人参与 • 2024-08-06 • stm32
最近,由于项目需要,学习了一下f4的fpu浮点数运算单元的使用方法和dsp库函数的建立使用,在此简单总结记录。
项目背景分析:
目标与流程梳理:
下面基于stm32f446ret6,使用标准库函数(版本:v1.8.0),在keil mdk 5.26环境下,完成上述需求。
fpu 即浮点运算单元(float point unit)。浮点运算,对于定点 cpu(没有 fpu 的 cpu)来说必须要按照 ieee-754 标准的算法来完成运算,是相当耗费时间的。而对于有 fpu 的 cpu来说,浮点运算则只是几条指令的事情,速度相当快。
stm32f4 属于 cortex m4f 架构,带有 32 位单精度硬件 fpu,支持浮点指令集,相对于cortex m0 和 cortex m3 等,高出数十倍甚至上百倍的运算性能。
打开system_stm32f4xx.c文件,在systeminit函数中,已规定了fpu的启用条件,即486行所示:
前者是要检查mcu是否拥有fpu,后者使能fpu,二者需同时满足。
打开stm32f4xx.h头文件,如下图第190行所示,文件已经在编译时将__fpu_present置为1,意思是该mcu存在fpu,那么下面只需关注如何将__fpu_used置1即可。
使能fpu的方法有很多,对于keil mdk环境,最方便的方法是在code generation中将floating point hardware配置为single precision,如下图所示:
经过这个设置,编译器会自动加入标识符__fpu_used为 1。 这样,遇到浮点运算就会使用硬件fpu相关指令,执行浮点运算,从而大大减少计算时间。
在调试窗口,可以看到对于进行浮点运算的指令,反汇编代码中存在xxx.f32的指令,说明fpu已开启,如下图所示。
需要注意,当运算中有浮点的数字时,数字后面要加上一个f,例如:
a = (float)para*9.1e-02f;
若不加f,keil会提示warning: #1035-d: single-precision operand implicitly converted to double-precision,意思是单精度运算隐式转换成了双精度运算了,运算速度将无法显著提升。
对于复杂运算,例如rms计算,如果编程时还是使用math.h头文件,效率提升很有限,因为math.h头文件是针对所有arm处理器的,其运算函数都是基于定点cpu和标准算法(ieee-754),没有使用fpu。因此,要充分发挥m4f的浮点功能,需要使用固件库自带的arm_math.h,即搭建dsp运行环境。
stm32f4的dsp库源码和测试实例在st提供的标准库:stm32f4_dsp_stdperiph_lib.zip里提供,官方下载链接:
http://www.st.com/web/en/catalog/tools/fm147/cl1794/sc961/ss1743/pf257901
这里使用v1.8.0版本的标准函数库,下载完成后打开dsp_lib源码包的source文件夹,里面存放了所有dsp库的源码, 如上图所示。examples文件夹是相对应的一些测试实例。以下是source源码文件夹下面的子文件夹包含的dsp库的功能:
所有这些dsp库代码合在一起是比较多的,因此,st提供了.lib格式的文件,方便使用。这些.lib文件就是由 source文件夹下的源码编译生成的,如果想看某个函数的源码,可在source文件夹下面查找。
我们需要根据所用mcu内核类型以及端模式来选择符合要求的 .lib文件,而stm32f4属于cortexm4f内核,小端模式,应选择: arm_cortexm4lf_math.lib(浮点cortex m4,小端模式)。
在工程目录下新建文件夹dsp,放置arm_cortexm4lf_math.lib和相关头文件,过程如图所示:
include文件夹直接拷贝stm32f4xx标准外设库_v1.8.0\libraries\cmsis\include中的所有文件。
打开工程,添加分组,将arm_cortexm4lf_math.lib添加到工程里面,如图:
添加好.lib文件后,要添加头文件包含路径,将第一步拷贝的include文件夹和dsp文件夹,加入头文件包含路径,如图:
最后,为了使用dsp库的所有功能,还需要添加几个全局宏定义:
arm_math_cm4
__cc_arm
arm_math_matrix_check
arm_math_rounding
对于stm32f446ret6,需要添加的所有宏为:
use_stdperiph_driver,stm32f446xx,arm_math_cm4,__cc_arm,arm_math_matrix_check,arm_math_rounding
注意两个宏之间用,隔开,如下图所示:
至此,dsp库运行环境搭建完成。
对于电压信号来说,rms是其方均根值,即有效值。与平均值的概念不同,rms直接反映信号的能量特征,对于连续的模拟信号而言,其定义计算式如下:
而对于经过adc采样后的数字信号而言,其计算式可表示为:
result = sqrt(((psrc[0] * psrc[0] + psrc[1] * psrc[1] + ... + psrc[blocksize-1] * psrc[blocksize-1]) / blocksize));
其中,result为rms计算结果,psrc[]为采样后的数字量,blocksize为处理的数据量。
打开statisticsfunctions文件夹中的arm_rms_f32.c文件,可见dsp库对于rms计算的函数定义,如下图所示:
因此,要使用arm_rms_f32函数,需要向其传递三个参数:
程序编写的整体思路是:
另外,若要实现实时信号rms计算处理,则要每存一个数据,计算一次rms值,即不断更新数组中的元素,这一需求可通过操作数组指针完成,当指针从数组首地址移动到尾地址时,将指针归位到首地址,思路上类似于数据结构中的循环队列。
为提高程序运行效率,数组元素的赋值采用指针操作,这样往往比下标的赋值方式更快。
根据上述思路,编写程序如下:
#include "pump.h"
#include "ads1256.h"
#include <stdio.h>
float datainput[data_length] = {0}; //传感器电压值存储数组、rms计算输入数据存储数组初始化
float *inputpoint = datainput; //输入数据数组指针初始化
float dataoutput; //计算后的rms值
float *outputpoint = &dataoutput; //计算结果变量指针
float *ifpoint = &datainput[data_length - 1] + 1; //判断指针,定义于输入数组的最后一个元素+1的地址处
int blocksize = 0; //每次rms计算的数据量
int npa_ddata; //差压传感器adc数字值
float npa_vdata; //差压传感器adc电压值
void flow_rms(void)
{
npa_ddata = ads1256readdata(ads1256_muxp_ain1|ads1256_muxn_aincom); //adc采集数据
npa_vdata = (float)npa_ddata/8388607.0f*5.0f; //转换为电压值
*inputpoint = npa_vdata; //把数据存入数组,指针指向数组中的某个元素地址
inputpoint ++; //地址+1,以存放下一个数据
if(blocksize != data_length) //若datainput数组中的元素数未满,则使rms计算的数据量+1,与当前数据量保持一致;反之则维持blocksize = data_length不变
blocksize ++;
if(inputpoint == ifpoint) //若输入数组的指针移动到数组的最后一个元素+1的地址处,则使指针重新归位
inputpoint = datainput;
arm_rms_f32(datainput, blocksize, outputpoint); //对采集的数据进行rms计算
printf("%f, %f\r\n", dataoutput, npa_vdata); //打印rms计算结果和实时信号值
}
#ifndef __pump_h
#define __pump_h
#include <stm32f4xx.h>
#include "arm_math.h"
#define data_length 250 //数组长度
void flow_rms(void);
#endif
void tim3_irqhandler(void)
{
if (tim_getitstatus(tim3, tim_it_update) != reset) //检查指定的tim3中断发生与否
{
tim_clearitpendingbit(tim3, tim_it_update); //清除tim3的中断待处理位
flow_rms();
}
}
使用微型气泵为差压传感器提供气压差源,配置不同占空比控制气泵抽气速率。确定条件下,使用vofa+上位机观察输出,结果如下:
可见,虽然输入为一系列不规则波形(与气泵引动的气流有关),但经rms计算,其均方根值基本稳定。由此可见,该方法非常适合于对不规则信号的直流化的应用中,如噪声计算等,此时应考虑硬件rms计算方案和软件哪种更合适。
后续程序可根据实际应用,加以完善。
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论