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

 
 
2 страниц V  < 1 2  
Reply to this topicStart new topic
> Помогите новичку с выбором, выбрать FPGA для работы с АЦП ADS16xx
van_de_luxe
сообщение Oct 18 2017, 05:34
Сообщение #16





Группа: Участник
Сообщений: 14
Регистрация: 1-04-10
Пользователь №: 56 348



Цитата(arhiv6 @ Oct 17 2017, 19:08) *
А что вы подразумеваете под "200 нс на настройку DMA"? Это же делается один раз...
А что за микроконтроллер используете?

stm32f407, SCLK 168M
Код
//поток RX
if(DMA_RX_STREAM->CR & DMA_SxCR_EN){
    DMA_RX_STREAM->CR &= ~DMA_SxCR_EN;
    while(DMA_RX_STREAM->CR & DMA_SxCR_EN){};
}
DMA->DMA_RX_IFCR = DMA_RX_CL_ALL;    //очистка всех перываний
DMA_RX_STREAM->M0AR = (uint32_t)pCurrBuffRx;
DMA_RX_STREAM->NDTR = 3;
DMA_RX_STREAM->CR |= DMA_SxCR_EN;                        //вкл потока

//поток TX
if(DMA_TX_STREAM->CR & DMA_SxCR_EN){
    DMA_TX_STREAM->CR &= ~DMA_SxCR_EN;
    while(DMA_TX_STREAM->CR & DMA_SxCR_EN){};
}
DMA->DMA_TX_IFCR = DMA_TX_CL_ALL;            //очистка всех перываний
DMA_TX_STREAM->M0AR = (uint32_t)&Mem4Tx;
DMA_TX_STREAM->NDTR = 3;

CS_ACTIVE();
DMA_TX_STREAM->CR |= DMA_SxCR_EN;                        //вкл потока
__ADS_1672_RREF_DMA_TX_STREAM->CR |= DMA_SxCR_EN;        //вкл потока


и этот код повторяется 2 раза, т.к. у меня 2 АЦП работают синхронно

Цитата(Lmx2315 @ Oct 17 2017, 22:46) *
..если данные постоянно идут - то надо по DMA писать по очереди в два буфера и обрабатывать их по очереди, причём обычно в настройках DMA уже продумано чтобы оно прыгало с одного буфера на другой , что у вас за микроконтроллер?

если бы они шли постоянно, проблем бы не было. Между порциями данный есть пауза, в ней и вся проблема, ее нужно обрабатывать

Цитата(arhiv6 @ Oct 17 2017, 23:18) *
Это если настроить DMA в режиме память->память.
Вам нужно после импульса DR прочитать из SPI 4-ре байта в память? Если у вас STM32, попробуйте по прерыванию GPIO ножки, к которой подключен DR запускать чтение по SPI. А DMA настройте на режим периферия->память, с инкрементом указателя памяти и режимом цикличности + работу DMA по событию выставления SPI-ем флага "буфер приёмника не пуст" (RXNE) + включаете прерывания DMA по событию завершения половины обмена и по окончании обмена (HTIE и TCIE). И делайте всю обработку в этих прерываниях, когда в памяти накопится достаточно данных (а буфер можно выделить большой - сколько памяти хватит). Это уже вам сэкономит время.

Не уверен, что так точно можно сделать, но вот как ещё можно доработать: если есть свободный таймер и второй канал DMA то можно не тратить время на обработку прерывания GPIO. Таймер настраиваем на подсчёт импульсов на ножке DR (считать будем до одного, т.е. обрабатывать каждый сигнал DR), этот сигнал запускает второй канал DMA, настроенное в режиме память->периферия для копирования в spi четырёх байт без циклического режима. А так как в SPI при записи происходит одновременно чтение, то получится после импульса DR копирование четырёх байт в память первым каналом DMA. Т.е. контроллер вообще может ничего не делать, только периодически отлавливая прерывания HTIF и TCIF от первого канала DMA.


В любом режиме DMA может работать непрерывно, генерируя запросы к периферии и ожидая от нее готовности данных.
В режиме SPI мастера после настройки и запуска SPI после каждого байта DMA пинает SPI, чтобы тот сгенерировал клок для очередного байта. И пинать будет до тех пор, пока NTDR>0, непрерывно.

Прочитать нужно 3 байта

По поводу прерываний - я так и делаю. EXTI->старт SPI-DMA->прерывание по окончанию транзакции DMA->и к началу. Времени на это не хватает, написал выше
В режиме мастера SPI молотит свой клок без остановки! на какой размер DMA настроили, столько он и зафигачит непрерывным потоком.
Если совсем быть точным, то я настраиваю для SPI и TX и RX. в TX подсовываю 3 пустых байта, как раз для того, чтобы SPI сгенерил клок (ножку TX вообще не настраиваю). А данные снимаю в прерывании rx_transfer_complete.
После окончания приема и до следующего EXTI SPI должен молчать

А вот с таймером мысль интересная, нужно посмотреть его возможности.. но сомневаюсь, что таймер способен запустить чужой DMA. То, что можно через DMA в таймер данные для генерации PWM подсовывать - это да

Еще есть мысль использовать таймер в качестве сигнала CLK. Тогда можно будет настроить DMA и SPI на 100500 байт и запуском/остановкой таймера, то бишь клока регулировать процесс приема данных

Сообщение отредактировал van_de_luxe - Oct 18 2017, 05:42
Go to the top of the page
 
+Quote Post
Timmy
сообщение Oct 18 2017, 07:10
Сообщение #17


Знающий
****

Группа: Участник
Сообщений: 835
Регистрация: 9-08-08
Из: Санкт-Петербург
Пользователь №: 39 515



Цитата(van_de_luxe @ Oct 18 2017, 08:34) *
stm32f407, SCLK 168M
CODE
//поток RX
if(DMA_RX_STREAM->CR & DMA_SxCR_EN){
DMA_RX_STREAM->CR &= ~DMA_SxCR_EN;
while(DMA_RX_STREAM->CR & DMA_SxCR_EN){};
}
DMA->DMA_RX_IFCR = DMA_RX_CL_ALL; //очистка всех перываний
DMA_RX_STREAM->M0AR = (uint32_t)pCurrBuffRx;
DMA_RX_STREAM->NDTR = 3;
DMA_RX_STREAM->CR |= DMA_SxCR_EN; //вкл потока

//поток TX
if(DMA_TX_STREAM->CR & DMA_SxCR_EN){
DMA_TX_STREAM->CR &= ~DMA_SxCR_EN;
while(DMA_TX_STREAM->CR & DMA_SxCR_EN){};
}
DMA->DMA_TX_IFCR = DMA_TX_CL_ALL; //очистка всех перываний
DMA_TX_STREAM->M0AR = (uint32_t)&Mem4Tx;
DMA_TX_STREAM->NDTR = 3;

CS_ACTIVE();
DMA_TX_STREAM->CR |= DMA_SxCR_EN; //вкл потока
__ADS_1672_RREF_DMA_TX_STREAM->CR |= DMA_SxCR_EN; //вкл потока


- не нужно каждый раз перезаписывать M0AR и NDTR, они помнят значение с предыдущей записи.
- RX канал DMA можно настроить на кольцевой режим и больше вообще не трогать
- в DMA_TX_STREAM->CR надо писать через "=" все флаги, а не один флаг через "|=", чтобы исключить операцию чтения периферийного регистра.

В результате имеем, что для запуска пакета в 3 байта нужно выполнить лишь одну запись в DMA_TX_STREAM->CR. И эту запись можно выполнить в ответ на DRDY от АЦП, используя таймер и ещё один DMA канал, вообще без участия процессора, которому останется только данные из кольцевого буфера не спеша подбирать. Хотя я так не пробовал, может и не получитсяsm.gif.
Go to the top of the page
 
+Quote Post
van_de_luxe
сообщение Oct 18 2017, 07:26
Сообщение #18





Группа: Участник
Сообщений: 14
Регистрация: 1-04-10
Пользователь №: 56 348



Цитата(Timmy @ Oct 18 2017, 11:10) *
- не нужно каждый раз перезаписывать M0AR и NDTR, они помнят значение с предыдущей записи.
- RX канал DMA можно настроить на кольцевой режим и больше вообще не трогать
- в DMA_TX_STREAM->CR надо писать через "=" все флаги, а не один флаг через "|=", чтобы исключить операцию чтения периферийного регистра.

В результате имеем, что для запуска пакета в 3 байта нужно выполнить лишь одну запись в DMA_TX_STREAM->CR. И эту запись можно выполнить в ответ на DRDY от АЦП, используя таймер и ещё один DMA канал, вообще без участия процессора, которому останется только данные из кольцевого буфера не спеша подбирать. Хотя я так не пробовал, может и не получитсяsm.gif.


перезаписывать нужно.
M0AR помнит предыдущее значение, но мне не нужно принимать данные туда же, тем более в кольцевом режиме. Мне нужно их в память складировать
если M0AR был 0x20000000 и перекачали 3 байта, он и останется 0x200000000, а не увеличится до 0x20000003. Изменяется скорее всего значения какого-то внутреннего регистра. Это я проверял
NDTR уменьшается с каждым перекачанным байтом и его однозначно нужно заново выставлять
С CR согласен
итого минус одна операция

Я правильно понял, что таймер вы предлагаете так использовать:
Заранее сформировать значение CR
завести DRDY на ногу счетчика таймера и активировать событие таймера для соотв. ему DMA.
DMA таймера при этом настроить на режим память-память (вот тут сомнения будет ли он тогда запросы от таймера видеть)

Получится так
Заранее настраиваем DMA, кроме включения
активируем таймер
таймер срабатывает, пинает свой поток DMA, который делает запись в регистр CR и включает DMA SPI
ждем прерывания RX transfer complete

Сообщение отредактировал van_de_luxe - Oct 18 2017, 07:26
Go to the top of the page
 
+Quote Post
Timmy
сообщение Oct 18 2017, 08:04
Сообщение #19


Знающий
****

Группа: Участник
Сообщений: 835
Регистрация: 9-08-08
Из: Санкт-Петербург
Пользователь №: 39 515



Цитата(van_de_luxe @ Oct 18 2017, 10:26) *
перезаписывать нужно.
M0AR помнит предыдущее значение, но мне не нужно принимать данные туда же, тем более в кольцевом режиме. Мне нужно их в память складировать
если M0AR был 0x20000000 и перекачали 3 байта, он и останется 0x200000000, а не увеличится до 0x20000003. Изменяется скорее всего значения какого-то внутреннего регистра. Это я проверял
NDTR уменьшается с каждым перекачанным байтом и его однозначно нужно заново выставлять
С CR согласен
итого минус одна операция

Вы думаете, что кольцевой буфер надо на 3 байта настраивать? Вообще-то можно и на 999, что создаст огромный запас на время реакции. А по NDTR прочитайте мануал очень внимательно, я сам так делаю и всё работает, у него два физических регистра, один теневой, который только пишется, другой счётный, который читается, а при перезапуске(ручном или автоматическом) загружается из теневого.
Go to the top of the page
 
+Quote Post

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

 


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


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