1 . 建立工程,生成代码时选择包含所有库。
 
2. 打开 option for target 选择 Target 标签,在code generatio中,将floating point hardware 选择 USE Single Precision。
 
3.  打开 option for target 选择 C/C++ 标签

在define后添加:__TARGET_FPU_VFP,ARM_MATH_MATRIX_CHECK,ARM_MATH_ROUNDING,ARM_MATH_CM4,__CC_ARM,由于使用HAL的库,所以前面有USE_HAL_DRIVER,STM32F429xx的全局宏定义,如果使用的不是HAL库,而是使用固件库的话,一般会有固件库的一个全局宏定义USE_STDPERIPH_DRIVER和STM32F4XXxx在里面。所以当前只需要添加
__TARGET_FPU_VFP,
ARM_MATH_MATRIX_CHECK,
ARM_MATH_ROUNDING,
ARM_MATH_CM4,
__CC_ARM
注意中间用英文逗号分开。其中ARM_MATH_MATRIX_CHECK是库函数的参数检查开关。ARM_MATH_ROUNDING这个是库函数在运算是是否开启四舍五入的功能,可以根据实际需要进行配置。ARM_MATH_CM4这个就非常重要,必须要配置进去,否则在编译之后,会默认使用math.h的库函数,而不会用到硬件的FPU的。__CC_ARM是不同编译器的编译配置宏定义,__CC_ARM就是代表MDK开发环境。
 4. 添加浮点库(.lib)文件到工程(或者添加源码库文件)。

如果用的是 uv4,打开 C:\Keil\ARM\CMSIS\Lib\ARM 目录,复制“arm_cortexM4lf_math.lib”文件到你的工程下,并加入工程。
如果用的是 uv5,打开 C:\Keil_v5\ARM\Pack\ARM\CMSIS\4.2.0\CMSIS\Lib\ARM 目录,复制“arm_cortexM4lf_math.lib”文件到工程下,并加入工程,4.2.0是库的版本,每个版本可能不一样。
也可以从官方下载固件库程序包中复制也行,  \STM32F4xx_DSP_StdPeriph_Lib\Libraries\CMSIS\Lib\ARM
如果查看DSP库的各个函数的原型,可以添加源码库文件, 则当前工程目录下的Drivers\CMSIS\DSP_Lib\Source目录可以查看,当然安装目录下也有该库源文件。
BasicMathFunctions
基本数学函数:提供浮点数的各种基本运算函数,如向量加减乘除等运算。 
CommonTables
arm_common_tables.c文件提供位翻转或相关参数表。
ComplexMathFunctions
复杂数学功能,如向量处理,求模运算的。
ControllerFunctions
控制功能函数。包括正弦余弦,PID电机控制,矢量Clarke变换,矢量Clarke逆变换等。
FastMathFunctions
快速数学功能函数。提供了一种快速的近似正弦,余弦和平方根等相比CMSIS计算库要快的数学函数。
FilteringFunctions
滤波函数功能,主要为FIR和LMS(最小均方根)等滤波函数。 
MatrixFunctions
矩阵处理函数。包括矩阵加法、矩阵初始化、矩阵反、矩阵乘法、矩阵规模、矩阵减法、矩阵转置等函数。
StatisticsFunctions
统计功能函数。如求平均值、最大值、最小值、计算均方根RMS、计算方差/标准差等。
SupportFunctions
支持功能函数,如数据拷贝,Q格式和浮点格式相互转换,Q任意格式相互转换。
TransformFunctions
变换功能。包括复数FFT(CFFT)/复数FFT逆运算(CIFFT)、实数FFT(RFFT)/实数FFT逆运算(RIFFT)、和DCT(离散余弦变换)和配套的初始化函数。
相关函数说明以及示例也可在安装路径Keil_v5\ARM\PACK\ARM\CMSIS\4.5.0\CMSIS\Documentation\DSP\html下获得,自行查阅。
5. DSP库的FFT变换示例。
在工程的main.c文件中添加如下代码
说明:采样频率为1024Hz,fft点数为1024点,则频率分辨率,计算公式:分辨率=采样频率/采样点数 = 1Hz,此时能看到0Hz,1Hz,2Hz,3Hz,.....512Hz的频率分量。
FFTOutput这个数组中,下标0对应的元素就是0Hz(也就是直流分量)的幅度,下标1对应的就是1Hz的幅度,下标2对应2Hz的幅度......,依次类推。
此点非常重要,例如采样率为2048Hz,那么频率分辨率为2Hz,那么能看到0Hz,2Hz,4Hz,6Hz,.....1024Hz的频率分量
FFTOutput这个数组中,下标0对应的元素就是0Hz(也就是直流分量)的幅度,下标1对应的就是2Hz的幅度,下标2对应4Hz的幅度......,依次类推。此时去看1Hz,3Hz,则会出现误差比较大的情况。
#include "arm_math.h"                  //添加头文件
#define FFT_LENGTH 1024 //FFT长度,默认是1024点FFT
#define SAMPLE_FREQ 1024 //采样频率
float fft_inputbuf[FFT_LENGTH*2];      //FFT输入输出数组,此数组为arm_cfft_radix4_f32的输入输出数组,前一个元素为实部,后一个为虚部,每两个元素代表一个点.
float fft_outputbuf[FFT_LENGTH]; //arm_cmplx_mag_f32()幅度输出数组
arm_cfft_radix4_instance_f32 scfft; //fft变换的初始化参数

在主函数进入while(1)之前添加如下代码

说明:arm_sin_f32函数生成采样点,采样信号为DC信号,100Hz,150Hz信号的叠加,此时分辨率为1Hz,刚好能够看到DC, 100Hz,150Hz频率分量的幅度,分别对应fft幅度输出数组的下标0,100,150

arm_cfft_radix4_init_f32(&scfft,FFT_LENGTH,0,1);//初始化scfft结构体,设定FFT相关参数
for(int i=0;i<FFT_LENGTH;i++)//生成信号序列
{
fft_inputbuf[2*i]=15 + 10*arm_sin_f32(2*PI*i*100/SAMPLE_FREQ) + \
5.5*arm_sin_f32(2*PI*i*150/SAMPLE_FREQ); //生成实部
fft_inputbuf[2*i+1]=0;//虚部全部为0
}
arm_cfft_radix4_f32(&scfft,fft_inputbuf); //FFT计算(基4(即fft长度22*n),FFT长度只能为64,256,1024,4096目前测试过这几个长度,)
arm_cmplx_mag_f32(fft_inputbuf,fft_outputbuf,FFT_LENGTH); //把运算结果复数求模得幅值

DC分量值为15360.001,则对应的直流分量为15360.001/FFT点数 = 15360.001/1024=15

100Hz分量值为5119.99658,则对应的100Hz幅度为5119.99658*2/FFT点数 = 5119.99658*2/1024=10

150Hz分量值为2815.99976,则对应的150Hz幅度为2815.99976*2/FFT点数 = 2815.99976*2/1024=5.5

其余的频率的幅度近似为0。

若要查看某一频率分量的实部与虚部,则可以查看fft_inputbuf数组。下标对应乘以2,因为实部和虚部存在。

当把采样频率改为2048Hz,生成信号频率其中一路改为151Hz,读者可以自行测试该频率分量的幅度,肯定会存在误差。



基于HAL库的STM32的DSP库详解(附FFT应用)的更多相关文章

  1. 基于STM32的uCOS-II移植详解

    百度:基于STM32的uCOS-II移植详解 源:基于STM32的uCOS-II移植详解

  2. 对python3中pathlib库的Path类的使用详解

    原文连接   https://www.jb51.net/article/148789.htm 1.调用库 ? 1 from pathlib import 2.创建Path对象 ? 1 2 3 4 5 ...

  3. 基于python中staticmethod和classmethod的区别(详解)

    例子 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 class A(object):   def foo(self,x):     print "executing foo ...

  4. 基于Python对象引用、可变性和垃圾回收详解

    基于Python对象引用.可变性和垃圾回收详解 下面小编就为大家带来一篇基于Python对象引用.可变性和垃圾回收详解.小编觉得挺不错的,现在就分享给大家,也给大家做个参考. 变量不是盒子 在示例所示 ...

  5. 【转】VS2013动态库文件的创建及其使用详解

    一.VS2013动态库文件的创建 1.新建项目,win32,win32项目,输入项目名称,例如MakeDll. 2.”确定“——”下一步“,选择”DLL“选项,再点”完成“: 3.菜单栏选择”项目“— ...

  6. C运行时库(C Run-time Library)详解(提供的另一个最重要的功能是为应用程序添加启动函数。Visual C++对控制台程序默认使用单线程的静态链接库,而MFC中的CFile类已暗藏了多线程)

    一.什么是C运行时库 1)C运行时库就是 C run-time library,是 C 而非 C++ 语言世界的概念:取这个名字就是因为你的 C 程序运行时需要这些库中的函数. 2)C 语言是所谓的“ ...

  7. STM32时钟配置方法详解

      一.在STM32中,有五个时钟源,为HSI.HSE.LSI.LSE.PLL. ①HSI是高速内部时钟,RC振荡器,频率为8MHz. ②HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源, ...

  8. 基于Docker搭建Maven私服Nexus,Nexus详解

    备注:首先在linux环境安装Java环境和Docker,私服需要的服务器性能和硬盘存储要高一点,内存不足可能到时启动失败,这里以4核8GLinux服务器做演示 一:基于Docker安装nexus3 ...

  9. iOS framework静态库中使用xib和图片资源详解

    一.新建bundle 前2篇文章介绍了iOS 最新framework和.a静态库制作及使用全解   iOS 工程套子工程,主工程和framework工程或.a library静态库工程联调 我现在是在 ...

随机推荐

  1. 【开源】使用.Net Core和GitHub Actions实现哔哩哔哩每日自动签到、投币、领取奖励

    BiliBiliTool是一个B站自动执行任务的工具,使用.NET Core编写,通过它可以实现B站帐号的每日自动观看.分享.投币视频,获取经验,每月自动领取会员权益.自动为自己充电等功能,帮助我们轻 ...

  2. PLC扩展模拟量输入模块是什么

    PLC模拟量输入模块就是采集电压.电流.热电阻.热电偶或者是温度等模拟量的采集模块,然后再通过总线传输到电脑上的智能模块.其实就是一款将远程现场的模拟量信号采集到计算机的设备,模拟量是表示了在一定的范 ...

  3. 敲黑板:InnoDB的Double Write,你必须知道

    世界上最快的捷径,就是脚踏实地,本文已收录[架构技术专栏]关注这个喜欢分享的地方. 前序 InnoDB引擎有几个重点特性,为其带来了更好的性能和可靠性: 插入缓冲(Insert Buffer) 两次写 ...

  4. leetcode113:sudoku-solver

    题目描述 请编写一个程序,给数独中的剩余的空格填写上数字 空格用字符'.'表示 假设给定的数独只有唯一的解法 这盘数独的解法是: 红色表示填上的解 Write a program to solve a ...

  5. Android基础——项目的文件结构(一)

    Android基础--项目的文件结构(一) Android视图与Project视图对比 [注]此项目文件结构仅限于Android Studio下的Android项目!!! 在Android Studi ...

  6. Blog.Core 项目已完成升级.NET5.0

    (是时候拿出来这种图了) 本文首发于公众号,但是会有新的内容加进来,所以就在博客园新开了一篇,望见谅.截止发稿,Blog.Core项目Master分支已经迁移到了5.0,新建了3.1的分支. 开心的锣 ...

  7. 跟我一起学Redis之Redis事务简单了解一下

    前言 关系数据库中的事务,小伙伴们应该是不陌生了,不管是在开发还是在面试过程中,总有两个问题逃不掉: 说说事务的特性: 事务隔离级别是怎么一回事? 事务处理不好,数据就可能不准确,最终就会导致业务出问 ...

  8. 深入探讨HBASE

    HBASE基础 1. HBase简介HBase是一个高可靠.高性能.面向列的,主要用于海量结构化和半结构化数据存储的分布式key-value存储系统. 它基于Google Bigtable开源实现,但 ...

  9. [MIT6.006] 14. Depth-First Search (DFS), Topological Sort 深度优先搜索,拓扑排序

    一.深度优先搜索 它的定义是:递归探索图,必要时要回溯,同时避免重复. 关于深度优先搜索的伪代码如下: 左边DFS-Visit(V, Adj.s)是只实现visit所有连接某个特定点(例如s)的其他点 ...

  10. TCP中RTT的测量和RTO的计算 以及 接收缓存大小的动态调整

    RTT测量 在发送端有两种RTT的测量方法,但是因为TCP流控制是在接收端进行的,所以接收端也需要 有测量RTT的方法. /* Receiver "autotuning" code ...