Jump to content

    

STM32 HAL UART+DMA

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

Прошу помочь разобраться с использованием связки 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 – нормальный.

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

Share this post


Link to post
Share on other sites
1 hour ago, lomy said:

рмальный.

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

Нет никакой проблемы. Вы считали 4 байта, снова проинитили ДМА вызвав HAL_UART_Receive_DMA(…), указатель начала области памяти куда дма кладет данные снова встал на начало массива куда и занеслись лишние байты из посылки

Share this post


Link to post
Share on other sites

В UART у STM есть очень удобное прерывание по событию idle. Оно возникает если после очередного байта была пауза кажется в 3 символа.

Делаете на прием два буфера для UART. Включаете DMA с прерыванием по idle. В прерывании переключаете буфера. В основной программе анализируете что там у вас в буфере.

Share this post


Link to post
Share on other sites

Спасибо, Omen и uriy. Попробую разобраться с прерыванием по idle.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this