Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32F407 ADC + DMA
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
smk
Прошу помочь с такой ситуацией. Есть 4 массива по 1000 элеменов. Нужно чтобы по приходу внешнего сигнала 1000 отсчетов АЦП ДМА уложил в первый массив. По следующему приходу синхросигнала уложил во второй и т.д. Потом при приходе другого синхросигнала круг повторился. Сейчас проблема в том. что даже не получается уложить 1000 отсчетов в массив и остановиться. Нужно как-то чтобы АЦП аппаратно пинал ДМА по завершении преобразования, а ДМА проделав 1000 переносов значений остановился. Собственно подскажите где я накололся. Спасибо.
Код
    RCC->APB2ENR |=(1<<8);                                                        //
    ADC1->CR2 |= (1<<0);                                                            //ADON: A/D Converter ON    
    ADC->CCR |= (1<<16)|(1<<17);             
    ADC1->CR2 |= (1<<8);                                                             //DMA: Direct memory access mode (for single ADC mode)
//    ADC1->CR2 |= (1<<9);                                                             //DMA disable selection (for single ADC mode)
    ADC1->CR2 |= (1<<1);                                                            //CONT: Continuous conversion
    ADC1->SMPR2 |= (7<<12);         //IN4 = 111: 480 cycles
    ADC1->SQR1 &= ~((1<<20)|(1<<21)|(1<<22)|(1<<23));            //11: 1 conversions
    ADC1->SQR3 = 4;                                                                        //
    
    RCC->AHB1ENR |=(1<<22);                                                      //DMA1EN: DMA2 clock enable
    DMA2_Stream0->CR &= ~((1<<27)|(1<<26)|(1<<25));      //000: channel 0 selected
    DMA2_Stream0->CR |= (1<<13);                                        //MSIZE[1:0]: Memory data size 01: half-word (16-bit)
    DMA2_Stream0->CR |= (1<<11);                                          //PSIZE[1:0]: Peripheral data size 01: Half-word (16-bit)
    DMA2_Stream0->CR |= (1<<10);                                          //MINC: Memory increment mode
    DMA2_Stream0->CR |= (1<<8);                                              //CIRC: Circular mode
//    DMA2_Stream0->CR |= DMA_SxCR_PFCTRL;
    DMA2_Stream0->CR &= ~((1<<7)|(1<<6));                       //DIR[1:0]: Data transfer direction 00: Peripheral-to-memory
    DMA2_Stream0->NDTR = 1000;                                              //NDT[15:0]: Number of data items to transfer
    DMA2_Stream0->PAR = (uint32_t)&ADC1->DR;                  //PAR[31:0]: Peripheral address
    DMA2_Stream0->M0AR = (uint32_t)&Kupol_1[0];              //M0A[31:0]: Memory 0 address
    DMA2_Stream0->CR |= (1<<0);                                              //EN: Stream enable / flag stream ready when read low
    ADC1->CR2 |= (1<<30);

Tanya
Цитата(smk @ Jul 29 2015, 14:52) *
Прошу помочь с такой ситуацией. Есть 4 массива по 1000 элеменов. Нужно чтобы по приходу внешнего сигнала 1000 отсчетов АЦП ДМА уложил в первый массив. По следующему приходу синхросигнала уложил во второй и т.д. Потом при приходе другого синхросигнала круг повторился.

Пользуюсь КУБом и не вникаю в детали. Все получается.
Примерно так. Записываем в конец массива 0xFFFF, запускаем АЦП_ДМА, АЦП стартует по фронту на ножке. Так как синхросигнал неизвестно когда придет, проверяем последний элемент массива. Можно иначе - через прерывания, например. Потом стартуем снова с другим массивом.
smk
По приходу синхросигнала вызывается прерывание. В прерывании подставляю ДМА новый адрес перврго элемента массива. Сбрасываю флаг и запускаю ДМА. При том, что представляет собой код значения АЦП укладываются м массив постоянно. Пока только в один. Проблема в том, что ДМА не останавливается, а укладывает по новому кругу. Мне нужно чтобы 1000 отсчетов уложились и стоп до следующего прихода синхры. Как это реализовать?
Код
void EXTI1_IRQHandler (void)    //Ïðèâÿçêà òûë                    
{
    EXTI->PR |= (1<<1);
    DMA2_Stream0->NDTR = 1000; //NDT[15:0]: Number of data items to transfer
    DMA2->LIFCR |= (1UL<<5);
    DMA2_Stream0->CR |= (1UL<<0);//EN: Stream enable / flag stream ready when read low
}
}
Tanya
Цитата(smk @ Jul 29 2015, 15:17) *
По приходу синхросигнала вызывается прерывание.
значения АЦП укладываются м массив постоянно. Пока только в один. Проблема в том, что ДМА не останавливается, а укладывает по новому кругу. Мне нужно чтобы 1000 отсчетов уложились и стоп до следующего прихода синхры. Как это реализовать?


Зачем прерывание с его задержкой?
У Вас круговой режим ДМА включен? Нужен однократный.
Сергей Борщ
А зачем вы выставили бит CIRC? Вот он вам и гонит следующие 1000 отсчетов без остановки.
Настройте ПДП со сброшенным битом CICR на первый массив. В прерывании ПДП об окончании пересылки настройте ПДП на второй массив и т.д.

А запускать можно либо ПДП (одно действие с битом EN, все остальное уже подготовлено) в прерывании от EXTI (как сейчас у вас сделано), либо можно ПДП запустить заранее, а этим внешним сигналом запускать таймер, который тактирует выборки вашего АЦП (если этот сигнал заведен на подходящий вход таймера).

И еще - завязывайте с магическим числами. В том же самом файле, где описаны структуры периферии, описаны и мнемонические имена битов:
Код
    DMA1_Channel1->CCR = 0
            | 1 * DMA_CCR1_EN           // enable channel
            | 1 * DMA_CCR1_TCIE         // Transfer complete interrupt
            | 1 * DMA_CCR1_HTIE         // Half Transfer interrupt
            | 0 * DMA_CCR1_TEIE         // Transfer error interrupt
            | 0 * DMA_CCR1_DIR          // Data transfer direction: Peripheral->Memory
            | 1 * DMA_CCR1_CIRC         // Circular mode
            | 0 * DMA_CCR1_PINC         // Peripheral increment mode
            | 1 * DMA_CCR1_MINC         // Memory increment mode
            | 0 * DMA_CCR1_PSIZE_0      // Peripheral size: 8 bits
            | 0 * DMA_CCR1_MSIZE_0      // Memory size: 8 bits
            | 0 * DMA_CCR1_PL_0         // Channel Priority level: lowest, conversion frequency is low enough
            | 0 * DMA_CCR1_MEM2MEM      // Memory to memory mode disabled
          ;
smk
Кое как справился, но наткнулся на неприятную штуку, связанную с битом OVR в АЦП. Там хорошо потанцевать надо если заткнется АЦП. А в целом вышло как и планировалось. Всем спасибо.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.