Имеется задача, читать с помощью микроконтроллера stm32h725vgt6, 12 бит с параллельной шины внешнего АЦП, при чём два его канала А и Б в мультиплексорном режиме. Частота тактирования должна быть не менее 4МГц. Для реализации мельтиплексорного режима, используется пин MUX_SELECT. Как описанно в даташите, если MUX_SELECT=0, то на выходной 12 битной шине канала А, будут данные с аналогового канала Б, а на шине Б будут данные с аналогового входа А. Если MUX_SELECT=1, то на выходной шине канала А, будут данные с аналогового канала А, а на шине Б будут данные с аналогового входа Б. Это позволяет использовать только одну шину данных для считывания данных с двух каналов АЦП. На этом графике видно, что если объединить пины тактирования каналов А, Б и MUX_SELECT, то можно за один переод тактирования, считывать два канала. Бах, бах, бах , всё должно работать как часы , но на практике всё сложнее.. Для параллельного считывания 12 бит на большой частоте используется DCMI и DMA. Если читать только один канал А или Б, то никаких проблем не возникает. Данные без проблем загружаются в массив. Схема подключения: Далее я пытаюсь физически подключить MUX_SELECT к тактированию каналов А и Б. И ожидаю от этого, что в массиве все чётные элементы будут данные с канала А, а не чётные, данные с канала Б. Но получается, что массив заполнен только данными канала Б. По этому сделал вывод, что DMA считывает данные вконце переода, как показал на картинке ниже: Подумал, что если тактировать АЦП частотой делённой на два, то DMA будет читать данные и в первой половине переода и во второй. Собрал делитель частоты на JK-тригере (что было под рукой), и подал на вход делителя частоты, сигнал с выхода ADC_CLKSRC (этот сигнал требуется для внешнего тактирования DCMI PIXCLK), а к выходу делителя, подключил тактирование каналов А, Б и MUX_SELECT. Сравнил два сигнала, входной и выходной, двухканальным осциллографом, вижу, что частота действительно делится на 2, в остальном сигналы идентичны. Таким образом частота сигнала на PIXCLK осталась прежней, а АЦП, тактируется меньшей частотой. В итоге получаю почти весь массив заполненый данными с канала А, и очень редко в массиве встречаются данные с канала Б. Подскажите, пожалуйста, как правильно настроить, для моего случая, DMA? Я так же пробовал изменять некоторые настройки, но это пальцем в небо, и результатов не принесло! Я понимаю, что проблема в синхронизации между тактированием DCMI и тактированием АЦП, но не знаю как это исправить. Вот мои настройки DMA, DCMI и каналов таймеров для тактирования. Контроллер работает на частоте 550МГц.
for ( uint8_t i = 0; i < NUM_DCMI_PINS; i++ ) { GPIO_InitStruct.Pin = pins[i]; LL_GPIO_Init( ports[i], &GPIO_InitStruct ); }
/* not a DCMI pin, but shorted to HSYNC and VSYNC. Init and set high */ GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pin = ADC_SYNC_PIN; GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; LL_GPIO_Init(ADC_SYNC_PORT, &GPIO_InitStruct); ADC_SYNC_PORT->BSRR |= (uint32_t)ADC_SYNC_PIN; }
static void hw_dcmi_dma_init ( void ) { /* enable the DCMI clock and read the register value back to introduce a delay */ RCC->AHB2ENR |= RCC_AHB2ENR_DCMI_PSSIEN; tmp_reg = RCC->AHB2ENR & RCC_AHB2ENR_DCMI_PSSIEN;
/* /1* start with rising edge active on PCKPOL */ SET_BIT(DCMI->CR, DCMI_CR_PCKPOL);
/* configure the DCMI control registers */ DCMI->CR |= (DCMI_CR_EDM_1 & ~DCMI_CR_EDM_0); // 12-bit data DCMI->CR |= (DCMI_CR_VSPOL | DCMI_CR_HSPOL); // VSYNC/HSYNC high DCMI->CR |= (DCMI_CR_ENABLE); // enable the DCMI peripheral
/************************************ * DMA CONFIGURATION ***********************************/ /* note: see section 15.3.19 in the reference manual */
/* enable the DMA2 clock and read the register value back to introduce a delay */ RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; tmp_reg = RCC->AHB1ENR & RCC_AHB1ENR_DMA2EN;
/* disable DMA stream and wait for it to actually disable */ DMA2_Stream1->CR &= ~(DMA_SxCR_EN); while ( (DMA2_Stream1->CR & DMA_SxCR_EN) != 0 );
/* set the peripheral address to the DCMI DR register */ WRITE_REG(DMA2_Stream1->PAR, (uint32_t)&DCMI->DR);
/* set the memory address to point to the dest. buffer */ WRITE_REG(DMA2_Stream1->M0AR, (uint32_t)&adcBffer[0]);
/* configure the total number of items to be transferred */ MODIFY_REG(DMA2_Stream1->NDTR, DMA_SxNDT, DCMI_ADC_DATA_BUF_SZ/4);
/* use DMAMUX1 to route a DMA request line (DCMI has ID 75) to the DMA channel */ MODIFY_REG(DMAMUX1_Channel9->CCR, DMAMUX_CxCR_DMAREQ_ID, 75U);
/* configure stream priority to very high */ DMA2_Stream1->CR |= (DMA_SxCR_PL);
Извините, если дал не полную информацию, готов предоставить всё что потребуется! Я понимаю, что оптимальное решение для данной задачи будет использование FPGA, но даный проект уже имеет реализацию на stm32 и требует минимальных изменений в схеме и печатной плате. Да и FPGA я не владею Использование HAL так же диктуется условиями проекта. Спасибо!
Если я правильно понял ситуацию, то читать стоит в середине импульса тактирования, а не на фронте переднем или заднем. Толи микруха успеет выставить значение, толи нет. То есть стоит не частоту снижать, а фазу двигать.
Тоесть вы хотите сказать, что использование делителя частоты не верно? Мне стоит тактировать АЦП, той же частотой, что и DCMI? Только к примеру настроить ещё один таймер на туже частоту и запускать его с некоторой задержкой от таймера тактирующего DCMI? Верно?
С этим АЦП не работал, так что наверняка не скажу. Посмотрите в какой момент интерфейс контроллера производит выборку данных с линии и в какой момент АЦП выставляет нужные уровни. Необходимо сделать так, чтобы в момент считывания преобразователь гарантированно установил на шине нужные данные, в этом смысл.
Если глобально, то зачем вообще внешний АЦП? Там и внутренний многим даст прикурить.
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Если глобально, то зачем вообще внешний АЦП? Там и внутренний многим даст прикурить.
Как я говорил вначале, данные требуется считывать с частотой не менее 4МГц, но в перспективе, чем больше частота, тем лучше. А данный контроллер больше 3-4MSPS не выдаст.
Цитата:
Необходимо сделать так, чтобы в момент считывания преобразователь гарантированно установил на шине нужные данные, в этом смысл.
Да! Это я понял! Надеюсь проблема в этом.. Буду тестировать
Цитата:
Посмотрите в какой момент интерфейс контроллера производит выборку данных с линии и в какой момент АЦП выставляет нужные уровни.
Да, это логичные шаги! Но как это сделать? Я не представляю как зафиксировать момент выборки данных, прерываний на этот случай нет.
Я хочу попробовать настроить сторонний таймер и запустить его со смещением по времени. Но буду ждать других советов!
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
у Вас на картинке есть параметр tpd (задержка от соответствующего фронта на установку данных на шине - только после нее данные достоверны) по тексту у Вас о нем ни слова. т.е. Вам надо не только удвоение частоты (захват чаще), но и фазовый сдвиг на этот самый tpd (для захвата). или аппаратно вкарячивать n кол-во вентилей, или жужать двумя таймерами.
Прерывания и не нужны. А если уж можно позволить себе прерывания, то всякие прочие интерфейсы и не требуются.
я говорил про прервывания только для отладки, что бы знать, где и когда что происходит.
Цитата:
Это разные вещи. Что требуется всё-таки? А если 16-битные АЦП запустить в разрешении 12 бит, то всё равно мало скорости?
Задача синхронизировать работу МК и внешнего вдухканального АЦП.
Цитата:
у Вас на картинке есть параметр tpd (задержка от соответствующего фронта на установку данных на шине - только после нее данные достоверны) по тексту у Вас о нем ни слова. т.е. Вам надо не только удвоение частоты (захват чаще), но и фазовый сдвиг на этот самый tpd (для захвата). или аппаратно вкарячивать n кол-во вентилей, или жужать двумя таймерами.
Да я понял, что требуется сместить тактовую частоту АЦП по фазе. Сейчас бьюсь над этим. Все частоты пока плавут. Настроил дополнительный таймер в TOGGLE режиме, на частоту в 2 раза меньше. Но пока не получается синхронизировать.
Добавлено after 2 hours 50 minutes 24 seconds: Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DMA Пытался сделать следующее: Выкинул делитель частоты на JK-триггере. Вместо него настроил отдельный таймер и для начала синхронизировал его с тактированием DCMI, потом разделил эту частоту на 2. Добавил смещение одного сигнала относительно другого. И пытался подобрать это смещение. Так же пытался инвертировать одно тактирование относительно другого. Результаты остаются неизменными, массив заполняется рандомно. То каналом А, то каналом Б.. На скриншоте показал, что даже на маленьких скоростх, это не работает. Так же видно, что частоты тактирования отличаются в два раза и есть смещение. У кого то есть какие то идеи? Спасибо, вам!
потому что в будущем планируется увеличение частоты семплирования, с которой не справляется внутренний АЦП
Так выберите такой, который справится. Если уж нужна высокая частота сэмплирования, то однозначно никакими ухищрениями не сможете читать в реальном времени из него с такой скоростью, с какой внутренний АЦП позволяет. Он 100 очков вперёд даст внешнему. Так как там и шина 32-битная (а не дохлые 12 бит) и сопряжение с DMA нормально сделано, без костылей со сдвигами фазы как у вас.
Возможно, вы правы! Если на я смогу подобрать контроллер pin-to-pin, но пока я не смог найти контроллер хотя бы в районе частоты семлирования 20MSPS.
Добавлено after 14 minutes 58 seconds: Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DMA Но как обычно бывает, и думаю такое было у всех, партия готовых и спаянных плат лежит передомной на столе и у меня есть задача отладить и запустить это чудо, именно поэтому я задал этот вопрос на форуме. Я видел некоторые статьи на тему совмещения параллельных васокоскоростных микросхем АЦП и контроллеров СТМ с помощью DCMI.. Вот к примеру: https://habr.com/ru/articles/482506/ viewtopic.php?p=3677112 https://github.com/cychenbuaa/Driving-A ... r_pto=wapp Но задача мультиплексирования выходов на одну шину перед ними не стояла, и не представляю как это отладить. Я надеялся мне тут помогут с этим
Но как обычно бывает, и думаю такое было у всех, партия готовых и спаянных плат лежит передомной на столе
Нет, так бывает только у тех, кто ставит телегу впереди лошади. У тех, у кого есть голова на плечах, такого не бывает, потому как сперва делается поиск наиболее оптимального решения задачи (и наиболее оптимального контроллера), потом - макетирование на отладочных платах. А изготовление своих плат - это когда уже все решения отработаны на макетках и точно работают. У тех кто паяет партию плат(!) , а только потом начинает думать, как правило - или эта партия идёт в мусорную корзину; или долго и мучительно потом костылится, чтобы хоть как-то дотянуть до требований (чего обычно не получается, а остаётся "что получилось").
Странно, что вам даже не пришло в голову промакетировать своё решение. Уж не говоря о том чтобы просто поискать более подходящий МК, а не брать первый попавшийся под руку.
Пока потеряны только деньги на изготовление плат, но ещё не потеряна куча времени, пойти к начальству, повиниться и свернуть на правильный путь. Вот правильное решение.
PS: Если уж нужна высокая частота сэмплирования, то почему не выбран LPC4370? Который к тому же и кратно дешевле вашего выбора? И запускается с полпинка. И схема простая. И таких характеристик по скорости сэмплирования как у него, на вашем паровозе даже близко не достичь.
Подумал, что если тактировать АЦП частотой делённой на два, то DMA будет читать данные и в первой половине переода и во второй. Собрал делитель частоты на JK-тригере (что было под рукой), и подал на вход делителя частоты, сигнал с выхода ADC_CLKSRC (этот сигнал требуется для внешнего тактирования DCMI PIXCLK), а к выходу делителя, подключил тактирование каналов А, Б и MUX_SELECT.
Данные принимаются по спаду DCMI_PIXCLK Это значит, что JK-триггер должен переворачиваться по нарастанию DCMI_PIXCLK Проверьте. И он должен быть максимально быстрым (инверторы на входе нежелательны из-за задержки).
Тогда давайте актуальную схему. Подозреваю, что затык какой-то вовсе не великий.
Да, конечно! не проблема! Я совместил всё на одном листе, поудалял всё лишнее. Прикрепил и pdf и изображение, если требуется могу выложить проект KiCAD
Добавлено after 3 minutes 56 seconds: Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DMA
Цитата:
Данные принимаются по спаду DCMI_PIXCLK Это значит, что JK-триггер должен переворачиваться по нарастанию DCMI_PIXCLK Проверьте. И он должен быть максимально быстрым (инверторы на входе нежелательны из-за задержки).
mont-oriol, спасбо за ответ) Но я уже писал выше, что отказался от использования JK, и настроил и синхронизировал отдельный таймер для тактирования АЦП. И да, я пытался делать тактирование прямым и инвертным
Добавлено after 16 minutes 54 seconds: Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DMA jcxz Я ценю ваш опыт и точку зрения. Я согласен, что важно макетировать и проверять решения перед применением. Возможно, я не сделал это ясным в своих предыдущих сообщениях, но я прошу конкретной помощи по конкретному вопросу. Если у вас есть опыт или знания, которые могут помочь мне решить эту проблему, я был бы очень благодарен за это. Если нет, то зачем лить воду и устраивать бесполезную полемику? Ситуация с вами напоминает общение на форуме: Обычный пользователь>>Помогите, пожалуйста, я не могу запустить эту программу, что мне делать? "Профессионал">>Выкинь комп!
До конца не додумал, но пока спать не ушёл напишу что понял. Для закрепления, так сказать. В инструкции на АЦП написано, что
Цитата:
If the ADCs are run with synchronized timing, this same clock can be applied to the MUX_SELECT bit. After the MUX_SELECT rising edge, either data port will have the data for its respective channel; after the falling edge, the alternate channel’s data will be placed on the bus.
Очевидно, это как раз желаемая ситуация. То есть за один период тактирования данные высовываются то одни, то другие. А интерфейс считывает только один раз за период, причём сразу по заднему фронту (по спаду). А уж успел там АЦП данные выставить или нет это уже его проблемы.
Очевидно, это как раз желаемая ситуация. То есть за один период тактирования данные высовываются то одни, то другие. А интерфейс считывает только один раз за период, причём сразу по заднему фронту (по спаду). А уж успел там АЦП данные выставить или нет это уже его проблемы.
Да, да.. имено поэтому пришлось использовать другой источник тактирования для АЦП и поделить его чатсоту на 2, что бы интерфейс считывал данные два раза за один период тактирования АЦП. Но синхронизировать это не получается. Или я не улавливаю вашу мысль?
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 29
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения