Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DMA

Чт авг 03, 2023 09:27:55

Добрый день!

Имеется задача, читать с помощью микроконтроллера stm32h725vgt6, 12 бит с параллельной шины внешнего АЦП, при чём два его канала А и Б в мультиплексорном режиме.
Изображение
Частота тактирования должна быть не менее 4МГц.
Для реализации мельтиплексорного режима, используется пин MUX_SELECT. Как описанно в даташите, если MUX_SELECT=0, то на выходной 12 битной шине канала А, будут данные с аналогового канала Б, а на шине Б будут данные с аналогового входа А. Если MUX_SELECT=1, то на выходной шине канала А, будут данные с аналогового канала А, а на шине Б будут данные с аналогового входа Б. Это позволяет использовать только одну шину данных для считывания данных с двух каналов АЦП.
Изображение
На этом графике видно, что если объединить пины тактирования каналов А, Б и MUX_SELECT, то можно за один переод тактирования, считывать два канала.
Бах, бах, бах :kill: , всё должно работать как часы 8) , но на практике всё сложнее..
Для параллельного считывания 12 бит на большой частоте используется DCMI и DMA. Если читать только один канал А или Б, то никаких проблем не возникает. Данные без проблем загружаются в массив. Схема подключения:
Изображение Изображение
Далее я пытаюсь физически подключить MUX_SELECT к тактированию каналов А и Б. И ожидаю от этого, что в массиве все чётные элементы будут данные с канала А, а не чётные, данные с канала Б. Но получается, что массив заполнен только данными канала Б.
По этому сделал вывод, что DMA считывает данные вконце переода, как показал на картинке ниже:
Изображение
Подумал, что если тактировать АЦП частотой делённой на два, то DMA будет читать данные и в первой половине переода и во второй. Собрал делитель частоты на JK-тригере (что было под рукой), и подал на вход делителя частоты, сигнал с выхода ADC_CLKSRC (этот сигнал требуется для внешнего тактирования DCMI PIXCLK), а к выходу делителя, подключил тактирование каналов А, Б и MUX_SELECT. Сравнил два сигнала, входной и выходной, двухканальным осциллографом, вижу, что частота действительно делится на 2, в остальном сигналы идентичны. Таким образом частота сигнала на PIXCLK осталась прежней, а АЦП, тактируется меньшей частотой. В итоге получаю почти весь массив заполненый данными с канала А, и очень редко в массиве встречаются данные с канала Б.
Подскажите, пожалуйста, как правильно настроить, для моего случая, DMA? Я так же пробовал изменять некоторые настройки, но это пальцем в небо, и результатов не принесло! Я понимаю, что проблема в синхронизации между тактированием DCMI и тактированием АЦП, но не знаю как это исправить.
Вот мои настройки DMA, DCMI и каналов таймеров для тактирования. Контроллер работает на частоте 550МГц.

Инициализация GPIO:
Код:
static void hw_dcmi_gpio_init ( void )
{
   
    LL_GPIO_InitTypeDef GPIO_InitStruct = { 0 };

    uint16_t pins[NUM_DCMI_PINS] = { DCMI_PIXCLK_PIN, DCMI_VSYNC_PIN, DCMI_HSYNC_PIN,
                                    ADC_D0_PIN, ADC_D1_PIN, ADC_D2_PIN,
                                    ADC_D3_PIN, ADC_D4_PIN, ADC_D5_PIN, ADC_D6_PIN,
                                    ADC_D7_PIN, ADC_D8_PIN, ADC_D9_PIN, ADC_D10_PIN,
                                    ADC_D11_PIN };

    GPIO_TypeDef * ports[NUM_DCMI_PINS] = { DCMI_PIXCLK_PORT, DCMI_VSYNC_PORT, DCMI_HSYNC_PORT,
                                ADC_D0_PORT, ADC_D1_PORT, ADC_D2_PORT,
                                ADC_D3_PORT, ADC_D4_PORT, ADC_D5_PORT, ADC_D6_PORT,
                                ADC_D7_PORT, ADC_D8_PORT, ADC_D9_PORT, ADC_D10_PORT,
                                ADC_D11_PORT };

    /* enable required clocks */
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOD_CLK_ENABLE();

    GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = LL_GPIO_AF_13;

    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_adc_clksrc_init ( void )
{
    TIM_MasterConfigTypeDef sMasterConfig = {0};
    TIM_OC_InitTypeDef sConfigOC = {0};
    TIM_ClockConfigTypeDef sClockSourceConfig = {0};
    TIM_SlaveConfigTypeDef sSlaveConfig = {0};

    // enable RCC clocks for timer dependencies
    __HAL_RCC_TIM1_CLK_ENABLE();
    __HAL_RCC_TIM2_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();

    /* DCMI PIXCLK source timer */
    htim_dcmi_pixclkc_src.Instance = DCMI_PIXCLK_TIM_INSTANCE;
    htim_dcmi_pixclkc_src.Init.Prescaler = 0;
    htim_dcmi_pixclkc_src.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim_dcmi_pixclkc_src.Init.Period = (uint32_t)(272.0f / DCMI_CLKSRC_FREQ_MHZ / 2.0f);
    htim_dcmi_pixclkc_src.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim_dcmi_pixclkc_src.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    if (HAL_TIM_Base_Init(&htim_dcmi_pixclkc_src) != HAL_OK)
        Error_Handler();

    sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
    if (HAL_TIM_ConfigClockSource(&htim_dcmi_pixclkc_src, &sClockSourceConfig) != HAL_OK)
        Error_Handler();

    if (HAL_TIM_OC_Init(&htim_dcmi_pixclkc_src) != HAL_OK)
        Error_Handler();

    sMasterConfig.MasterOutputTrigger = TIM_TRGO_ENABLE;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
    if (HAL_TIMEx_MasterConfigSynchronization(&htim_dcmi_pixclkc_src, &sMasterConfig) != HAL_OK)
        Error_Handler();

    sConfigOC.OCMode = TIM_OCMODE_TOGGLE;
    sConfigOC.Pulse = 0;
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    if (HAL_TIM_OC_ConfigChannel(&htim_dcmi_pixclkc_src, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
        Error_Handler();

    __HAL_TIM_ENABLE_OCxPRELOAD(&htim_dcmi_pixclkc_src, TIM_CHANNEL_1);
   
    /* ADC clock source */
    htim_adc_clksrc.Instance = ADC_CLKSRC_TIM_INSTANCE;
    htim_adc_clksrc.Init.Prescaler = 0;
    htim_adc_clksrc.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim_adc_clksrc.Init.Period = (uint32_t)( 272.0f / DCMI_CLKSRC_FREQ_MHZ ) + 1U;
    htim_adc_clksrc.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim_adc_clksrc.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;

    if (HAL_TIM_Base_Init(&htim_adc_clksrc) != HAL_OK)
        Error_Handler();

    sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
    if (HAL_TIM_ConfigClockSource(&htim_adc_clksrc, &sClockSourceConfig) != HAL_OK)
        Error_Handler();

    if (HAL_TIM_OC_Init(&htim_adc_clksrc) != HAL_OK)
        Error_Handler();

    sSlaveConfig.SlaveMode = TIM_SLAVEMODE_GATED;
    sSlaveConfig.InputTrigger = TIM_TS_ITR0;
    if (HAL_TIM_SlaveConfigSynchro(&htim_adc_clksrc, &sSlaveConfig) != HAL_OK)
        Error_Handler();

/*     sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; */
/*     sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE; */
/*     if (HAL_TIMEx_MasterConfigSynchronization(&htim_adc_clksrc, &sMasterConfig) != HAL_OK) */
/*         Error_Handler(); */

    sConfigOC.OCMode = TIM_OCMODE_TOGGLE;
    sConfigOC.Pulse = 0;
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    if (HAL_TIM_OC_ConfigChannel(&htim_adc_clksrc, &sConfigOC, ADC_CLKSRC_TIM_CHANNEL) != HAL_OK)
        Error_Handler();

    __HAL_TIM_ENABLE_OCxPRELOAD(&htim_adc_clksrc, ADC_CLKSRC_TIM_CHANNEL);

}


Инициализация DMA:
Код:
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

    /* SEGGER_RTT_printf(0, "DCMI CR: 0x%x\n", DCMI->CR); */

    /************************************
     * 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);

    /* direction: peripheral-to-memory */
    DMA2_Stream1->CR &= ~(DMA_SxCR_DIR);

    /* enable memory increment */
    DMA2_Stream1->CR |= DMA_SxCR_MINC;

    /* disable peripheral inc */
    DMA2_Stream1->CR &= ~(DMA_SxCR_PINC);

    /* set memory burst to INC8 */
    DMA2_Stream1->CR |= DMA_SxCR_MBURST_1;
    DMA2_Stream1->CR &= ~(DMA_SxCR_MBURST_0);

    /* set peripheral burst to single */
    DMA2_Stream1->CR &= ~(DMA_SxCR_PBURST);

    /* set peripheral data size to a word */
    DMA2_Stream1->CR |= DMA_SxCR_PSIZE_1;
    DMA2_Stream1->CR &= ~DMA_SxCR_PSIZE_0;
   
    /* set memory data size to a word */
    DMA2_Stream1->CR |= DMA_SxCR_MSIZE_1;
    DMA2_Stream1->CR &= ~DMA_SxCR_MSIZE_0;

    /* enable circular mode */
    DMA2_Stream1->CR |= DMA_SxCR_CIRC;

    /* disable peripheral flow controller */
    DMA2_Stream1->CR &= ~DMA_SxCR_PFCTRL;

    /* ensable DMA stream and wait for it to actually ensable */
    DMA2_Stream1->CR |= (DMA_SxCR_EN);
    while ( (DMA2_Stream1->CR & DMA_SxCR_EN) == 0 );
   
    /* SEGGER_RTT_printf(0, "DMA2_Stream1 CR: 0x%x\n", DMA2_Stream1->CR); */
    /* SEGGER_RTT_printf(0, "DMAMUX1_Channel9 CCR: 0x%x\n", DMAMUX1_Channel9->CCR); */

    /* configure DMA2_Stream1 interrupt */
    NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
    NVIC_SetPriority(DMA2_Stream1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x01, 0x02));
    NVIC_EnableIRQ(DMA2_Stream1_IRQn);

    /* enable DMA stream interrupt */
    DMA2_Stream1->CR |= DMA_SxCR_TCIE;
}


Извините, если дал не полную информацию, готов предоставить всё что потребуется! Я понимаю, что оптимальное решение для данной задачи будет использование FPGA, но даный проект уже имеет реализацию на stm32 и требует минимальных изменений в схеме и печатной плате. Да и FPGA я не владею :oops:
Использование HAL так же диктуется условиями проекта.
Спасибо!

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Чт авг 03, 2023 09:42:05

Если я правильно понял ситуацию, то читать стоит в середине импульса тактирования, а не на фронте переднем или заднем. Толи микруха успеет выставить значение, толи нет. То есть стоит не частоту снижать, а фазу двигать.

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Чт авг 03, 2023 09:56:19

Тоесть вы хотите сказать, что использование делителя частоты не верно? Мне стоит тактировать АЦП, той же частотой, что и DCMI? Только к примеру настроить ещё один таймер на туже частоту и запускать его с некоторой задержкой от таймера тактирующего DCMI? Верно?

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Чт авг 03, 2023 10:08:48

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

Если глобально, то зачем вообще внешний АЦП? Там и внутренний многим даст прикурить.

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Чт авг 03, 2023 19:13:10

Начну с конца)
Если глобально, то зачем вообще внешний АЦП? Там и внутренний многим даст прикурить.

Как я говорил вначале, данные требуется считывать с частотой не менее 4МГц, но в перспективе, чем больше частота, тем лучше. А данный контроллер больше 3-4MSPS не выдаст.

Необходимо сделать так, чтобы в момент считывания преобразователь гарантированно установил на шине нужные данные, в этом смысл.

Да! Это я понял! Надеюсь проблема в этом.. Буду тестировать

Посмотрите в какой момент интерфейс контроллера производит выборку данных с линии и в какой момент АЦП выставляет нужные уровни.

Да, это логичные шаги! Но как это сделать? Я не представляю как зафиксировать момент выборки данных, прерываний на этот случай нет.

Я хочу попробовать настроить сторонний таймер и запустить его со смещением по времени. Но буду ждать других советов!

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Чт авг 03, 2023 20:19:30

Инвертор тактового сигнала!

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Чт авг 03, 2023 20:23:01

Да, я пробовал брать тактовый сигнал не с прямого выхода Q, делителя, а с инвертного, ситуация сохраняется прежней.

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Чт авг 03, 2023 21:01:15

у Вас на картинке есть параметр tpd (задержка от соответствующего фронта на установку данных на шине - только после нее данные достоверны) по тексту у Вас о нем ни слова.
т.е. Вам надо не только удвоение частоты (захват чаще), но и фазовый сдвиг на этот самый tpd (для захвата).
или аппаратно вкарячивать n кол-во вентилей, или жужать двумя таймерами.

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Чт авг 03, 2023 21:50:27

dimaib писал(а):прерываний на этот случай нет.

dimaib писал(а):используется DCMI и DMA

Прерывания и не нужны. А если уж можно позволить себе прерывания, то всякие прочие интерфейсы и не требуются.

dimaib писал(а):Частота тактирования должна быть не менее 4МГц.

dimaib писал(а):данные требуется считывать с частотой не менее 4МГц

Это разные вещи. Что требуется всё-таки? А если 16-битные АЦП запустить в разрешении 12 бит, то всё равно мало скорости?

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Пт авг 04, 2023 00:48:55

Прерывания и не нужны. А если уж можно позволить себе прерывания, то всякие прочие интерфейсы и не требуются.

я говорил про прервывания только для отладки, что бы знать, где и когда что происходит.

Это разные вещи. Что требуется всё-таки? А если 16-битные АЦП запустить в разрешении 12 бит, то всё равно мало скорости?

Задача синхронизировать работу МК и внешнего вдухканального АЦП.

у Вас на картинке есть параметр tpd (задержка от соответствующего фронта на установку данных на шине - только после нее данные достоверны) по тексту у Вас о нем ни слова.
т.е. Вам надо не только удвоение частоты (захват чаще), но и фазовый сдвиг на этот самый tpd (для захвата).
или аппаратно вкарячивать n кол-во вентилей, или жужать двумя таймерами.


Да я понял, что требуется сместить тактовую частоту АЦП по фазе. Сейчас бьюсь над этим. Все частоты пока плавут.
Настроил дополнительный таймер в TOGGLE режиме, на частоту в 2 раза меньше. Но пока не получается синхронизировать.

Добавлено after 2 hours 50 minutes 24 seconds:
Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DMA
Пытался сделать следующее:
Выкинул делитель частоты на JK-триггере. Вместо него настроил отдельный таймер и для начала синхронизировал его с тактированием DCMI, потом разделил эту частоту на 2.
Добавил смещение одного сигнала относительно другого. И пытался подобрать это смещение.
Так же пытался инвертировать одно тактирование относительно другого.
Результаты остаются неизменными, массив заполняется рандомно. То каналом А, то каналом Б..
Изображение
На скриншоте показал, что даже на маленьких скоростх, это не работает. Так же видно, что частоты тактирования отличаются в два раза и есть смещение.
У кого то есть какие то идеи? :idea: :solder:
Спасибо, вам!

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Пт авг 04, 2023 02:10:34

У кого то есть какие то идеи?
Зачем все эти сложности с параллельными шинами и т.п.? Почему не использовать АЦП встроенный в МК?

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Пт авг 04, 2023 02:28:58

Зачем все эти сложности с параллельными шинами и т.п.? Почему не использовать АЦП встроенный в МК?

потому что в будущем планируется увеличение частоты семплирования, с которой не справляется внутренний АЦП

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Пт авг 04, 2023 02:34:53

потому что в будущем планируется увеличение частоты семплирования, с которой не справляется внутренний АЦП
Так выберите такой, который справится. Если уж нужна высокая частота сэмплирования, то однозначно никакими ухищрениями не сможете читать в реальном времени из него с такой скоростью, с какой внутренний АЦП позволяет. Он 100 очков вперёд даст внешнему. Так как там и шина 32-битная (а не дохлые 12 бит) и сопряжение с DMA нормально сделано, без костылей со сдвигами фазы как у вас.

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Пт авг 04, 2023 09:16:43

Возможно, вы правы! Если на я смогу подобрать контроллер 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
Но задача мультиплексирования выходов на одну шину перед ними не стояла, и не представляю как это отладить.
Я надеялся мне тут помогут с этим

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Пт авг 04, 2023 09:26:33

Тогда давайте актуальную схему. Подозреваю, что затык какой-то вовсе не великий.

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Пт авг 04, 2023 10:10:00

Но как обычно бывает, и думаю такое было у всех, партия готовых и спаянных плат лежит передомной на столе
Нет, так бывает только у тех, кто ставит телегу впереди лошади. У тех, у кого есть голова на плечах, такого не бывает, потому как сперва делается поиск наиболее оптимального решения задачи (и наиболее оптимального контроллера), потом - макетирование на отладочных платах. А изготовление своих плат - это когда уже все решения отработаны на макетках и точно работают.
У тех кто паяет партию плат(!) :facepalm: , а только потом начинает думать, как правило - или эта партия идёт в мусорную корзину; или долго и мучительно потом костылится, чтобы хоть как-то дотянуть до требований (чего обычно не получается, а остаётся "что получилось").

Странно, что вам даже не пришло в голову промакетировать своё решение. Уж не говоря о том чтобы просто поискать более подходящий МК, а не брать первый попавшийся под руку.

Я надеялся мне тут помогут с этим
Пока потеряны только деньги на изготовление плат, но ещё не потеряна куча времени, пойти к начальству, повиниться и свернуть на правильный путь. Вот правильное решение.

PS: Если уж нужна высокая частота сэмплирования, то почему не выбран LPC4370? Который к тому же и кратно дешевле вашего выбора? И запускается с полпинка. И схема простая. И таких характеристик по скорости сэмплирования как у него, на вашем паровозе даже близко не достичь.

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Пт авг 04, 2023 12:20:33

Подумал, что если тактировать АЦП частотой делённой на два, то DMA будет читать данные и в первой половине переода и во второй. Собрал делитель частоты на JK-тригере (что было под рукой), и подал на вход делителя частоты, сигнал с выхода ADC_CLKSRC (этот сигнал требуется для внешнего тактирования DCMI PIXCLK), а к выходу делителя, подключил тактирование каналов А, Б и MUX_SELECT.

Изображение
Данные принимаются по спаду DCMI_PIXCLK
Это значит, что JK-триггер должен переворачиваться по нарастанию DCMI_PIXCLK
Проверьте.
И он должен быть максимально быстрым (инверторы на входе нежелательны из-за задержки).

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Пт авг 04, 2023 19:59:15

Тогда давайте актуальную схему. Подозреваю, что затык какой-то вовсе не великий.

Да, конечно! не проблема! Я совместил всё на одном листе, поудалял всё лишнее.
Прикрепил и 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
Я ценю ваш опыт и точку зрения. Я согласен, что важно макетировать и проверять решения перед применением.
Возможно, я не сделал это ясным в своих предыдущих сообщениях, но я прошу конкретной помощи по конкретному вопросу.
Если у вас есть опыт или знания, которые могут помочь мне решить эту проблему, я был бы очень благодарен за это. Если нет, то зачем лить воду и устраивать бесполезную полемику?
Ситуация с вами напоминает общение на форуме:
Обычный пользователь>>Помогите, пожалуйста, я не могу запустить эту программу, что мне делать?
"Профессионал">>Выкинь комп!
Вложения
ad.pdf
(156.91 KiB) Скачиваний: 50

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Пт авг 04, 2023 23:15:36

До конца не додумал, но пока спать не ушёл напишу что понял. Для закрепления, так сказать.
В инструкции на АЦП написано, что
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.

Очевидно, это как раз желаемая ситуация. То есть за один период тактирования данные высовываются то одни, то другие. А интерфейс считывает только один раз за период, причём сразу по заднему фронту (по спаду). А уж успел там АЦП данные выставить или нет это уже его проблемы.

Re: stm32+AD9238. High-speed ADC. Каналы А и Б. Настройка DM

Пт авг 04, 2023 23:34:11

Очевидно, это как раз желаемая ситуация. То есть за один период тактирования данные высовываются то одни, то другие. А интерфейс считывает только один раз за период, причём сразу по заднему фронту (по спаду). А уж успел там АЦП данные выставить или нет это уже его проблемы.

Да, да.. имено поэтому пришлось использовать другой источник тактирования для АЦП и поделить его чатсоту на 2, что бы интерфейс считывал данные два раза за один период тактирования АЦП. Но синхронизировать это не получается.
Или я не улавливаю вашу мысль?
Ответить