|
STM32F103C8_DMA方式2路ADC采集雙聲道音頻FFT變換顯示頻譜
這是一個(gè)完整的項(xiàng)目,沒(méi)有加狗
關(guān)鍵點(diǎn)在于多路采集,F(xiàn)FT庫(kù)函數(shù)應(yīng)用,這個(gè)FFT函數(shù)用匯編優(yōu)化,速度比較快。
當(dāng)然,本系統(tǒng)速度瓶頸在畫(huà)點(diǎn)顯示。后期我采用直接寫顯存,就比較快了。
上段忙,這也是我對(duì)同道的一點(diǎn)小小的貢獻(xiàn)
單片機(jī)源程序如下:
- #include "stm32f10x.h"
- #include "usart.h"
- #include "adc.h"
- #include "delay.h"
- #include "Lcd_Driver.h"
- #include "LCD_Config.h"
- #include "stm32_dsp.h"
- #include "math.h"
- #define NPT 256 //FFT采樣點(diǎn)數(shù)
- long lBUFMAG[NPT+NPT]; //存儲(chǔ)求模后的數(shù)據(jù)[NPT+NPT/2]
- long lBUFOUT[NPT]; //FFT輸出序列NPT=256
- long lBUFIN0[NPT]; //FFT輸入系列
- long lBUFIN1[NPT]; //FFT輸入系列
- void dsp_column0(void);
- void dsp_column1(void);
- void powerMag(long nfill);//計(jì)算頻點(diǎn)幅值
- void dsp_column_1(void);
- void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u16 dot);
- extern __IO uint16_t ADC_ConvertedValue[NOFCHANEL];
- // 局部變量,用于保存轉(zhuǎn)換計(jì)算后的電壓值
- float ADC_ConvertedValueLocal[NOFCHANEL];
-
- int main(void)
- {
- u16 i;
- uart_init(115200);
- ADCx_Init();
- delay_init();
- Lcd_Init();//初始化硬件SPI
- Lcd_Clear(BLUE); //清屏函數(shù)
- while(1)
- {
- ADC_SoftwareStartConvCmd(ADC_x, ENABLE);
- while(!DMA_GetFlagStatus(DMA1_FLAG_TC1));
- DMA_ClearFlag(DMA1_FLAG_TC1);
- ADC_SoftwareStartConvCmd(ADC1, DISABLE);
- ADC_ConvertedValueLocal[0] =(float) ADC_ConvertedValue[0]/4096*3.3;
- ADC_ConvertedValueLocal[1] =(float) ADC_ConvertedValue[1]/4096*3.3;
- printf("CH0 = %f V \r\n",ADC_ConvertedValueLocal[0]);
- printf("CH1 = %f V \r\n",ADC_ConvertedValueLocal[1]);
- for(i=0;i<NPT;i++)
- {// 由于沒(méi)有采用外部觸發(fā),所以使用軟件觸發(fā)ADC轉(zhuǎn)換
- ADC_SoftwareStartConvCmd(ADC_x, ENABLE);
- while(!DMA_GetFlagStatus(DMA1_FLAG_TC1));
- DMA_ClearFlag(DMA1_FLAG_TC1);
- ADC_SoftwareStartConvCmd(ADC1, DISABLE);
- lBUFIN0[i] =(float) ADC_ConvertedValue[0];
- lBUFIN1[i] =(float) ADC_ConvertedValue[1];
- }
- cr4_fft_256_stm32(lBUFOUT,lBUFIN1,NPT);//調(diào)用STM32的DSP庫(kù)作FFT變換
- powerMag(NPT);//計(jì)算頻點(diǎn)幅值
- dsp_column1();//顯示x根柱條。
-
- cr4_fft_256_stm32(lBUFOUT,lBUFIN0,NPT);//調(diào)用STM32的DSP庫(kù)作FFT變換
- //(FFT輸出序列,輸入序列,NPT=256)
- powerMag(NPT);//計(jì)算頻點(diǎn)幅值
- dsp_column0();//顯示x根柱條。
- }
- }
- //顯示各頻點(diǎn)的柱條
- void dsp_column0(void)
- {
- u8 i,j=80;
- for(i=1;i<161;i+=2)
- { OLED_Fill(i,0,i,128,0x0000); //填充區(qū)域的對(duì)角坐標(biāo)
- OLED_Fill(i,0,i,lBUFMAG[j],RED); //填充區(qū)域的對(duì)角坐標(biāo)
- j --;
- }
- }
- //顯示各頻點(diǎn)的柱條
- void dsp_column1(void)
- {
- u8 i,j=80;
- for(i=0;i<160;i+=2)
- { OLED_Fill(i,0,i,128,0x0000); //填充區(qū)域的對(duì)角坐標(biāo)
- OLED_Fill(i,0,i,lBUFMAG[j],GREEN); //填充區(qū)域的對(duì)角坐標(biāo)
- j --;
- }
- }
- //x1,y1,x2,y2 填充區(qū)域的對(duì)角坐標(biāo)
- //確保x1<=x2;y1<=y2 0<=x1<=127 0<=y1<=63
- //dot:0,清空;1,填充
- void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u16 dot) //可以快
- {
- u8 x,y;
- for(x=x1;x<=x2;x++)
- {
- for(y=y1;y<=y2;y++) Gui_DrawPoint(x,y,dot);//畫(huà)一個(gè)點(diǎn)
- }
- }
- ////////////////////////////////////////////
- //計(jì)算各頻點(diǎn)的模值
- void powerMag(long nfill) //計(jì)算頻點(diǎn)幅值
- { int32_t lX,lY;
- uint32_t i,j;
- for (i=0; i < nfill; i++) //256
- {
- lX= (lBUFOUT[i]<<16)>>16; /* sine_cosine --> cos */
- lY= (lBUFOUT[i] >> 16); /* sine_cosine --> sin */
- {
- float X= 64*((float)lX)/32768;
- float Y = 64*((float)lY)/32768;
- float Mag = sqrt(X*X+ Y*Y)/nfill; // 先平方和,再開(kāi)方sqrt
- j= (long)(Mag*65536); //存儲(chǔ)求模后的數(shù)據(jù)
- if(j>128) j=128;//避免顯示越界
- lBUFMAG[i] =j;
- }
- }
- }
復(fù)制代碼
所有程序51hei提供下載:
DMA2通道ADC_FFT.7z
(216.08 KB, 下載次數(shù): 169)
2021-1-21 16:46 上傳
點(diǎn)擊文件名下載附件
|
評(píng)分
-
查看全部評(píng)分
|