Перейти к содержанию
    

lomy

Участник
  • Постов

    20
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные lomy


  1. Проблема решена. Эта ситуация описана в Reference manual -> ADC -> Interleaved mode -> Dual ADC mode -> Note:

    Спойлер

    If the conversion sequence is interrupted (for instance when DMA end of transfer occurs),
    the multi-ADC sequencer must be reset by configuring it in independent mode first (bits
    DUAL[4:0] = 00000) before reprogramming the interleaved mode.
    Аналогично для Triple ADC mode.

    Соответственно перед повторным запуском ADC нужно сделать так:

              ADC->CCR &= ~(ADC_CCR_MULTI);
              ADC->CCR |= ADC_DUALMODE_INTERL;
              ADC->CCR &= ~(ADC_CCR_DMA);
              ADC->CCR |= ADC_DMAACCESSMODE_2;

    Решение нашел здесь: https://community.st.com/t5/stm32-mcus-products/adc-in-dual-interleaved-mode-with-normal-dma-buffer/td-p/279239

  2. 1 час назад, HardEgor сказал:

    А отладчиком пробовали пользоваться, что бы посмотреть в каком он состоянии? Он циклится или зависает?

    Из странностей в отладчике я вижу, что ADC2 выставляет флаг переполнения OVR, очевидно это происходит по окончании преобразования, т.к. данные идут без потерь, ADC/DMA не останавливаются пока не заполнят весь массив. Но т.к. перед повторным запуском используется

    HAL_ADCEx_MultiModeStop_DMA(&hadc1);
    
    HAL_ADC_Stop(&hadc2);

    то все флаги ошибок обнуляются, в отладчике все биты при первом и повторном запуске ADC и DMA одинаковы.

  3. Добрый день! Столкнулся с некорректным поведением ADC/DMA  в контроллере STM32F407, судя по перерытым мною форумам, проблема не только этого камня. Если использовать ADC с DMA  в режиме Dual или Triple interleaved mode то все корректно срабатывает только один раз после старта контроллера в дальнейшем можно сколько угодно раз перезапускать ADC данных с него не будет. Я уже попробовал все, что смог найти на просторах интерентов, результата никого. Кто-нибудь поделитесь опытом использования этого режима АЦП, как вы его правильно останавливаете и запускаете.

    Упрощенный код для Dual:

    Spoiler
    If(нажата кнопка 1)
    
    {
    
    HAL_ADC_Start(&hadc2);                                
    HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t*)&adc_buf, BUFSIZE);
    }
    
    If(нажата кнопка 2)
    
    {
    
    HAL_ADCEx_MultiModeStop_DMA(&hadc1);
    
    HAL_ADC_Stop(&hadc2);
    
    // Обработка данных
    
    }
    
    Все это работает только один раз.
    
    Пробовал перед стартом переинициализировать периферию:
    
    HAL_DMA_Init(&hdma_adc1);
    
    HAL_ADC_Init(&hadc1);
    
    HAL_ADC_Init(&hadc2);
    
    Такое решение встречал на англоязычных форумах:
    
    CLEAR_BIT(hadc1.State, HAL_ADC_STATE_ERROR_DMA);
    
    После остановки АЦП так  делал:
    
    HAL_DMA_Abort(&hdma_adc1);

    Конечно, встречал записи, что  это проблемы HAL, но повторюсь один раз все работает корректно. И размер буфера значения не имеет, при первом запуске ADC выдаст установленное количество данных и они будет корректные, никаких потерь, проверял и в Dual и в Triple mode.

  4. Всем привет! Есть осциллограф TDS 2014C многие годы был подключен к ПК по USB. На ПК была установлена родная программа от Tektronix «OpenChoice Desktop», основное предназначение делать скрины экрана осциллографа и сохранять их на ПК. С какого-то момента перестала работать, причина не известна. Программа видит осциллограф, может его идентифицировать, но не может подключиться выкидывает сообщение «Unknown or unexpected system error. Please verify the instrument connections or the installation». Шнурок USB менял, программу переустанавливал, в том числе устанавливал более новую версию, результата никакого. Может кто сталкивался? Поиски в интернете ничего не дают, печаль (

  5. 1 час назад, scifi сказал:

    Очевидно, нужно сначала 1) COMP_CSR_EN, затем 2) задержка на переходные процессы, затем 3) сконфигурировать 57 ногу как Alternate Function.

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

  6. Здравствуйте!

    Вопрос по использованию аналогового компаратора. Микроконтроллер STM32L476, периферия COMP2. В компараторе задействован Input+ соответственно на него подается аналоговый сигнал, Input- на нем установлено ¾ Internal VRef и включен External Output, в моем случае это 57 нога контроллера на нее выводится сигнал полученный с компаратора. Инициализация MX_COMP2_Init(); проходит нормально. Столкнулся с тем, что при старте компаратора HAL_COMP_Start(&hcomp2); он кратковременно срабатывает на время 40 мкс., выдает высокий потенциал. Это происходит только один раз при старте, дальше он работает абсолютно корректно, но если его остановить HAL_COMP_Stop(&hcomp2); и запустить заново, то при старте он опять сработает. Время всегда одинаковое 40 мкс. При работе использую библиотеку HAL, с помощью отладчика нашел место, где переключается порт:

    /* Enable the selected comparator */

    SET_BIT(hcomp->Instance->CSR, COMP_CSR_EN);

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

    Заранее спасибо.

    Comp.jpg

  7. Здравствуйте, уважаемые коллеги.

    Прошу помочь разобраться с использованием связки UART+DMA на прием, в частности интересует работа функции HAL_UART_Receive_DMA(…). Сразу оговорюсь, что я перечитал много постов по этой теме на большинстве известных форумов и многое оттуда почерпнул. Теперь к сути: в большом проекте есть кусок, который отвечает за связь между двумя контроллерами, один из которых раз в несколько миллисекунд отправляет короткое сообщение (не более 20 байт) другому контроллеру сообщение все время одинакового размера. UART включен на прием, DMA работает в нормальном режиме (не в циклическом). В main вызываю HAL_UART_Receive_DMA(&huart5,(uint8_t*) mc_mes, 4);  //4 байта взято просто для эксперимента

    В бесконечном цикле мониторю hdma_uart5_rx.State

                                   if (hdma_uart5_rx.State == HAL_DMA_STATE_READY)

                                   {

                                                   HAL_UART_Receive_DMA(&huart5,(uint8_t*) mc_mes, 4);

                                                   hdma_uart5_rx.State = HAL_DMA_STATE_BUSY;

                                   }

    Вот собственно и весь упрощенный код.

    Как я понимаю работу этой функции, поправьте меня, если я не прав:

    Вызывая функцию HAL_UART_Receive_DMA(…) мы передаем ей ожидаемое кол-во байт для приема. Этот параметр устанавливает внутренний счетчик DMA, (регистр NDT). Для каждого байта, который он получает, счетчик уменьшается на единицу, пока не достигнет нуля. Когда счетчик становится равен нулю происходит передача данных. В этот момент мы попадаем в условие (hdma_usart2_rx.State==HAL_DMA_STATE_READY_MEM0), где мы опять вызываем  функцию HAL_UART_Receive_DMA(…).

    Проблема: если мы намеренно посылаем пакет большего размера чем у нас заявлено, например, вместо четырех байт отправим пять, то массив принятых данных сбивается, «лишние» эл-ты заносятся в массив mc_mes [] на первые места (так как будто DMA работает в циклическом режиме!). А этого быть не должно т.к. у нас режим работы DMA – нормальный.

    Может кто-то сталкивался с такой проблемой и может объяснить, почему так происходит?

  8. Один таймер с двумя каналами и один элемент "исключающее или" в малом корпусе.

    В предыдущем варианте устройства, было сделано на логике, сейчас была поставлена задача, все оптимизировать, если что-то может делать контроллер то логику исключить.

  9. Если не нужен дедтайм между каналами, то можно решить задачу на одном таймере и DMA. Первый сигнал представляется в виде двух последовательных широтно модулированных импульсов с различным периодом и скважностью. Второй сигнал аналогично, но в противоположной полярности, и с нулевой скважностью в одном такте из двух. Соотвественно настраиваем ШИМ режимы, и загрузку теневых ARR, CCR1, CCR2 через DMA burst при переполнении счётчика. DMA в кольцевом режиме на 6 слов по 16 бит.

    Да нечто подобное подробно описано в Application note, который выложил A.Lex на первой страницы этого обсуждения глава называется: Arbitrary waveform generation using timer DMA-burst feature (стр. 45). Я не смог реализовать такую штуку для двух каналов одного таймера, но это скорее от недостатка опыта, думаю Ваша идея пригодится кому-то более опытному.

  10. А почему так громоздко? На dual-SPI не получилось?

    Просто с таймерами я уже некоторое время провозился и более менее разобрался как их настраивать. А с dual-SPI мне нужно еще нужно разобраться, но я попробую. Если все получится то отпишусь в этой теме.

     

     

  11. Задача решена на связке нескольких таймеров. За основу взяты три таймера TIM3, TIM2 и TIM1.

    TIM3 отсчитывает длинные периоды по 15 мс по окончании счета тактирует TIM2 и TIM1 по ITR2.

    TIM2 настроен как Slave, своим первым каналом он управляет портом МК в режиме PWM Generation. Обязательно включить One Pulse Mode.

    TIM1 тоже настроен как Slave, и своим первым каналом он управляет портом МК в режиме PWM Generation. Обязательно включить One Pulse Mode и задать счет повторений Repetition Counter ( по моему эта функция есть только у Advanced-control timers).

    Собственно все работает самостоятельно, без каких либо пользовательских прерываний. Поэтому синхронизация импульсов получается идеальная (видно на осциллограмме). Частоту можно задавать изменением тактирования частоты таймеров или изменением длительностей импульсов PWM.

    Спасибо всем кто откликнулся на обсуждение. Если будут вопросы с удовольствием отвечу.

     

    IMG_20180323_164425.jpg

     

  12. Если синхронности не дает, то не буду тратить на это время.

     

    К тому моменту как я обратился на форум, я перерыл много информации в интернете. У меня сложилось такое ощущение, что это задача имеет решение с помощью двух таймеров (один ведомый другой ведущий) и периферии которой они могут управлять напрямую. Наверное я заблуждался.

  13. Спасибо за ответ.

    Я активно использовал этот Application note, и научился его помощью генерировать пачки импульсов. Но я не смог решить своей задачи. Если у Вас будет время взгляните, пожалуйста, на диаграмму стр. 68. Там видно, что в инверсном канале остается «лишний импульс». Возможно ли сделать то, что там называется “Commutation update to inactive mode” на один импульс раньше?

  14. Здравствуйте, уважаемые коллеги.

    Прошу помочь с решением задачи. Сразу оговорюсь, что я инженер-схематехник, и практического опыта программирования микроконтроллеров у меня нет. Задача такая, используя микроконтроллер STM32L476RG (можно другой серии, главное STM32) нужно генерировать сигнал на двух портах микроконтроллера как на прикрепленном изображении. Сигналы должны быть обязательно синхронизированы.

    IMG_20180319_152743.jpg

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

    Способ 1: активировал два таймера (ведущий и ведомый), один отсчитывает длинные периоды по 15 мс и тактирует второй, который в режиме one pulse генерирует прямой и комплементарный сигнал, проблема состоит в том, что в инверсном канале, когда таймер 2 «бездействует» устанавливается 1 (это правильно по логике работы инверсного канала, но не удовлетворяет решению)

    IMG_20180319_153312.jpg

    Способ 2: активировал два таймера, один отсчитывает длинные периоды по 15 мс второй считает короткие полупериоды 0,5 мкс порты переключаю вручную в обработчике прерываний, получается, довольно криво. Синхронизировать два канала не удается (сгенерированные импульсы смещены друг относительно друга)

    Способ 3: активировал 3 таймера один отсчитывает длинные периоды по 15 мс и тактирует второй, который генерирует два импульса и тактирует третий таймер, который генерирует одиночный импульс, проблема в том, что все это почему-то работает только с тактовой частотой контроллера 80 МГц, стоит только начать настраивать частоты тактирования контроллера или самих таймеров как все разваливается.

    Если у кого то есть идеи или готовое решение, пожалуйста, ответьте.

     

×
×
  • Создать...