IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 基于stm32f103c8t6的fft频率计 -> 正文阅读

[嵌入式]基于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下测得,峰峰值更大些精度会更高些。

信号发生器输出实测
10khz9961hz
15khz15040hz
20khz20022hz
25khz25000hz
30khz29987hz
35khz34968hz

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、DMA
		ADC_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_tim
		TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 		//TIM向上计数模式
		TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);			//根据指定的参数初始化TIMx的时间基数单位
		
		TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;		//选择定时器模式:TIM脉冲宽度调制模式1
		TIM_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_CH2
		
		TIM_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

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-01-14 02:08:40  更:2022-01-14 02:09:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 12:30:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码