使用stm32做一个实时扩音器,采样频率为16000,需要一个移频防啸叫的程序
时间: 2023-05-31 18:01:57 浏览: 104
以下是一个简单的实时扩音器程序,使用STM32的ADC模块进行音频采样,并将采样数据通过DAC模块输出。同时,为了防止啸叫,添加了一个移频滤波器。
#include "stm32f4xx.h"
#define SAMPLE_RATE 16000
#define BUFFER_SIZE 1024
uint16_t adc_data[BUFFER_SIZE];
int16_t output_buffer[BUFFER_SIZE];
int16_t last_output = 0;
int16_t last_input = 0;
void init_adc(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE);
}
void init_dac(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
DAC_InitTypeDef DAC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
DAC_Init(DAC_Channel_1, &DAC_InitStructure);
DAC_Init(DAC_Channel_2, &DAC_InitStructure);
DAC_Cmd(DAC_Channel_1, ENABLE);
DAC_Cmd(DAC_Channel_2, ENABLE);
}
void init_timer(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 1000000 / SAMPLE_RATE - 1;
TIM_TimeBaseStructure.TIM_Prescaler = 1;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
TIM_Cmd(TIM2, ENABLE);
}
void init_filter(void)
{
static const float b[] = {0.0039, 0.0117, 0.0234, 0.0391, 0.0586, 0.0781, 0.0977, 0.1172, 0.1328, 0.1445, 0.1484, 0.1445, 0.1328, 0.1172, 0.0977, 0.0781, 0.0586, 0.0391, 0.0234, 0.0117, 0.0039};
static const float a[] = {1.0000, -0.6008, 1.7231, -2.8560, 3.6892, -4.2389, 4.4198, -4.2389, 3.6892, -2.8560, 1.7231, -0.6008, 1.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000};
arm_biquad_casd_df1_inst_f32 filter;
arm_biquad_cascade_df1_init_f32(&filter, 2, b, a);
for (int i = 0; i < BUFFER_SIZE; i++) {
output_buffer[i] = 0;
}
while (1) {
while (!TIM_GetFlagStatus(TIM2, TIM_FLAG_Update)) {}
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
int16_t input = adc_data[0] - 2048;
int16_t output = input - last_input + 0.99f * last_output;
float f_input = input;
float f_output;
arm_biquad_cascade_df1_f32(&filter, &f_input, &f_output, 1);
output_buffer[0] = (int16_t)f_output;
last_input = input;
last_output = output;
for (int i = 0; i < BUFFER_SIZE; i++) {
DAC_SetChannel1Data(DAC_Align_12b_R, output_buffer[i] + 2048);
DAC_SetChannel2Data(DAC_Align_12b_R, output_buffer[i] + 2048);
while (!DAC_GetFlagStatus(DAC_Channel_1, DAC_FLAG_DMAUDR)) {}
DAC_ClearFlag(DAC_Channel_1, DAC_FLAG_DMAUDR);
while (!DAC_GetFlagStatus(DAC_Channel_2, DAC_FLAG_DMAUDR)) {}
DAC_ClearFlag(DAC_Channel_2, DAC_FLAG_DMAUDR);
}
}
}
int main(void)
{
init_adc();
init_dac();
init_timer();
init_filter();
while (1) {}
return 0;
}
阅读全文