lomy 0 8 ноября, 2018 Опубликовано 8 ноября, 2018 · Жалоба Здравствуйте, уважаемые коллеги. Прошу помочь разобраться с использованием связки 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 – нормальный. Может кто-то сталкивался с такой проблемой и может объяснить, почему так происходит? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
0men 2 8 ноября, 2018 Опубликовано 8 ноября, 2018 · Жалоба 1 hour ago, lomy said: рмальный. Может кто-то сталкивался с такой проблемой и может объяснить, почему так происходит? Нет никакой проблемы. Вы считали 4 байта, снова проинитили ДМА вызвав HAL_UART_Receive_DMA(…), указатель начала области памяти куда дма кладет данные снова встал на начало массива куда и занеслись лишние байты из посылки Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
uriy 5 9 ноября, 2018 Опубликовано 9 ноября, 2018 · Жалоба В UART у STM есть очень удобное прерывание по событию idle. Оно возникает если после очередного байта была пауза кажется в 3 символа. Делаете на прием два буфера для UART. Включаете DMA с прерыванием по idle. В прерывании переключаете буфера. В основной программе анализируете что там у вас в буфере. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lomy 0 9 ноября, 2018 Опубликовано 9 ноября, 2018 · Жалоба Спасибо, Omen и uriy. Попробую разобраться с прерыванием по idle. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться