标题:
STM32+定时ADC+DMA+FFT源码
[打印本页]
作者:
zjjoker
时间:
2018-7-21 18:03
标题:
STM32+定时ADC+DMA+FFT源码
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "pwm.h"
#include "adc.h"
#include "dma.h"
#include "lcd.h"
#include "math.h"
#include "arm_math.h"
float CalMax_FREQ(float *Data, u16 DataSize);
#define SEND_BUFF_SIZE 4096
#define SAMPLE_FREQ 6000
#define INIT_FREQ 400
#define MAX_FREQ 3000
#define INC_FREQ 25
u16 ADCDMA_DATA[SEND_BUFF_SIZE];
float fft_inputbuf[SEND_BUFF_SIZE*2]; //FFT输入数组
float fft_outputbuf[SEND_BUFF_SIZE]; //FFT输出数组
float FundamentalFreq;
u16 ExsistingFreq;
int main(void)
{
u16 led0pwmval=1000000/SAMPLE_FREQ;
float temp;
u16 adcx;
u16 i = 0,j=0,k=0;
u16 ExsistingPwmCount;
u8 INC_FREQ_Flag = 0;
arm_cfft_radix4_instance_f32 scfft;
FundamentalFreq = 0;
ExsistingFreq = INIT_FREQ;
// u8 dir=1;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168); //初始化延时函数
uart_init(115200);//初始化串口波特率为115200
LED_Init();
LCD_Init();
Adc_Init();
MYDMA_Config(DMA2_Stream0,DMA_Channel_0,(u32)&ADC1->DR,(u32)ADCDMA_DATA,SEND_BUFF_SIZE);
TIM3_PWM_Init(led0pwmval-1,84-1); //84M/84=1Mhz的计数频率,重装载值500,所以PWM频率为 1M/500=2Khz.
TIM_SetCompare1(TIM3,led0pwmval/2); //修改比较值,修改占空比
// ExsistingFreq = 814;
// ExsistingFreq = INIT_FREQ;
// ExsistingPwmCount = 100000/ExsistingFreq;
// TIM14_PWM_Init(ExsistingPwmCount-1,840-1); //84M/840=100Khz的计数频率,重装载值25,所以PWM频率为 100K/ExsistingFreq=5KHz.
// TIM_SetCompare1(TIM14,ExsistingPwmCount/2); //修改比较值,修改占空比
arm_cfft_radix4_init_f32(&scfft,SEND_BUFF_SIZE,0,1);//初始化scfft结构体,设定FFT相关参数
POINT_COLOR=RED;
LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
LCD_ShowString(30,70,200,16,16,"ADC TEST");
LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,110,200,16,16,"2014/5/6");
POINT_COLOR=BLUE;//设置字体为蓝色
LCD_ShowString(30,130,200,16,16,"ADC1_CH5_VAL:");
LCD_ShowString(30,150,200,16,16,"ADC1_CH5_VOL:0.000V"); //先在固定位置显示小数点
// //初始化扫频
// for(i=0;i<(MAX_FREQ-INIT_FREQ)/INC_FREQ;i++)
// {
// ExsistingFreq = INIT_FREQ+i*INC_FREQ;
// ExsistingPwmCount = 100000/ExsistingFreq;
// TIM14_PWM_Init(ExsistingPwmCount-1,840-1);
// TIM_SetCompare1(TIM14,ExsistingPwmCount/2);
// TIM_Cmd(TIM14, ENABLE);
// delay_ms(10);
// TIM_Cmd(TIM14, DISABLE);
// }
// delay_ms(100);
// printf("The %d times:\r\n",j);
// //开始采样
// ADC_Cmd(ADC1,ENABLE);
// //等待采样完成
// while(DMA_GetFlagStatus(DMA2_Stream0,DMA_FLAG_TCIF0)==RESET);
// //DMA传输完成,清除标志位,等待下次DMA传输
// DMA_ClearFlag(DMA2_Stream0,DMA_FLAG_TCIF0);//清除DMA2_Steam7传输完成标志
// //禁止ADC转换,计算传感器频率
// ADC_Cmd(ADC1,DISABLE);
// LED0 = !LED0;
// for(k=0;k<SEND_BUFF_SIZE;k++)
// {
// fft_inputbuf[2*k] =(float)(ADCDMA_DATA[k]*(3.3/4096));
// fft_inputbuf[2*k+1] = 0;
// }
// //计算频率,傅里叶变换
// arm_cfft_radix4_f32(&scfft,fft_inputbuf); //FFT计算(基4)
// arm_cmplx_mag_f32(fft_inputbuf,fft_outputbuf,SEND_BUFF_SIZE); //把运算结果复数求模得幅值
// //计算基频
// FundamentalFreq = CalMax_FREQ(fft_outputbuf,SEND_BUFF_SIZE/2);
// //得到初始频率
// ExsistingFreq = FundamentalFreq;
// printf("FFT Result:\r\n");
// printf("The Calculate Fundamental Frequency: %f\r\n",FundamentalFreq);
//
// k=0;
while(1) //实现比较值从0-300递增,到300后从300-0递减,循环
{
adcx = ADCDMA_DATA[SEND_BUFF_SIZE-1];
LCD_ShowxNum(134,130,adcx,4,16,0); //显示ADCC采样后的原始值
temp=(float)adcx*(3.3/4096); //获取计算后的带小数的实际电压值,比如3.1111
adcx=temp; //赋值整数部分给adcx变量,因为adcx为u16整形
LCD_ShowxNum(134,150,adcx,1,16,0); //显示电压值的整数部分,3.1111的话,这里就是显示3
temp-=adcx; //把已经显示的整数部分去掉,留下小数部分,比如3.1111-3=0.1111
temp*=1000; //小数部分乘以1000,例如:0.1111就转换为111.1,相当于保留三位小数。
LCD_ShowxNum(150,150,temp,3,16,0X80); //显示小数部分(前面转换为了整形显示),这里显示的就是111.
// //激励
//// ExsistingFreq = 810;
// ExsistingPwmCount = 100000/ExsistingFreq;
// TIM14_PWM_Init(ExsistingPwmCount-1,840-1);
// TIM_SetCompare1(TIM14,ExsistingPwmCount/2);
// TIM_Cmd(TIM14, ENABLE); //使能TIM14
// //激励50ms
// delay_ms(50);
// //停止激励
//// TIM_Cmd(TIM14, DISABLE);
// //延时200ms采样,去除波形不稳定时波形对采样结果影响
// delay_ms(100);
// //开始采样
// ADC_Cmd(ADC1,ENABLE);
// //等待采样完成
// while(DMA_GetFlagStatus(DMA2_Stream0,DMA_FLAG_TCIF0)==RESET);
// //DMA传输完成,清除标志位,等待下次DMA传输
// DMA_ClearFlag(DMA2_Stream0,DMA_FLAG_TCIF0);//清除DMA2_Steam7传输完成标志
// //禁止ADC转换,计算传感器频率
// ADC_Cmd(ADC1,DISABLE);
// LED0 = !LED0;
// for(i=0;i<SEND_BUFF_SIZE;i++)
// {
// fft_inputbuf[2*i] =(float)(ADCDMA_DATA[i]*(3.3/4096));
// fft_inputbuf[2*i+1] = 0;
// }
// //计算频率,傅里叶变换
// arm_cfft_radix4_f32(&scfft,fft_inputbuf); //FFT计算(基4)
// arm_cmplx_mag_f32(fft_inputbuf,fft_outputbuf,SEND_BUFF_SIZE); //把运算结果复数求模得幅值
// //计算基频
// FundamentalFreq = CalMax_FREQ(fft_outputbuf,SEND_BUFF_SIZE/2);
// printf("FFT Result:\r\n");
// printf("The Calculate Fundamental Frequency: %f\r\n",FundamentalFreq);
//
// //判断是否起振
// if(FundamentalFreq>(ExsistingFreq-INC_FREQ/2)&&FundamentalFreq<(ExsistingFreq+INC_FREQ/2))
// {
// //起振成功,保留起振频率
// ExsistingFreq = (u16)FundamentalFreq;
// printf("FFT Result:\r\n");
// printf("The ExsistingFreq Frequency: %d\r\n",ExsistingFreq);
// }
// else
// {
if((FundamentalFreq>ExsistingFreq-INC_FREQ/2)&&(FundamentalFreq<ExsistingFreq+INC_FREQ/2))
{
printf("Frequency is correct: \r\n");
k=0;
}
else
{
k=1;
}
//起振失败,扫频
//初始化扫频
if(k==1)
{
printf("Initial Scan Frequency:\r\n");
for(i=0;i<(MAX_FREQ-INIT_FREQ)/INC_FREQ;i++)
{
ExsistingFreq = INIT_FREQ+i*INC_FREQ;
ExsistingPwmCount = 100000/ExsistingFreq;
TIM14_PWM_Init(ExsistingPwmCount-1,840-1);
TIM_SetCompare1(TIM14,ExsistingPwmCount/2);
TIM_Cmd(TIM14, ENABLE);
delay_ms(10);
TIM_Cmd(TIM14, DISABLE);
}
// delay_ms(100);
// printf("The %d times:\r\n",j);
// //开始采样
// ADC_Cmd(ADC1,ENABLE);
// //等待采样完成
// while(DMA_GetFlagStatus(DMA2_Stream0,DMA_FLAG_TCIF0)==RESET);
// //DMA传输完成,清除标志位,等待下次DMA传输
// DMA_ClearFlag(DMA2_Stream0,DMA_FLAG_TCIF0);//清除DMA2_Steam7传输完成标志
// //禁止ADC转换,计算传感器频率
// ADC_Cmd(ADC1,DISABLE);
// LED0 = !LED0;
// for(k=0;k<SEND_BUFF_SIZE;k++)
// {
// fft_inputbuf[2*k] =(float)(ADCDMA_DATA[k]*(3.3/4096));
// fft_inputbuf[2*k+1] = 0;
// }
// //计算频率,傅里叶变换
// arm_cfft_radix4_f32(&scfft,fft_inputbuf); //FFT计算(基4)
// arm_cmplx_mag_f32(fft_inputbuf,fft_outputbuf,SEND_BUFF_SIZE); //把运算结果复数求模得幅值
// //计算基频
// FundamentalFreq = CalMax_FREQ(fft_outputbuf,SEND_BUFF_SIZE/2);
// //得到初始频率
// ExsistingFreq = (u16)FundamentalFreq;
// printf("FFT Result:\r\n");
// printf("The ExsistingFreq Frequency: %d\r\n",ExsistingFreq);
}
else //正常激励
{
// ExsistingFreq = FundamentalFreq;
ExsistingPwmCount = 100000/ExsistingFreq;
TIM14_PWM_Init(ExsistingPwmCount-1,840-1);
TIM_SetCompare1(TIM14,ExsistingPwmCount/2);
TIM_Cmd(TIM14, ENABLE);
delay_ms(100);
TIM_Cmd(TIM14, DISABLE);
// delay_ms(100);
// printf("The %d times:\r\n",j);
// //开始采样
// ADC_Cmd(ADC1,ENABLE);
// //等待采样完成
// while(DMA_GetFlagStatus(DMA2_Stream0,DMA_FLAG_TCIF0)==RESET);
// //DMA传输完成,清除标志位,等待下次DMA传输
// DMA_ClearFlag(DMA2_Stream0,DMA_FLAG_TCIF0);//清除DMA2_Steam7传输完成标志
// //禁止ADC转换,计算传感器频率
// ADC_Cmd(ADC1,DISABLE);
// LED0 = !LED0;
// for(k=0;k<SEND_BUFF_SIZE;k++)
// {
// fft_inputbuf[2*k] =(float)(ADCDMA_DATA[k]*(3.3/4096));
// fft_inputbuf[2*k+1] = 0;
// }
// //计算频率,傅里叶变换
// arm_cfft_radix4_f32(&scfft,fft_inputbuf); //FFT计算(基4)
// arm_cmplx_mag_f32(fft_inputbuf,fft_outputbuf,SEND_BUFF_SIZE); //把运算结果复数求模得幅值
// //计算基频
// FundamentalFreq = CalMax_FREQ(fft_outputbuf,SEND_BUFF_SIZE/2);
// //得到初始频率
// ExsistingFreq = (u16)FundamentalFreq;
// printf("FFT Result:\r\n");
// printf("The ExsistingFreq Frequency: %d\r\n",ExsistingFreq);
}
// }
delay_ms(100);
printf("The %d times:\r\n",j);
//开始采样
ADC_Cmd(ADC1,ENABLE);
//等待采样完成
while(DMA_GetFlagStatus(DMA2_Stream0,DMA_FLAG_TCIF0)==RESET);
//DMA传输完成,清除标志位,等待下次DMA传输
DMA_ClearFlag(DMA2_Stream0,DMA_FLAG_TCIF0);//清除DMA2_Steam7传输完成标志
//禁止ADC转换,计算传感器频率
ADC_Cmd(ADC1,DISABLE);
LED0 = !LED0;
for(k=0;k<SEND_BUFF_SIZE;k++)
{
fft_inputbuf[2*k] =(float)(ADCDMA_DATA[k]*(3.3/4096));
fft_inputbuf[2*k+1] = 0;
}
//计算频率,傅里叶变换
arm_cfft_radix4_f32(&scfft,fft_inputbuf); //FFT计算(基4)
arm_cmplx_mag_f32(fft_inputbuf,fft_outputbuf,SEND_BUFF_SIZE); //把运算结果复数求模得幅值
//计算基频
FundamentalFreq = CalMax_FREQ(fft_outputbuf,SEND_BUFF_SIZE/2);
for(i=0;i<10;i++)
{
if(fft_inputbuf[2*i])
{
INC_FREQ_Flag = 0;
}
else
{
INC_FREQ_Flag = 1;
}
}
if(0 == INC_FREQ_Flag)
{
//更新激励频率
ExsistingFreq = (u16)FundamentalFreq;
}
// //得到初始频率
// ExsistingFreq = (u16)FundamentalFreq;
printf("FFT Result:\r\n");
printf("The ExsistingFreq Frequency: %d\r\n",ExsistingFreq);
//串口打印频率
printf("FFT Result:\r\n");
printf("The Fundamental Frequency: %f\r\n",FundamentalFreq);
delay_ms(1000);
//使能激励信号
// TIM_Cmd(TIM14, ENABLE); //使能TIM14
// delay_ms(50);
}
}
float CalMax_FREQ(float *Data, u16 DataSize)
{
u16 i;
u16 MaxIndex = 1;
float CalFreq = 0;
for(i=1;i<DataSize;i++)
{
// printf("%f\r\n",Data[i]);
if(Data[i]>Data[MaxIndex])
{
MaxIndex = i;
}
}
CalFreq = (float)MaxIndex* SAMPLE_FREQ/SEND_BUFF_SIZE;
return CalFreq;
}
复制代码
全部资料51hei下载地址:
定时ADC+DMA +FFT-0118.rar
(1.12 MB, 下载次数: 250)
2018-7-21 18:11 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
zhouwang4135463
时间:
2018-8-5 12:42
这个能把能不能采集到频率啊!!!!!
作者:
jiangkeqin_sy
时间:
2018-9-20 13:35
这个能把能不能采集到频率啊!!!!!
作者:
jiangkeqin_sy
时间:
2018-9-20 13:35
很想学习啊
作者:
乐独
时间:
2019-4-29 17:06
希望有用
作者:
6542011
时间:
2019-5-5 09:44
非常感谢楼主的分享,现在正在学习
作者:
zyb329321151
时间:
2019-5-14 09:29
这个是F4系列的板子呀。。我的是F1的。。
作者:
cnc2020
时间:
2019-5-16 23:07
很想学习啊
作者:
cnc2020
时间:
2019-5-18 21:57
good job
作者:
cnc2020
时间:
2019-5-18 21:58
很想学习
作者:
cnc2020
时间:
2019-5-21 22:23
希望有用
作者:
Joker灬
时间:
2019-7-3 11:08
感谢分享
作者:
lc9099
时间:
2019-7-17 16:59
感谢分享!!
作者:
ar_fa
时间:
2019-12-4 17:05
资料不错,做个记号
作者:
ar_fa
时间:
2019-12-13 08:19
资料不错,感谢楼主分享
作者:
LUJIATU
时间:
2019-12-23 14:26
很想学习啊
作者:
shu_007
时间:
2019-12-24 19:30
本人对傅里叶一窍不通,希望能有所 了解,学习了。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1