реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> STM32F407 ADC + DMA, Не получается уложить в массив
smk
сообщение Jul 29 2015, 11:52
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Прошу помочь с такой ситуацией. Есть 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);



--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
Tanya
сообщение Jul 29 2015, 12:08
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 8 752
Регистрация: 6-01-06
Пользователь №: 12 883



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

Пользуюсь КУБом и не вникаю в детали. Все получается.
Примерно так. Записываем в конец массива 0xFFFF, запускаем АЦП_ДМА, АЦП стартует по фронту на ножке. Так как синхросигнал неизвестно когда придет, проверяем последний элемент массива. Можно иначе - через прерывания, например. Потом стартуем снова с другим массивом.
Go to the top of the page
 
+Quote Post
smk
сообщение Jul 29 2015, 12:17
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



По приходу синхросигнала вызывается прерывание. В прерывании подставляю ДМА новый адрес перврго элемента массива. Сбрасываю флаг и запускаю ДМА. При том, что представляет собой код значения АЦП укладываются м массив постоянно. Пока только в один. Проблема в том, что ДМА не останавливается, а укладывает по новому кругу. Мне нужно чтобы 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
}
}


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
Tanya
сообщение Jul 29 2015, 12:41
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 8 752
Регистрация: 6-01-06
Пользователь №: 12 883



Цитата(smk @ Jul 29 2015, 15:17) *
По приходу синхросигнала вызывается прерывание.
значения АЦП укладываются м массив постоянно. Пока только в один. Проблема в том, что ДМА не останавливается, а укладывает по новому кругу. Мне нужно чтобы 1000 отсчетов уложились и стоп до следующего прихода синхры. Как это реализовать?


Зачем прерывание с его задержкой?
У Вас круговой режим ДМА включен? Нужен однократный.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 29 2015, 13:21
Сообщение #5


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



А зачем вы выставили бит 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
          ;


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
smk
сообщение Jul 30 2015, 12:46
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Кое как справился, но наткнулся на неприятную штуку, связанную с битом OVR в АЦП. Там хорошо потанцевать надо если заткнется АЦП. А в целом вышло как и планировалось. Всем спасибо.


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 17:07
Рейтинг@Mail.ru


Страница сгенерированна за 0.01414 секунд с 7
ELECTRONIX ©2004-2016