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

 
 
> ADC+DMA STM32F407, Как определить время преобразования?
Haamu
сообщение Jan 13 2014, 08:40
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 90
Регистрация: 12-12-13
Пользователь №: 79 587



Необходимо измерить сигнал с нескольких каналов последовательно, сохраняя данные в память через DMA. Измерять надо крайне быстро. Действую таким образом: выбираю канал, запускаю АЦП. Вот кусок кода:
Код
if(ModeStruct.Discreteness_hall) {
    if ((step_counter % ModeStruct.Discreteness_hall) == 0) {
        ADC1->SQR3 = ADC_Channel_0;
        ADC1->CR2 |= ADC_CR2_SWSTART;    //Start ADC
    }
}
if (ModeStruct.Discreteness_l) {
    if ((step_counter % ModeStruct.Discreteness_l) == 0) {
        ADC1->SQR3 = ADC_Channel_1;
        ADC1->CR2 |= ADC_CR2_SWSTART;    //Start ADC
    }
}
if (ModeStruct.Discreteness_diff) {
    if ((step_counter % ModeStruct.Discreteness_diff) == 0) {
        ADC1->SQR3 = ADC_Channel_2;
        ADC1->CR2 |= ADC_CR2_SWSTART;    //Start ADC
    }
}

Вот инициализация (тоже кусок):
Код
ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStruct.ADC_ScanConvMode = DISABLE;
ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStruct.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStruct);

Столкнулся с такой проблемой, что в какой-то момент очередное преобразование АЦП запускается до того, как завершилось предыдущее, после чего отключается DMA.
Подскажите, как максимально быстро можно проверить, завершилось ли предыдущее преобразование, можно ли запускать следующее?
Пробовал проверять таким вот образом:
Код
ADC1->SQR3 = ADC_Channel_0;
ADC1->CR2 |= ADC_CR2_SWSTART;    //Start ADC
while(!(ADC1->SR & (uint32_t)ADC_FLAG_EOC)) {}
ADC1->SR &= ~((uint32_t)ADC_FLAG_EOC);

Без DMA такой способ работает. Но когда включаю DMA, то флаг окончания преобразования не поднимается, видимо его DMA раньше перехватывает и сам сбрасывает.
Была мысль делать небольшую задержку после запуска преобразования, но что-то я запутался, как рассчитать время, необходимое для завершения перобразования. А конкретно, как определить часосту тактирования АЦП? Частота ядра в моем случае 168МГц, соответстсвенно шина APB2 работает на частоте 84МГц. Значит и частота АЦП 84МГц, или есть еще какие-то предделители? Вводит в заблуждение предделитель в ADC common control register. Учитывается ли этот регистр при работе с одним АЦП или используется только когда запускаю 2 или 3 АЦП одновременно?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
MiklPolikov
сообщение Jan 16 2014, 02:36
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Вы неправильно подходите к задаче.
1)Зачем запускать преобразование по каждому каналу отдельно ? Нужно выбрать группу(цепочку) каналов, и запускать преобразование всей группы, тогда они и будут преобразовываться с максимальной скоростью .
2)После преобразования, если уж оно запущено как у Вас вручную, нужно ждать когда выставится бит того что оно завершено. В вашем коде этого нет.
3)Зачем вообще запусать преобразование вручную ? Надо выбрать гдеппу(цепочку) каналов, запускать преобразование по триггеру от таймера, по завершению преобразования автоматический запрос ДМА. А потом уже разбирать то что ДМА в память написал.

Вот Вам два моих кода. Первый настраивает цепочку из двух каналов для преобразования по запуску вручную и чтения результата вручную.
Второй настраивает цепочку из 1 канала(но из комментариев понятно, как сделать больше) для преобразования по триггеру от таймера и чтения по ДМА.
Они для STM32L151, но на вид у нас АЦП почти одинаковые.

Код
   ADC1->CR2&=~ADC_CR2_ADON;  //вЫключили АЦП
    
   ADC1->CR1|=ADC_CR1_PDI;  //power down между преобразованиями    
     ADC1->CR1|=ADC_CR1_PDD;  //power down между пачками преобразований
    
   //ADC1->SMPR2|=(7<<3);  //канал 11 время выборки 384 клока
     //ADC1->SMPR2|=(7<<12);  //канал 14 время выборки 384 клока

     ADC1->CR1|=ADC_CR1_SCAN; //включаем Scan mode , что бы преобразовывалась вся цепочка за раз

   //ADC1->JSQR|=ADC_JSQR_JL_1; //3 преобразования в цепочке injectid каналов
     ADC1->JSQR|=ADC_JSQR_JL_0; //2 преобразования в цепочке injectid каналов

   ADC1->JSQR|=(11<<15)|(14<<10); //injected каналы 11 и 14

     ADC->CCR&=~ADC_CCR_ADCPRE;  //частота АЦП= HSI

   ADC1->CR1&=~ADC_CR1_RES_0;
     ADC1->CR1&=~ADC_CR1_RES_1; // 12 бит
    // ADC1->CR2|=ADC_CR2_ALIGN; // левый сдвиг результата в регистре данных. Что бы правитльно прочитать 12и битовый результат из 16и битового резистра

   ADC1->CR2|=ADC_CR2_ADON;  //включили АЦП
   while(!(ADC1->SR & ADC_SR_ADONS)){}  //ждём пока включится
        
   while(ADC1->SR & ADC_SR_JCNR){} //ждём пока injected каналы станут готовы
   ADC1->SR&=~ADC_SR_JEOC;
    
   ADC1->CR2|=ADC_CR2_JSWSTART; //запускаем преобразование injectid каналов
   while(!(ADC1->SR & ADC_SR_JEOC)){}//ждём пока преобразование завершится


Код
   ADC1->CR2&=~ADC_CR2_ADON;  //вЫключили АЦП

   ADC1->SMPR1=0x0;
   ADC1->SMPR2=0x0;
   ADC1->SMPR3=0x0; //время выборки минимальное
  
    ADC->CCR&=~ADC_CCR_ADCPRE;  //частота АЦП= HSI
   //ADC->CCR|=ADC_CCR_TSVREFE; //включили внутренний источник опорного напряжения  //////////////////////////////

   ADC1->CR1|=ADC_CR1_PDI;  //power down между преобразованиями    
   //ADC1->CR1|=ADC_CR1_PDD;  //power down  во время задержки
   //ADC1->CR1|=ADC_CR2_DELS; // задержка 255 клоков APB


      ADC1->CR1&=~ADC_CR1_RES_0;
     ADC1->CR1&=~ADC_CR1_RES_1; // 12 бит
     ADC1->CR2|=ADC_CR2_ALIGN; // левый сдвиг результата в регистре данных. Что бы правитльно прочитать 12и битовый результат из 16и битового резистра


   ADC1->CR2|=ADC_CR2_EXTEN_1; // преобразование по переднему фронту внешнего сигнала//////////////////////////////
   ADC1->CR2|=ADC_CR2_EXTSEL_0; //преобразование по  TIM9_TRGO event
  
   ADC1->SQR5|=(1<<0);  //1 преобразование в цепочке  1 канал
  
   ADC1->CR2|=ADC_CR2_DDS; // Запросы ДМА не прекращаются после последней передачи
   ADC1->CR2|=ADC_CR2_DMA; // Включаем запрос ДМА

   ADC1->CR2|=ADC_CR2_ADON;  //включили АЦП
   while(!(ADC1->SR & ADC_SR_ADONS)){} // ждём пока включится


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
Haamu
сообщение Jan 16 2014, 11:54
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 90
Регистрация: 12-12-13
Пользователь №: 79 587



Цитата(MiklPolikov @ Jan 16 2014, 06:36) *
1)Зачем запускать преобразование по каждому каналу отдельно ? Нужно выбрать группу(цепочку) каналов, и запускать преобразование всей группы

Я рассматривал такой вариант, но отказался от него, т.к. каждый раз число каналов может быть разным (в зависимости от значения параметра дискретности). Для понятности, вот полностью обработчик прерывания таймера:
Код
void TIM3_IRQHandler(void) //limit - 560 ticks
{
    if (TIM3->SR & TIM_IT_Update) {
        if (step_counter < 10000) {        //step_counter = 0 - 9999
            DAC->DHR12R2 = ModeStruct.SignalData[step_counter] + 0x7FF;
            DAC->SWTRIGR |= DAC_SWTRIGR_SWTRIG2;
            __asm("mov r0, #10 \n" "cycle00: subs r0, #1 \n" " bhi cycle00");
            if (ModeStruct.Discreteness_hall) {
                if ((step_counter % ModeStruct.Discreteness_hall) == 0) {
                    ADC1->SQR3 = ADC_Channel_0;
                    ADC1->CR2 |= ADC_CR2_SWSTART;
                    __asm("mov r0, #12 \n" "cycle01: subs r0, #1 \n" " bhi cycle01");
                }
            }
            if (ModeStruct.Discreteness_l) {
                if ((step_counter % ModeStruct.Discreteness_l) == 0) {
                    ADC1->SQR3 = ADC_Channel_1;
                    ADC1->CR2 |= ADC_CR2_SWSTART;
                    __asm("mov r0, #12 \n" "cycle02: subs r0, #1 \n" " bhi cycle02");
                }
            }
            if (ModeStruct.Discreteness_diff) {
                if ((step_counter % ModeStruct.Discreteness_diff) == 0) {
                    ADC1->SQR3 = ADC_Channel_2;
                    ADC1->CR2 |= ADC_CR2_SWSTART;
                    __asm("mov r0, #12 \n" "cycle03: subs r0, #1 \n" " bhi cycle03");
                }
            }
            if (ModeStruct.Discreteness_b_hall) {
                if ((step_counter % ModeStruct.Discreteness_b_hall) == 0) {
                    ADC1->SQR3 = ADC_Channel_10;
                    ADC1->CR2 |= ADC_CR2_SWSTART;
                    __asm("mov r0, #12 \n" "cycle04: subs r0, #1 \n" " bhi cycle04");
                }
            }
            if (ModeStruct.Discreteness_b_l) {
                if ((step_counter % ModeStruct.Discreteness_b_l) == 0) {
                    ADC1->SQR3 = ADC_Channel_11;
                    ADC1->CR2 |= ADC_CR2_SWSTART;
                    __asm("mov r0, #12 \n" "cycle05: subs r0, #1 \n" " bhi cycle05");
                }
            }
            step_counter ++;
        } else {
            step_counter = 0;
            period_counter --;
        }
        if (period_counter == 0) {
            DAC_SetChannel2Data(DAC_Align_12b_R, 0x0000);
            DAC_SoftwareTriggerCmd(DAC_Channel_2, ENABLE);
            timer_stop();
        }
        TIM3->SR &= ~TIM_IT_Update;
    }
}

Цитата(MiklPolikov @ Jan 16 2014, 06:36) *
2)После преобразования, если уж оно запущено как у Вас вручную, нужно ждать когда выставится бит того что оно завершено. В вашем коде этого нет.

Какой это бит? Как я уже писал ранее, с битом EOC ничего не вышло.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Jan 16 2014, 12:35
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(Haamu @ Jan 16 2014, 15:54) *
Какой это бит? Как я уже писал ранее, с битом EOC ничего не вышло.


Я вручную запускаю только injected каналы, и поэтому проверяю бит ADC_SR_JEOC


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Haamu   ADC+DMA STM32F407   Jan 13 2014, 08:40
|- - Сергей Борщ   Цитата(Haamu @ Jan 16 2014, 13:54) Я расс...   Jan 17 2014, 12:16
|- - HardEgor   Product Specifications Table 67. ADC characteristi...   Jan 17 2014, 18:24
|- - Haamu   Цитата(HardEgor @ Jan 17 2014, 22:24) Pro...   Jan 20 2014, 12:55
|- - HardEgor   Ну так можно снизить системную частоту и подобрать...   Jan 20 2014, 15:34
|- - Falkon_99   В тему про АЦП, у меня STM32F207 Настроил преобра...   Feb 22 2014, 20:59
|- - ViKo   Цитата(Falkon_99 @ Feb 22 2014, 23:59) На...   Feb 23 2014, 15:31
|- - Falkon_99   я прозрел! От частоты АЦП зависят результвты п...   Feb 23 2014, 17:08
|- - scifi   Цитата(Falkon_99 @ Feb 23 2014, 21:08) В ...   Feb 23 2014, 18:00
|- - Falkon_99   TS_temp ADC sampling time when reading the tempera...   Feb 24 2014, 07:52
- - HardEgor   Цитата(Haamu @ Jan 13 2014, 15:40) Была м...   Jan 16 2014, 16:29
|- - Haamu   HardEgor, подскажите пожалуйста, где именно в дата...   Jan 17 2014, 11:42
- - vlad_new   Проверте не попадаете ли Вы под еррату с Vbat (Bat...   Feb 24 2014, 13:14


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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 20:36
Рейтинг@Mail.ru


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