基于stm32f103c8t6的fft频率计
之前项目中需要用到正弦信号的频率测量,也参考了几个大佬的博客(链接如下),但可能是由于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频率计相关推荐
- 全相位算法c语言表达,基于DSP的全相位FFT频率计设计.pdf
基于DSP的全相位FFT频率计设计 学兔兔 l 匐 化 基于DSP的全相位FFT频率计设计 The all-phase FFT cymometer based on DSP 董翠英 DoNG Cui- ...
- 基于FPGA的FFT设计
基于FPGA的FFT设计 1.verilog源代码还有实验报告 2.FFT的主要算法 FFT算法并不是一种新的理论算法,它只是用来计算DFT的快速算法,所以它是以DFT为基础的.本课题采用的是基-2 ...
- 基于STM32F103C8T6的充电桩计费系统(程序+原理图+PCB+论文)
本设计: 基于STM32F103C8T6的充电桩计费系统(程序+原理图+PCB+论文) 原理图:Altium Designer 程序编译器:keil 5 编程语言:C语言 编号C0019 下载链接 [ ...
- 基于ppg和fft神经网络的光学血压估计【翻译】
基于ppg和fft神经网络的光学血压估计 摘要 我们引入并验证了仅使用指尖的光体积描记图(PPG)信号的逐拍光学血压(BP)估计范式.该方案确定了主体对PPG信号的特定贡献,并通过适当的归一化去除其大 ...
- 基于STM32F103C8T6与ESP8266的物联网智能温度采集与蓝牙OLED数字钟的设计与实现
基于STM32F103C8T6与ESP8266的物联网智能温度采集与蓝牙OLED数字钟的设计与实现 作者: 颜孙炜 文章目录 基于STM32F103C8T6与ESP8266的物联网智能温度采集与蓝牙O ...
- 基于STM32F103c8t6的智能垃圾桶项目
基于STM32F103c8t6的智能垃圾桶项目 写在前头 软件配置 硬件部分 1. 主控芯片 2. HC-SR04超声波模块 模块简介 模块参数 工作原理 GPIO配置 3. SG90舵机 模块简介 ...
- 基于STM32F103C8T6(HAL库)的HC-SR501红外人体传感及HC-SR04超声波测距
系列文章目录 一.基于STM32F103C8T6最小系统板和STM32CubeMX实现LED灯循环闪烁 二.基于STM32F103C8T6和STM32CubeMX实现UART串口通信数据收发 三.实战 ...
- 基于STM32F103C8T6的MPU6050调试与数字运动处理器DMP
基于STM32F103C8T6的MPU6050调试与数字运动处理器DMP StrongerHangover 笔者之前也接触过MPU6050模块,但是并没有真正的去了解内部的通讯方式与内部的寄存器操作, ...
- matlab fft谱分析实验报告,基于matlab的fft频谱分析及应用实验报告.docx
基于matlab的fft频谱分析及应用实验报告 实验三用FFT对信号进行频谱分析 一实验目的 1能够熟练掌握快速离散傅立叶变换的原理及应用FFT进行频谱分析的基本方法:2了解用FFT进行频谱分析可能出 ...
- 基于STM32F103C8T6的循迹避障小车完整制作过程(详细)----上篇(第123点)
基于STM32F103C8T6的循迹避障小车完整制作过程 本文适合小白观看 由于本人的一个小项目,要做一个基于STM32的循迹避障小车,前后花了约1周的时间,这个过程中也参考了很多大神分享的资料,学到 ...
最新文章
- Ubuntu 16.04 利用qemu模拟ARM开发板
- 分布式计算平台:Dryad
- 计算机视觉与深度学习 | 对恐怖袭击事件记录数据的量化分析(附源代码):博主的机器学习首秀(研究生数学建模二等奖)
- C++Binomia distribution二项分布的实现算法(附完整源码)
- 记录java在后台运行命令
- Unity3D获取Andorid设备返回键,主页键等功能
- 梯度下降法快速教程 | 第三章:学习率衰减因子(decay)的原理与Python实现
- 获取计算机主机mac地址的命令有,怎么获取计算机的MAC地址和IP地址?
- c语言编程 scant,C语言编程练习章.doc
- Flask模板操作一:基本使用
- Java 运行环境安装(JRE JDK 区别)
- 5960 差分约束系统
- A.Busiest Computing Nodes
- Revit平台盗版软件的陷阱与风险
- 是否能够成为真正的编程高手,主要是在于是否有毅力坚持学习和练习。今天从最简单的输出名言“贵有恒,何必三更起五更眠:最无益,只怕一日曝十日寒。”开始,主要是想让读者激励自己,坚持学习C语言。
- WCF 项目应用连载[2] - 创建Lig日志系统
- 拍照比“剪刀手”会泄露指纹信息,1.5米之内百分百还原。
- iPhone开发——UIViewContoller subclass
- Excel打开UTF-8编码CSV文件乱码的问题
- Smarty之section
热门文章
- Camunda 动态增加会签
- mysql无法创建partition_mysql的partition分区
- 强世功:中美“关键十年” ——“新罗马帝国”与“新的伟大斗争”
- 思博伦spirent testcenter 抓包,过滤特定报文
- 【原创】《矩阵的史诗级玩法》连载十七:用矩阵研究二次贝塞尔曲线和抛物线的关系(上)
- 走进tensorflow第六步——拟合一元二次函数
- 解决win10以太网没有有效的ip配置
- 4.2 存储器读写指令的发射与执行2
- 用尽量简单地话,一次讲明白傅里叶级数(FS)、傅里叶变换(FT)、离散时间傅里叶变换(DTFT)、离散傅里叶级数(DFS)、离散傅里叶变换(DFT)以及它们之间的联系和区别。
- android卡通头像,Face V(卡通头像制作)