Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ADC STM32F100C4T6B 7ch
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Artos5
Доброй ночи уважаемые форумчане! Помогите пожалуйста разобраться.
Хочу опрашивать АЦП (все 7 каналов) за 1-10мс.

Набрел на примеры в интернете , но они только на один канал..
Из доки понял что в инжектированном режиме можно работать сразу с 4 каналами , то есть эти 4 канала будут складывать данные в разные регистры и не затирать другие измеренные каналы АЦП.

Вопрос: какой режим мне лучше использовать? И как настроить чтобы я мог читать данные?

к примеру так:

Код
ch1 = ADC1;
ch2 = ADC2;
ch3 = ADC3;
ch4 = ADC4;
ch5 = ADC5;
ch6 = ADC6;
ch7 = ADC7;



пример нашел такой:

Код
void init_adc()
{
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// включаем порта А
        RCC_APB2PeriphClockCmd(RCC_APB2ENR_ADC1EN, ENABLE);// включаем модуль АЦП
        ADC1->SMPR2 |= (ADC_SMPR2_SMP1_2 | ADC_SMPR2_SMP1_1 | ADC_SMPR2_SMP1_0); //Задаем время выборки                                                                                            
        ADC1->CR2 |= ADC_CR2_JEXTSEL; //Преобразование инжектированной группы                                                        
        ADC1->CR2 |= ADC_CR2_JEXTTRIG; //Разрешаем внешний запуск инжектированной группы
        ADC1->CR2 |= ADC_CR2_CONT; //Преобразования запускаются одно за другим
        ADC1->CR1 |= ADC_CR1_JAUTO;
        ADC1->JSQR |= (1<<15); //Задаем номер канала  - ADC1
        ADC1->CR2 |= ADC_CR2_ADON;//Теперь включаем АЦП
        ADC1->CR2 |= ADC_CR2_JSWSTART; //Запуск преобразований
        while (!(ADC1->SR & ADC_SR_JEOC)); //ждем пока первое преобразование завершится
}

int main(void)
{
        init_7leds();
        init_adc();
        while(1)
    {
            adc_res=ADC1->JDR1;
            adc_res = (adc_res * 7300) / 100000;
            set_7led(adc_res);
    }
}

Может кто уже работал в многоканальном режиме, и может тому человеку не жалко будет показать пример кода?
Заранее спасибо за помощь! sm.gif
С уважением Артем.


-----------------------------


Я правильно понимаю?
Что надо прочитать один канал в переменную , потом выключить АЦП , выбрать другой канал АЦП , включить снова преобразование , дождаться завершения преобразования , прочитать содержимое.

Или можно выбирать номер канала не выключая АЦП?
Работал до этого с AVR , поэтому , сейчас неудобно переходить на STM32 ....
adnega
Цитата(Artos5 @ Sep 5 2014, 00:21) *
Я правильно понимаю?
Что надо прочитать один канал в переменную , потом выключить АЦП , выбрать другой канал АЦП , включить снова преобразование , дождаться завершения преобразования , прочитать содержимое.
Или можно выбирать номер канала не выключая АЦП?

Можно и нужно сделать так:
Запускаете АЦП на последовательное преобразование N каналов. Настраиваете DMA на кольцевой буфер размером 2*N с генерацией прерываний по заполнению и половинному заполнению. Подбираете тайминги так, чтобы заполнение полукольца происходило за нужные вам 1-10 мс.
Итого: будет вызываться прерывание от DMA, в котором вы сможете получить доступ к массиву данных с АЦП с N каналов. При этом АЦП продолжает молотить во вторую часть кольцевого буфера, т.е. работает непрерывно.
Artos5
Премного вам благодарен за ваш ответ!
Очень непривычно...
А есть у вас практический пример реализации этого?

ПС: По поводу ДМА . Мне надо выделить буфер под массив данных с АЦП 14 слов при использовании 7 входов АЦП. Верно? sm.gif
Получается если я "провтыкаю" , и вовремя не заберу данные , то я или потеряю их или они перемешаются? Верно?
Golikov A.
не верно
у вас АЦП сделат 7 преобразований и положит их в начало буфера (в первую половину), и позовет вас прерыванием, там вы опять запустите преобразование 7 каналов, и начнете забирать первые 7 слов, АЦП тем временем будет фигачить во 2 часть буфера, когда оно их добьет опять будет прерывание, где вы опять запустите АЦП, оно будет заполнять первую половину буфера, а вы забирать вторую...
для того буфер и 2 размера

Если я не ошибаюсь, то АЦП отдолбив 7 каналов остановиться, и вы не запустив его заново, следующие 7 слов не получите...
Artos5
Теперь понял sm.gif
А скажите, есть у вас практический пример подобной реализации?
А то в теории понятно , а практически как реализовать - ничего не понятно... sm.gif
ViKo
Цитата(adnega @ Sep 5 2014, 07:44) *
Подбираете тайминги так, чтобы заполнение полукольца происходило за нужные вам 1-10 мс.
... При этом АЦП продолжает молотить во вторую часть кольцевого буфера, т.е. работает непрерывно.

Если процессор будет успевать непрерывно обрабатывать данные, поступающие с периодом 1-10 мс, то ПДП - лишнее звено в цепи.
ПДП полезен только при работе с пачками данных.
adnega
Цитата(Golikov A. @ Sep 5 2014, 10:54) *
Если я не ошибаюсь, то АЦП отдолбив 7 каналов остановиться, и вы не запустив его заново, следующие 7 слов не получите...

И да, и нет. В настройках АЦП есть битик, который заставляет АЦП молотить каналы непрерывно.

Цитата(ViKo @ Sep 5 2014, 11:39) *
Если процессор будет успевать непрерывно обрабатывать данные, поступающие с периодом 1-10 мс, то ПДП - лишнее звено в цепи.

)) так много про что можно сказать.
Если реакция на данные с АЦП не требует промедления, то согласен: нужно заводить на прерывание от АЦП.
Если удобнее за раз обработать данные сразу с 7 каналов, но при этом частота выборок должна быть крайне стабильной, то DMA выручает.

Настройка DMA - это 4 строчки. Надеюсь мы не этого боимся?

F100 не такие толстые камушки, и там где можно решить задачу аппаратно - нужно напрягать периферию (АЦП, таймеры, DMA), а не ядро (CPU).

Из практики: я делал образец рефрактометра на F103 с эквивалентной частотой АЦП 96МГц. Только таймеры, DMA и встроенное АЦП.
KnightIgor
Цитата(ViKo @ Sep 5 2014, 09:39) *
Если процессор будет успевать непрерывно обрабатывать данные, поступающие с периодом 1-10 мс, то ПДП - лишнее звено в цепи.
ПДП полезен только при работе с пачками данных.

В документации прямо написано, что при использовании ADC в режиме сканирования использование DMA неизбежно. Причина: прерывание "завершение преобразования" от ADC вырабатывается не после преобразования каждого канала, а лишь после полного прохода.
Для автора темы: кое-что обсуждалось здесь: я как раз занимался темой многоканального непрерывного циклического преобразования. Там Сергей Борщ и предложил замечательную идею с буфером 2*N и прерыванием от полузаполнения от DMA, о чем упоминает здесь также и adnega.
AHTOXA
Цитата(adnega @ Sep 5 2014, 10:44) *
Запускаете АЦП на последовательное преобразование N каналов. Настраиваете DMA на кольцевой буфер размером 2*N с генерацией прерываний по заполнению и половинному заполнению. Подбираете тайминги так, чтобы заполнение полукольца происходило за нужные вам 1-10 мс.

Имхо, частоту опроса лучше регулировать не подбором таймингов, а запуском преобразования АЦП по таймеру. Так мы легко получим любую нужную частоту опроса.
adnega
Цитата(AHTOXA @ Sep 5 2014, 13:04) *
Имхо, частоту опроса лучше регулировать не подбором таймингов, а запуском преобразования АЦП по таймеру. Так мы легко получим любую нужную частоту опроса.

Если частота преобразований низкая, то без таймера никак. Если на пределе возможностей АЦП (например, 1 МГц), то только таймингами в модуле АЦП.
ViKo
Цитата(KnightIgor @ Sep 5 2014, 11:05) *
В документации прямо написано, что при использовании ADC в режиме сканирования использование DMA неизбежно. Причина: прерывание "завершение преобразования" от ADC вырабатывается не после преобразования каждого канала, а лишь после полного прохода.

Да, у F100 так. А вот у F303 не так.
Цитата
EOC: End of conversion flag
This bit is set by hardware at the end of each regular conversion of a channel when a new data is
available in the ADC_DR register.

DMA дает выигрыш в том, что не тратятся такты на вход - выход в прерывание. А только на вход - выход в прерывание после заполнения буфера DMA. На пределе производительности я тоже применял DMA c прерыванием на половине заполнения.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.