19.04.2013, 10:13
|
|
Частый гость
Регистрация: 04.12.2012
Сообщений: 38
Сказал спасибо: 25
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: ADC+DMA stm32f4
Сообщение от SasaVitebsk
|
Отвечу Вам максимально детально.
|
Спасибо большое за развернутый ответ! Я так и рассуждал что для ДМА нет разницы откуда брать данные, но так или иначе, мой выше предложенный код никак не хочет работать (((
|
|
|
|
19.04.2013, 10:21
|
|
Частый гость
Регистрация: 04.12.2012
Сообщений: 38
Сказал спасибо: 25
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: ADC+DMA stm32f4
Сообщение от SasaVitebsk
|
Отвечу Вам максимально детально.
|
Спасибо большое за развернутый ответ! Я так и рассуждал что для ДМА нет разницы откуда брать данные, но так или иначе, мой выше предложенный код никак не хочет работать (((
|
|
|
|
19.04.2013, 12:25
|
|
Гражданин KAZUS.RU
Регистрация: 04.08.2006
Сообщений: 911
Сказал спасибо: 28
Сказали Спасибо 180 раз(а) в 139 сообщении(ях)
|
Re: ADC+DMA stm32f4
А что значит "не работает"?
Надо разбираться. Поскольку пользы от такого DMA - 0, то я так не делал.
Надо запрограммировать на инкремент памяти и инкремент регистров. По 4 байта со смещением 4. У Вас вроде 3 регистра, соответственно длина 12 байт. Старт DMA сделать по таймеру. По тому же таймеру, по которому вы запускаете измерение.
При отладке, сначала убедится что вы мерите правильно. То есть в ваших регистрах АЦП ADC_JDR лежат правильные значения. Далее переходите к DMA.
Не может не работать. Должно всё работать.
|
|
|
Сказали "Спасибо" SasaVitebsk
|
|
|
19.04.2013, 12:35
|
|
Частый гость
Регистрация: 04.12.2012
Сообщений: 38
Сказал спасибо: 25
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: ADC+DMA stm32f4
Блин, как меня задолбал этот АЦП, все никак не могу настроить(((((((((
Не могу понять почему ацп не тактируется от таймера!!!!!!!!
PHP код:
|
//*********************TIM3************************* RCC-›APB1ENR |= RCC_APB1ENR_TIM2EN; // тактирование таймера TIM2-›PSC = 160-1; // предделитель TIM2-›ARR = 1000-1; // переполнение TIM2-›CR2 |= TIM_CR2_MMS_1; // output (TRGO) TIM2-›CR1 |= TIM_CR1_CEN; // запуск счета
RCC-›AHB1ENR |= RCC_AHB1ENR_GPIOAEN; //********************ADC1**CH6 PA6*************** RCC-›APB2ENR |= RCC_APB2ENR_ADC1EN; //********************DMA*************************** RCC-›AHB1ENR |= RCC_AHB1ENR_DMA2EN; DMA2_Stream0-›CR&=~ DMA_SxCR_CHSEL; // 000: channel 0 selected DMA2_Stream0-›PAR= (uint32_t)&ADC1-›DR; // DMA2_Stream0-›M0AR=(uint32_t)&BUFF[0]; // Массив DMA2_Stream0-›NDTR=100; // Длина буфера DMA2_Stream0-›CR|= DMA_SxCR_MINC; // Инкремент адреса DMA2_Stream0-›CR|= DMA_SxCR_MSIZE_0; // 16 бит DMA2_Stream0-›CR|= DMA_SxCR_PSIZE_0; // 16 бит DMA2_Stream0-›CR|= DMA_SxCR_CIRC; // Непрерывный режим DMA2_Stream0-›CR&=~ DMA_SxCR_DIR; // 01: peripheral-to-Memory DMA2_Stream0-›CR|= DMA_SxCR_PL; // 11: Very high приоритет DMA2_Stream0-›CR|= DMA_SxCR_EN; // Вкл. передачу
GPIOA-›MODER |= GPIO_MODER_MODER6; //ADC1 CH6 PA6 ADC1-›CR2 |= (ADC_CR2_EXTSEL_1|ADC_CR2_EXTSEL_2);// 0110 tim 2 (TRGO) ADC1-›CR2 |=ADC_CR2_DMA; //разрешаем рабуту DMA // ADC1-›CR2 |=ADC_CR2_CONT; ADC1-›SQR3 =6; ADC1-›CR2 |=ADC_CR2_SWSTART; ADC1-›CR2 |=ADC_CR2_ADON;
|
Если установить бит "ADC_CR2_CONT" то данные попадают в буфер, но меня такой режим не устраивает! мне необходимо чтобы ацп измерял по таймеру!Все биты для тактирования, от таймера, я установил
PHP код:
|
ADC1-›CR2|=DC_CR2_EXTSEL_1|ADC_CR2_EXTSEL_2);// 0110 tim 2 (TRGO)
|
но толку нет (((((
Подскажите пожалуйста, в чем может быть причина?
|
|
|
|
19.04.2013, 14:06
|
|
Частый гость
Регистрация: 04.12.2012
Сообщений: 38
Сказал спасибо: 25
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: ADC+DMA stm32f4
Сообщение от SasaVitebsk
|
А что значит "не работает"?
Надо разбираться. Поскольку пользы от такого DMA - 0, то я так не делал.
Надо запрограммировать на инкремент памяти и инкремент регистров. По 4 байта со смещением 4. У Вас вроде 3 регистра, соответственно длина 12 байт. Старт DMA сделать по таймеру. По тому же таймеру, по которому вы запускаете измерение.
При отладке, сначала убедится что вы мерите правильно. То есть в ваших регистрах АЦП ADC_JDR лежат правильные значения. Далее переходите к DMA.
Не может не работать. Должно всё работать.
|
В ацп я уверен, он ацепирует то что надо и как надо, данные приходят в регистр и обновляются согласно таймеру!
По поводу пользы такого метода измерения- в моем устройстве основная задача это измерять выходное напряжение, ну и в зависимости от измерений корректировать его!!!т.е сам расчет напряжения (RMS) и корректировка DAC, находится в основном цикле программы (фон).
На формирование буфера по прерываниям АЦП у меня почти нет времени, поэтому хочу использовать DMA! собственно, мне не важно в каком режиме будут работать каналы АЦП, главное что бы буфер формировался не по прерыванию!
По поводу
Цитата:
|
Старт DMA сделать по таймеру
|
, - это идея! Я пытался сделать что бы ADC тактировал DMA забирать значения
Код:
|
ADC1-›CR2 |=ADC_CR2_DMA; |
, но и это должно было работать!!! При настройке регулярных каналов у АЦП ситуация другая- Данные приходят в буфер, но ADC не тактируется от таймера...............
|
|
|
|
19.04.2013, 16:39
|
|
Гражданин KAZUS.RU
Регистрация: 04.08.2006
Сообщений: 911
Сказал спасибо: 28
Сказали Спасибо 180 раз(а) в 139 сообщении(ях)
|
Re: ADC+DMA stm32f4
Сообщение от STM32F4
|
По поводу пользы такого метода измерения- в моем устройстве основная задача это измерять выходное напряжение, ну и в зависимости от измерений корректировать его!!!т.е сам расчет напряжения (RMS) и корректировка DAC, находится в основном цикле программы (фон).
На формирование буфера по прерываниям АЦП у меня почти нет времени, поэтому хочу использовать DMA!
|
А зачем вам прерывания?!!! На то они и инжектированные каналы. Читайте прямо с регистров в основном цикле. Я же вам поясняю, что разницы нет, читаете ли вы из памяти или из регистров. У вас 4 канала и 4 регистра. Вы 1 раз инициализируете и читаете прямо с соответствующего регистра.
|
|
|
Сказали "Спасибо" SasaVitebsk
|
|
|
19.04.2013, 17:12
|
|
Частый гость
Регистрация: 04.12.2012
Сообщений: 38
Сказал спасибо: 25
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: ADC+DMA stm32f4
Сообщение от SasaVitebsk
|
А зачем вам прерывания?!!! На то они и инжектированные каналы. Читайте прямо с регистров в основном цикле. Я же вам поясняю, что разницы нет, читаете ли вы из памяти или из регистров. У вас 4 канала и 4 регистра. Вы 1 раз инициализируете и читаете прямо с соответствующего регистра.
|
На прерывания или, еще лучше, ожидание ацепирования значений, времени совсем нет ((((Тут однозначно ДМА, исключительно для формирования буфера (массива)!
Более того, необходимо измерять двумя АЦП одновременно (прямой и инверсный сигнал).
Последний раз редактировалось STM32F4; 19.04.2013 в 17:21.
|
|
|
|
19.04.2013, 22:44
|
|
Гражданин KAZUS.RU
Регистрация: 04.08.2006
Сообщений: 911
Сказал спасибо: 28
Сказали Спасибо 180 раз(а) в 139 сообщении(ях)
|
Re: ADC+DMA stm32f4
Сообщение от STM32F4
|
На прерывания или, еще лучше, ожидание ацепирования значений, времени совсем нет ((((Тут однозначно ДМА, исключительно для формирования буфера (массива)!
Более того, необходимо измерять двумя АЦП одновременно (прямой и инверсный сигнал).
|
Экий вы непонятливый... )))))))
Не надо ничего ждать!!!! Просто забирайте значения тогда, когда они вам понадобятся. Они будут автоматически обновлятся!!! Что тут непонятного?
Если хотите организуйте буфер прямо на месте. Только я не понимаю какая разница? Но тем не менее возьмите буфер и привяжите его к адресам ваших регистров. Я смотрел, они подряд идут. Такое ощущение, что вы не понимаете как это всё работает и пытаетесь брится из-за угла...
Измеряйте двумя АЦП. Какие проблемы? В чём вы пишете?
|
|
|
Сказали "Спасибо" SasaVitebsk
|
|
|
21.04.2013, 23:11
|
|
Вид на жительство
Регистрация: 10.08.2005
Сообщений: 385
Сказал спасибо: 0
Сказали Спасибо 161 раз(а) в 140 сообщении(ях)
|
Re: ADC+DMA stm32f4
Сообщение от SasaVitebsk
|
Что тут непонятного?
Если хотите организуйте буфер прямо на месте. Только я не понимаю какая разница? Но тем не менее возьмите буфер и привяжите его к адресам ваших регистров. Я смотрел, они подряд идут. Такое ощущение, что вы не понимаете как это всё работает и пытаетесь брится из-за угла...
Измеряйте двумя АЦП. Какие проблемы? В чём вы пишете?
|
Человеку нужен ряд измерений через известный интервал времени, заданный таймером. И при этом желательно без лишней нагрузки процессора.
Для чего и нужен ДМА. Догадываюсь что в STM 32 это возможно.
|
|
|
Сказали "Спасибо" Alecsej
|
|
|
22.04.2013, 01:36
|
|
Гражданин KAZUS.RU
Регистрация: 04.08.2006
Сообщений: 911
Сказал спасибо: 28
Сказали Спасибо 180 раз(а) в 139 сообщении(ях)
|
Re: ADC+DMA stm32f4
Сообщение от Alecsej
|
Человеку нужен ряд измерений через известный интервал времени, заданный таймером. И при этом желательно без лишней нагрузки процессора.
Для чего и нужен ДМА. Догадываюсь что в STM 32 это возможно.
|
Если бы вы не "догадывались", а конкретно разбирались бы в данном камне, то было бы проще. В данном случае DMA только загружает процессор и ничего не даёт.
====
Попробую ещё раз.
1. DMA выполняет операцию копирования. Применительно к АЦП он выполняет копирование из регистра в память процессора. Теоретически, на время транзакции, CPU может останавливаться. Но операция копирования с помощью DMA в любом случае оказывается быстрее, чем пересылка с помощью процессора. Кроме того, в процессорах Cortex, и в частности stm32f4 применена матрица шин, которая теоретически позволяет выполнять операцию пересылки без остановки процессора, при условии наличия свободной шины. Но грубо говоря, всё равно операция пересылки подгружает, как минимум шину, и уменьшает среднюю скорость работы процессора. Надеюсь это понятно? Если нет, то задайте вопрос.
2. При работе с регулярными каналами АЦП получается значительный выигрыш. Вы, аппаратно, можете запрограммировать работу АЦП в автоматическом режиме с перебором каналов. Например вы можете запрограммировать цикл измерения следующих входных каналов 5-7-4-8-11-1-2. И АЦП будет перебирать эти каналы. Результат измерения будет ложить в регистр ADC_DR. CPU не отвлекается на эту работу. Но вы не можете из главного цикла просто прочитать регистр ADC_DR. Точнее вы можете, но вы не знаете какому каналу соответствует значение, находящееся в регистре DR. Чтобы это узнать надо обработать прерывание по завершению преобразования АЦП и там сопоставить значение - номеру канала. Обработка прерывания займёт десятки тактов на каждый канал. Поэтому удобно использовать DMA. DMA должен забирать данные из регистра ADC_DR и складывать их в память с инкрементом по 2. В приведенном мной примере длина буфера будет 7 (по 2 байта), по числу каналов в цикле. Таким образом данные в буфере будут соответствовать своим каналам. Писать прерывание не надо Вы можете прямо в голове забирать данные прямо из памяти. Накладные расходы на DMA значительно меньше чем обработка прерывания.
3. При работе с инжектированными каналами (их 4), вы программируете какой канал соответствует какому регистру. Например ADC_JDR1 = 9, ADC_JDR2 = 12, ADC_JDR3 = 15. АЦП автоматически, без загрузки процессора измеряет и ложит результат в регистры. Вам не надо прерывание. Вы просто можете брать данные прямо из регистра. Время обращения к регистру и памяти одинаково. Таким образом лишняя пересылка НИЧЕГО НЕ ДАЁТ. Но нагружает шину и уменьшает производительность процессора.
====
Теперь по поводу буфера. По-моему, CMSIS уже определяет регистры JDR как массив. Скорее всего обращение к нему будет ADC1-›JDR[n]. Но если нет, то вы это можете сделать сами. Вы должны объявить массив uint32_t из 4 элементов и разместить его по адресу начиная с ADC_JDR1. Либо объявить указатель на массив (как это делается в CMSIS) и присвоить ему значение адреса ADC_JDR1.
Здесь надо хоть немного язык знать.
Последний раз редактировалось SasaVitebsk; 22.04.2013 в 01:43.
|
|
|
Сказали "Спасибо" SasaVitebsk
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 02:31.
|
|