之前项目中需要用到正弦信号的频率测量,也参考了几个大佬的博客(链接如下),但可能是由于stm32的型号不匹配,虽然也在网上查了一些需要修改的地方,但结果一直不太对,后来经过自己摸索结果终于对了,在这里给大家分享下,具体原理不在赘述。
参考的部分大佬博客(stm32f103zet6):
链接1: https://blog.csdn.net/weixin_43368814/article/details/103552114.
链接2: https://blog.csdn.net/weixin_42616791/article/details/108419412.

优缺点

1、fft方式测频率,峰峰值可以最低为20mV,输入捕获方式,峰峰值需要达到七、八百mV以上,才可以精准测量;
2、程序的测量精度利用信号发生器进行了验证(下面表格的数据基本是在峰峰值20mV下测得,峰峰值更大些精度会更高些。

信号发生器输出 实测
10khz 9961hz
15khz 15040hz
20khz 20022hz
25khz 25000hz
30khz 29987hz
35khz 34968hz

3、在峰峰值的峰谷(顶点)小于1.6v时,该方式可以测量的最小峰峰值为20mv(信号发生器的最小峰峰值为20mV),一旦峰底值(最小值)超过1.6V(峰峰值仍为20mV),测量结果就不准了,误差很大(我暂时没找到原因,有知道原因的大佬,欢迎评论区解答);

代码

头文件

#include <stdio.h>
#include "string.h"
#include "fft_calculate.h"
#include "adc.h"#define ADC1_DR_Address    ((uint32_t)0x4001244C)
uint16_t ADC_Value[NPT];

adc(PA6,定时器2外部触发)

void Adc_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;ADC_InitTypeDef ADC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_Init(GPIOA, &GPIO_InitStructure);  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;       ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure);RCC_ADCCLKConfig(RCC_PCLK2_Div6);ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_1Cycles5);//使能ADC、DMAADC_DMACmd(ADC1,ENABLE);ADC_Cmd(ADC1,ENABLE);ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1));ADC_StartCalibration(ADC1);              while(ADC_GetCalibrationStatus(ADC1));  ADC_ExternalTrigConvCmd(ADC1, ENABLE);
}

DMA(一次接收1024点数据)

void DMA1_Init(void)
{DMA_InitTypeDef DMA_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);                DMA_DeInit(DMA1_Channel1);DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;          DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_Value;   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                 DMA_InitStructure.DMA_BufferSize = NPT;            DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;       DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;            DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord ; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord ;  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular  ;         DMA_InitStructure.DMA_Priority = DMA_Priority_High ;       DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;           DMA_Init(DMA1_Channel1, &DMA_InitStructure);  DMA_ClearITPendingBit(DMA1_IT_TC1);DMA_ITConfig(DMA1_Channel1,DMA_IT_TC, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);DMA_Cmd(DMA1_Channel1,ENABLE);
}

定时器

void TIM2_Init(void)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);       //时钟使能TIM_TimeBaseStructure.TIM_Period = arr;      //设置在下一个更新事件装入活动的自动重装载寄存器周期的值TIM_TimeBaseStructure.TIM_Prescaler =psc;             //设置用来作为TIMx时钟频率除数的预分频值TIM_TimeBaseStructure.TIM_ClockDivision = 0;        //设置时钟分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;        //TIM向上计数模式TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);          //根据指定的参数初始化TIMx的时间基数单位TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;       //选择定时器模式:TIM脉冲宽度调制模式1TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;        //比较输出使能TIM_OCInitStructure.TIM_Pulse = 9;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;        //输出极性:TIM输出比较极性低TIM_OC2Init(TIM2, & TIM_OCInitStructure);      //初始化外设TIM2_CH2TIM_Cmd(TIM2, ENABLE);           //使能TIMx
}

中断处理函数(不需要在.h文件中定义,main中直接调用)

void  DMA1_Channel1_IRQHandler(void)
{u16 i = 0;if(DMA_GetITStatus(DMA1_IT_TC1)!=RESET){for(i=0;i<NPT;i++){InBufArray[i] = ((signed short)(ADC_Value[i])) << 16;  }DMA_ClearITPendingBit(DMA1_IT_TC1);}
}

#最后附上程序下载地址
链接: 链接:https://pan.baidu.com/s/1CuYofbGRXZIoccYkexHHzw
.提取码:fp1q

基于stm32f103c8t6的fft频率计相关推荐

  1. 全相位算法c语言表达,基于DSP的全相位FFT频率计设计.pdf

    基于DSP的全相位FFT频率计设计 学兔兔 l 匐 化 基于DSP的全相位FFT频率计设计 The all-phase FFT cymometer based on DSP 董翠英 DoNG Cui- ...

  2. 基于FPGA的FFT设计

    基于FPGA的FFT设计 1.verilog源代码还有实验报告 2.FFT的主要算法 FFT算法并不是一种新的理论算法,它只是用来计算DFT的快速算法,所以它是以DFT为基础的.本课题采用的是基-2 ...

  3. 基于STM32F103C8T6的充电桩计费系统(程序+原理图+PCB+论文)

    本设计: 基于STM32F103C8T6的充电桩计费系统(程序+原理图+PCB+论文) 原理图:Altium Designer 程序编译器:keil 5 编程语言:C语言 编号C0019 下载链接 [ ...

  4. 基于ppg和fft神经网络的光学血压估计【翻译】

    基于ppg和fft神经网络的光学血压估计 摘要 我们引入并验证了仅使用指尖的光体积描记图(PPG)信号的逐拍光学血压(BP)估计范式.该方案确定了主体对PPG信号的特定贡献,并通过适当的归一化去除其大 ...

  5. 基于STM32F103C8T6与ESP8266的物联网智能温度采集与蓝牙OLED数字钟的设计与实现

    基于STM32F103C8T6与ESP8266的物联网智能温度采集与蓝牙OLED数字钟的设计与实现 作者: 颜孙炜 文章目录 基于STM32F103C8T6与ESP8266的物联网智能温度采集与蓝牙O ...

  6. 基于STM32F103c8t6的智能垃圾桶项目

    基于STM32F103c8t6的智能垃圾桶项目 写在前头 软件配置 硬件部分 1. 主控芯片 2. HC-SR04超声波模块 模块简介 模块参数 工作原理 GPIO配置 3. SG90舵机 模块简介 ...

  7. 基于STM32F103C8T6(HAL库)的HC-SR501红外人体传感及HC-SR04超声波测距

    系列文章目录 一.基于STM32F103C8T6最小系统板和STM32CubeMX实现LED灯循环闪烁 二.基于STM32F103C8T6和STM32CubeMX实现UART串口通信数据收发 三.实战 ...

  8. 基于STM32F103C8T6的MPU6050调试与数字运动处理器DMP

    基于STM32F103C8T6的MPU6050调试与数字运动处理器DMP StrongerHangover 笔者之前也接触过MPU6050模块,但是并没有真正的去了解内部的通讯方式与内部的寄存器操作, ...

  9. matlab fft谱分析实验报告,基于matlab的fft频谱分析及应用实验报告.docx

    基于matlab的fft频谱分析及应用实验报告 实验三用FFT对信号进行频谱分析 一实验目的 1能够熟练掌握快速离散傅立叶变换的原理及应用FFT进行频谱分析的基本方法:2了解用FFT进行频谱分析可能出 ...

  10. 基于STM32F103C8T6的循迹避障小车完整制作过程(详细)----上篇(第123点)

    基于STM32F103C8T6的循迹避障小车完整制作过程 本文适合小白观看 由于本人的一个小项目,要做一个基于STM32的循迹避障小车,前后花了约1周的时间,这个过程中也参考了很多大神分享的资料,学到 ...

最新文章

  1. Ubuntu 16.04 利用qemu模拟ARM开发板
  2. 分布式计算平台:Dryad
  3. 计算机视觉与深度学习 | 对恐怖袭击事件记录数据的量化分析(附源代码):博主的机器学习首秀(研究生数学建模二等奖)
  4. C++Binomia distribution二项分布的实现算法(附完整源码)
  5. 记录java在后台运行命令
  6. Unity3D获取Andorid设备返回键,主页键等功能
  7. 梯度下降法快速教程 | 第三章:学习率衰减因子(decay)的原理与Python实现
  8. 获取计算机主机mac地址的命令有,怎么获取计算机的MAC地址和IP地址?
  9. c语言编程 scant,C语言编程练习章.doc
  10. Flask模板操作一:基本使用
  11. Java 运行环境安装(JRE JDK 区别)
  12. 5960 差分约束系统
  13. A.Busiest Computing Nodes
  14. Revit平台盗版软件的陷阱与风险
  15. 是否能够成为真正的编程高手,主要是在于是否有毅力坚持学习和练习。今天从最简单的输出名言“贵有恒,何必三更起五更眠:最无益,只怕一日曝十日寒。”开始,主要是想让读者激励自己,坚持学习C语言。
  16. WCF 项目应用连载[2] - 创建Lig日志系统
  17. 拍照比“剪刀手”会泄露指纹信息,1.5米之内百分百还原。
  18. iPhone开发——UIViewContoller subclass
  19. Excel打开UTF-8编码CSV文件乱码的问题
  20. Smarty之section

热门文章

  1. Camunda 动态增加会签
  2. mysql无法创建partition_mysql的partition分区
  3. 强世功:中美“关键十年” ——“新罗马帝国”与“新的伟大斗争”
  4. 思博伦spirent testcenter 抓包,过滤特定报文
  5. 【原创】《矩阵的史诗级玩法》连载十七:用矩阵研究二次贝塞尔曲线和抛物线的关系(上)
  6. 走进tensorflow第六步——拟合一元二次函数
  7. 解决win10以太网没有有效的ip配置
  8. 4.2 存储器读写指令的发射与执行2
  9. 用尽量简单地话,一次讲明白傅里叶级数(FS)、傅里叶变换(FT)、离散时间傅里叶变换(DTFT)、离散傅里叶级数(DFS)、离散傅里叶变换(DFT)以及它们之间的联系和区别。
  10. android卡通头像,Face V(卡通头像制作)