#include "audio_adc.h" #include #include "stm32f1xx.h" // Один непрерывный DMA-буфер: 2 * 512 = 1024 семпла static audio_sample_t dma_buffer[2 * AUDIO_BUFFER_SIZE]; // Callback функция static audio_buffer_ready_callback_t user_callback = NULL; // Статистика (для отладки) static volatile uint32_t buffer_count = 0; static volatile uint32_t dma_half_transfer_count = 0; static volatile uint32_t dma_full_transfer_count = 0; // Private Function Prototypes static void audio_gpio_init(void); static void audio_timer_init(void); static void audio_adc_hw_init(void); static void audio_dma_init(void); bool audio_adc_init(audio_buffer_ready_callback_t callback) { if (callback == NULL) return false; user_callback = callback; audio_gpio_init(); audio_timer_init(); audio_adc_hw_init(); audio_dma_init(); return true; } void audio_adc_start(void) { DMA1_Channel1->CCR |= DMA_CCR_EN; ADC1->CR2 |= ADC_CR2_ADON; TIM3->CR1 |= TIM_CR1_CEN; } void audio_adc_stop(void) { TIM3->CR1 &= ~TIM_CR1_CEN; ADC1->CR2 &= ~ADC_CR2_ADON; DMA1_Channel1->CCR &= ~DMA_CCR_EN; } uint32_t audio_adc_get_buffer_count(void) { return buffer_count; } static void audio_gpio_init(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // PA1 analog GPIOA->CRL &= ~(0xF << 4); } static void audio_timer_init(void) { // Включаем тактирование Timer3 RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; // Настраиваем TIM3 для 22050 Hz TIM3->PSC = AUDIO_TIMER_PRESCALER; TIM3->ARR = AUDIO_TIMER_PERIOD; // TRGO = Update event TIM3->CR2 &= ~TIM_CR2_MMS; TIM3->CR2 |= TIM_CR2_MMS_1; TIM3->CR1 |= TIM_CR1_ARPE; TIM3->EGR |= TIM_EGR_UG; TIM3->CNT = 0; } static void audio_adc_hw_init(void) { RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; RCC->CFGR &= ~RCC_CFGR_ADCPRE; RCC->CFGR |= RCC_CFGR_ADCPRE_DIV6; ADC1->CR2 = 0; ADC1->CR1 = 0; ADC1->CR1 &= ~ADC_CR1_SCAN; ADC1->CR2 &= ~ADC_CR2_CONT; // EXTSEL = 011 (Timer2 TRGO), EXTTRIG enable ADC1->CR2 &= ~ADC_CR2_EXTSEL; ADC1->CR2 |= (0x4U << 17); // TIM3_TRGO ADC1->CR2 |= ADC_CR2_EXTTRIG; ADC1->CR2 |= ADC_CR2_DMA; ADC1->CR2 &= ~ADC_CR2_ALIGN; ADC1->SQR1 &= ~ADC_SQR1_L; ADC1->SQR3 &= ~ADC_SQR3_SQ1; ADC1->SQR3 |= (AUDIO_ADC_CHANNEL << ADC_SQR3_SQ1_Pos); ADC1->SMPR2 &= ~ADC_SMPR2_SMP1; ADC1->SMPR2 |= ADC_SMPR2_SMP1_0; // 7.5 cycles // calibration ADC1->CR2 |= ADC_CR2_ADON; for (volatile int i = 0; i < 1000; i++) {} ADC1->CR2 |= ADC_CR2_CAL; while (ADC1->CR2 & ADC_CR2_CAL) {} ADC1->CR2 &= ~ADC_CR2_ADON; } static void audio_dma_init(void) { RCC->AHBENR |= RCC_AHBENR_DMA1EN; DMA1_Channel1->CCR &= ~DMA_CCR_EN; while (DMA1_Channel1->CCR & DMA_CCR_EN) {} // ADC1 DR -> RAM DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; // ВАЖНО: CMAR указывает на непрерывный буфер 1024 samples DMA1_Channel1->CMAR = (uint32_t)dma_buffer; // ВАЖНО: 2 * 512 = 1024 samples DMA1_Channel1->CNDTR = 2 * AUDIO_BUFFER_SIZE; uint32_t ccr = 0; ccr |= DMA_CCR_MINC; ccr |= DMA_CCR_CIRC; ccr |= DMA_CCR_HTIE; ccr |= DMA_CCR_TCIE; ccr |= DMA_CCR_PL_1; // high ccr |= DMA_CCR_MSIZE_0; // 16-bit ccr |= DMA_CCR_PSIZE_0; // 16-bit DMA1_Channel1->CCR = ccr; NVIC_SetPriority(DMA1_Channel1_IRQn, 6); NVIC_EnableIRQ(DMA1_Channel1_IRQn); } void DMA1_Channel1_IRQHandler(void) { uint32_t isr = DMA1->ISR; if (isr & DMA_ISR_HTIF1) { DMA1->IFCR = DMA_IFCR_CHTIF1; dma_half_transfer_count++; // первая половина: [0 .. 511] if (user_callback) { user_callback(&dma_buffer[0], AUDIO_BUFFER_SIZE); } buffer_count++; } if (isr & DMA_ISR_TCIF1) { DMA1->IFCR = DMA_IFCR_CTCIF1; dma_full_transfer_count++; // вторая половина: [512 .. 1023] if (user_callback) { user_callback(&dma_buffer[AUDIO_BUFFER_SIZE], AUDIO_BUFFER_SIZE); } buffer_count++; } if (isr & DMA_ISR_TEIF1) { DMA1->IFCR = DMA_IFCR_CTEIF1; // TODO: error handling } }