STM32CubeMX配置ADC采样(轮询、中断、DMA)

选择DMA循环采集DMA_CIRCULAR

uint16_t ADCRes[ADC_DMA_BUF_SIZE]; //变量易变,编译器不能随便优化

#define ADC_Ech_Channel 3

#define ADC_DMA_BUF_SIZE 10 * ADC_Ech_Channel/* ADC DMA采集 BUF大小, 应等于ADC通道数的整数倍 */

HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADCRes, ADC_DMA_BUF_SIZE*2);

循环采集不需要打开下面停止重启DMA采集的注释

void DMA1_Channel1_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
//    HAL_GPIO_TogglePin(GPIOB,LED_RED_Pin);
  adc_dma_ok = 1;                      /* 标记DMA传输完成 */
//    HAL_ADC_Stop_DMA(&hadc1);
    
  /* USER CODE END DMA1_Channel1_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_adc1);
  /* USER CODE BEGIN DMA1_Channel1_IRQn 1 */
//    HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADCRes, ADC_DMA_BUF_SIZE*2);
    
  /* USER CODE END DMA1_Channel1_IRQn 1 */
}

选择定时器触发

使用串口绘制实时曲线 —— SerialChart - QIYUEXIN - 博客园

https://www.cnblogs.com/qiyuexin/p/7067646.html

(388条消息) 串口波形显示软件SerialChart的使用_天外飞仙CUG的博客-CSDN博客

https://blog.csdn.net/zhang062061/article/details/114109581

(387条消息) STM32_如何添加DSP库_stm32 dsp_江湖上都叫我秋博的博客-CSDN博客

https://blog.csdn.net/heqiunong/article/details/124346055

生成项目后,我们需要的DSP库已经包含到STM32CubeMX生成的项目文件夹中了

路径: 项目路径/Drivers/CMSIS/DSP

打开项目后,需要更改三个位置

  1. 把arm_cortexM4lf_math.lib包含到项目中

  1. 把arm_cortexM3l_math.lib包含到项目中

添加一个预定义 " ,ARM_MATH_CM4

3、添加包含路径 Include Paths。" 项目路径/Drivers/CMSIS/DSP/Include "

测试代码

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"
 
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "arm_math.h"    // 包含一个arm_math.h
/* USER CODE END Includes */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
float data;                // 定义一个全局变量
/* USER CODE END 0 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
        data = arm_sin_f32(3.1415926/6);    // 用DSP库里面的函数arm_sin_f32计算 sin(Π/6)
  }
  /* USER CODE END 3 */

测试结果

方法2:(388条消息) STM32CubeMX关于添加DSP库的使用_W_oilpicture的博客-CSDN博客

https://blog.csdn.net/WandZ123/article/details/125593908

(387条消息) 音乐频谱显示小玩具——FFT在STM32中的实现与应用_max4466电路图_To丶紫罗兰的博客-CSDN博客

https://blog.csdn.net/qq_24025329/article/details/105563919?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-8-105563919-blog-90042669.pc_relevant_3mothn_strategy_and_data_recovery&spm=1001.2101.3001.4242.5&utm_relevant_index=11

https://www.likecs.com/show-203853067.html

(387条消息) stm32f1单片机上用FFT测量信号频率(高精度、过程详细)_stm32 fft_Mr Justin的博客-CSDN博客

https://blog.csdn.net/weixin_43368814/article/details/103552114?spm=1001.2101.3001.6650.10&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-10-103552114-blog-108143282.pc_relevant_3mothn_strategy_and_data_recovery&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-10-103552114-blog-108143282.pc_relevant_3mothn_strategy_and_data_recovery&utm_relevant_index=14

void DMA1_Channel1_IRQHandler(void)
{
  u16 i = 0;
    
  DMA_Cmd(DMA1_Channel1, DISABLE);

  DMA_ClearITPendingBit(DMA_IT_HT);
  DMA_ClearITPendingBit(DMA1_IT_TC1);        //清除中断标志位
  for(i=0;i<NPT;i++)
    InBufArray[i] = ((signed short)(ADC_Value[i])) << 16;  //左移16位,高16位存放实部

    cr4_fft_1024_stm32(OutBufArray, InBufArray, NPT);
    GetPowerMag();                          //获取信号谐波分量的幅值
    DMA_Cmd(DMA1_Channel1, ENABLE);
}

(387条消息) 基于STM32的FFT频谱分析+波形识别_stm32fft频谱分析__鑫鑫鑫_的博客-CSDN博客

https://blog.csdn.net/qq_42628795/article/details/95314989?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-4-95314989-blog-103552114.pc_relevant_3mothn_strategy_and_data_recovery&spm=1001.2101.3001.4242.3&utm_relevant_index=7

基于HAL库的STM32的DSP库详解(附FFT应用) - 廖伟伟 - 博客园

https://www.cnblogs.com/lwwBKY/p/14063829.html

如果查看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下获得,自行查阅。

(387条消息) STM32F103如何实现 FFT?_wenzi嵌入式软件的博客-CSDN博客

https://blog.csdn.net/weixin_42616791/article/details/108419412?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167954053316800213025098%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=167954053316800213025098&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-2-108419412-null-null.article_score_rank_blog&utm_term=STM32103%20FFT%E9%A2%91%E8%B0%B1%E5%88%86%E6%9E%90&spm=1018.2226.3001.4450

FFT 变换之后和原始信号的对应关系

假设我们对一个波形进行了采样,采样了 N 个点,经过 FFT 之后,就可以得到 N 个点的 FFT 结果,每一个点就对应着一个频率点。这个点的模值,就是该频率下的幅度特性。具体的关系就是如果原始信号的峰值为 A ,那么 FFT 的结果的每个点的模值就是 A 的 N / 2 倍。而第一个点就是直流分量,它的模值是直流分量的 N 倍。而每个点的相位就是在该频率下的信号的相位,第一个点表示的是直流分量,也就是 0 HZ的点,而最后一个点 N 的再下一个点(实际这个点是不存在的),也就是 N+1 个点则表示的是采样频率 Fs,这中间被 N - 1 个点平均分成 N 等份,每一个点的频率依次增加。也就是如果要计算某个点的频率,那么就只需要这样计算即可:Fn = (n - 1) * Fs / N。

从上述所展示的公式,我们可以知道 Fn 所能够分辨的频率为 Fs / N,如果采样频率 Fs 为 1024Hz,采样点数为 1024 点,则可以分辨到 1 HZ。也就是说采样 1s 时间的信号并做 FFT ,则结果可以分析精确到 1 Hz,如果采样 2 s 时间的信号并做 FFT,则结果可以分析精确到 0.5 Hz,所以也就说明了一个道理,如果要提高频率分辨率,则必须增加采样点数,也就是采样时间,下面这张图更能够清晰地表示这种关系:

将原信号变换之后的频谱的宽度与原始信号也存在一定的关系。根据 Nyquist采样定律,FFT 之后的频谱宽度最大只能是原始信号采样率的 1/2,如果原始信号的采样频率为 4GS/s,那么 FFT 之后的频宽最多只能是 2GHz,这还只是理想情况。所以也能够得出一个结论:时域信号的采样率乘上一个固定系数即是变换之后频谱的宽度,可以用如下所示的一张图清晰说明:

经过上述的分析,我们有了如下的结论:更高的频谱分辨率需要有更长的采样时间,更宽的频谱分布需要提高对于原始信号的采样率,那我们在实际的使用过程中,当然是希望频谱更宽,分辨率更加精确,那么示波器的长存储就是必要的。

(387条消息) STM32CubeMX配置ADC采样(轮询、中断、DMA)_Sense_long的博客-CSDN博客

https://blog.csdn.net/weixin_46461874/article/details/128686185?spm=1001.2101.3001.6650.4&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EYuanLiJiHua%7EPosition-4-128686185-blog-122049671.pc_relevant_3mothn_strategy_and_data_recovery&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EYuanLiJiHua%7EPosition-4-128686185-blog-122049671.pc_relevant_3mothn_strategy_and_data_recovery&utm_relevant_index=5

void DMA1_Channel1_IRQHandler(void)
{
    g_adc_dma_sta = 1;                      /* 标记DMA传输完成 */
    HAL_ADC_Stop_DMA(&hadc1);
    for (int i = 0; i < (ADC_DMA_BUF_SIZE - 1) ; i++)  /* 每个通道采集了10次数据,进行10次累加 */
    {
       temp = (float)g_adc_dma_buf[i] * (3.3 / 4096); 
       printf("%d  %x  %fV \r\n",i,g_adc_dma_buf[i],temp);
    }
  /* USER CODE END DMA1_Channel1_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_adc1);
  /* USER CODE BEGIN DMA1_Channel1_IRQn 1 */
    HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&g_adc_dma_buf, ADC_DMA_BUF_SIZE);
}
#define ADC_Ech_Channel            5  
#define ADC_DMA_BUF_SIZE        10 * ADC_Ech_Channel      /* ADC DMA采集 BUF大小, 应等于ADC通道数的整数倍 */
extern uint16_t g_adc_dma_buf[ADC_DMA_BUF_SIZE];

int main(void)
{
  MX_DMA_Init();
  MX_ADC1_Init();
  HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&g_adc_dma_buf, ADC_DMA_BUF_SIZE);
 /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    if (g_adc_dma_sta == 1)
    {
     temp = (float)g_adc_dma_buf[i] * (3.3 / 4096); 
     printf(" %x  %f V \r\n",g_adc_dma_buf[i],temp);
    }
  }
}        

stm32f103+FFT+OLED的音乐频谱制作(干货 只需三步即可) | 小蜜蜂

https://www.lmlphp.com/user/56/article/item/9127/

ZLG_GUI方便绘图 不用GUI也可以 看自己需求

猜你喜欢

转载自blog.csdn.net/m0_37777700/article/details/129703699