pav256 (06.12.2013 16:36, просмотров: 26275)
Не работает ADC->DMA в STM32F4 Необходимо по 4-м каналам АЦП через DMA передавать массив данных в память. Другими словами последовательно по каждому каналу осуществляется измерение, затем процесс повторяется и так необходимое количество раз, определяемое объемом передаваемых через DMA выборок. Как только DMA передаст необходимый массив данных (SAMPL_ADC*CHANNEL_ADC), перестанут выполняться запросы ADC (при этом ADC_SR_OVR=1).
Реализация: запускаю таймер на 1мс (заведомо больше чем время обработки ADC), обрабатываю массив полученных данных и перезапускаю ADC и DMA. Все вроде просто, однако не работает как надо. После инициализации корректные данные в памяти, т.е. ADC и DMA работают. А вот после этого получаю только 2-3-4... выборок, остальные "0". При этом NDTR=0, т.е. DMA передал все данные. Пробовал подключать прерывание DMA, там останавливать ADC и DMA, а по таймеру обрабатывать и перезапускать ADC и DMA - результат аналогичный. Что то я недопонимаю в связке ADC<->DMA, RM0090 перечитывал несколько раз. Кто сталкивался или хотя бы может кинуть идею куда рыть, прошу ответить.
//настройка ADC1_IN10(PC.0), ADC1_IN11(PC.1), ADC1_IN12(PC.2), ADC1_IN13(PC.3)
void instal_adc_dma(void)
{
// включаем тактирование ADC1, DMA2 and GPIO
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN | RCC_AHB1ENR_GPIOCEN;
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
// вход - аналоговый
GPIOC->MODER &= ~(uint32_t)(3 << 0*2 | 3 << 1*2 | 3 << 2*2 | 3 << 3*2);
// конфигурируем 4-й поток DMA (0 канал)
DMA2_Stream4->CR |= DMA_SxCR_MSIZE_0; // данные в памяти 2 байта
DMA2_Stream4->CR |= DMA_SxCR_PSIZE_0; // данные в перефирии 2 байта
DMA2_Stream4->CR |= DMA_SxCR_MINC; // инкремент указателя в памяти - ВКЛ
// DMA2_Stream4->CR |= DMA_SxCR_TCIE; // прерывание по окончании передачи - ВКЛ
DMA2_Stream4->M0AR = (uint32_t)&DataADC; // базовый адрес памяти
DMA2_Stream4->PAR = (uint32_t)&(ADC1->DR); // базовый адрес переферии
// DMA2->HIFCR |= DMA_HIFCR_CTCIF4 | DMA_HIFCR_CHTIF4 | DMA_HIFCR_CTEIF4 | DMA_HIFCR_CDMEIF4 | DMA_HIFCR_CFEIF4;
DMA2_Stream4->NDTR = SAMPL_ADC * CHANNEL_ADC; // объем передаваемого блока
// ADC1 (каналы 10-13)
ADC1->SMPR1 |= ADC_SMPR1_SMP10_1 | ADC_SMPR1_SMP11_1 | ADC_SMPR1_SMP12_1 | ADC_SMPR1_SMP13_1;
ADC1->SQR1 |= 4 << 20;
ADC1->SQR3 |= 10<<0*5 | 11<<1*5 | 12<<2*5 | 13<<3*5;
ADC1->CR1 |= ADC_CR1_SCAN;
ADC1->CR2 |= ADC_CR2_ADON | ADC_CR2_CONT | ADC_CR2_DMA | ADC_CR2_DDS;
//старт
DMA2_Stream4->CR |= DMA_SxCR_EN; // активация 4-го потока DMA2
ADC1->CR2 |= ADC_CR2_SWSTART; // запускаем преобразование
return;
}
// таймер (1ms)
void TIM7_IRQHandler(void)
{
TIM7->SR &= ~TIM_SR_UIF; // сбрасываем прерывание
DMA2_Stream4->CR &= ~DMA_SxCR_EN; // деактивация 4-го потока DMA2
ADC1->SR &= ~ADC_SR_STRT; // останавливаем ADC
//обработка выборок...
// DMA2->HIFCR |= DMA_HIFCR_CTCIF4 | DMA_HIFCR_CHTIF4 | DMA_HIFCR_CTEIF4 | DMA_HIFCR_CDMEIF4 | DMA_HIFCR_CFEIF4;
ADC1->SR &= ~ADC_SR_OVR; // сбрасываем флаг переполнения
DMA2_Stream4->NDTR = SAMPL_ADC * CHANNEL_ADC; // объем передаваемого блока
DMA2_Stream4->CR |= DMA_SxCR_EN; // активация 4-го потока DMA2 (как и было 0-ой канал)
ADC1->CR2 |= ADC_CR2_SWSTART; // запускаем преобразование
}