UART_DMA_DBUS-DEMO

UART_DMA_DBUS

UART

  • 打开UART或者USART-选择Asynchronous

  • Asynchronous - 异步通信

    Synchronous - 同步通信

  • 打开Parameter Settings选项卡

  • 分别配置波特率、数据位长度、校验位、停止位

  • 数据方向根据需求配置

  • 过采样一般默认16

  • NVIC Setting选项卡中打开串口中断-根据需求自行开启

  • DMA Setting-Add-一般默认即可

  • 优先级根据需求调整

  • GPIO Setting-检查IO口是否选择正确

UART基础配置完成


DMA

  • DMA配置可以使用HAL库函数直接配置
  • 也可以自己仿照HAL库函数进行配置
  • 此处采用自己配置的方式配置DMA

DAM_init

void DMA_init(void)
{
    //enable the DMA transfer for the receiver request
    SET_BIT(huart3.Instance->CR3, USART_CR3_DMAR);
    //enalbe idle interrupt
    __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
    //disable DMA
    __HAL_DMA_DISABLE(&hdma_usart3_rx);
    while(hdma_usart3_rx.Instance->CR & DMA_SxCR_EN)
    {
        __HAL_DMA_DISABLE(&hdma_usart3_rx);
    }
    hdma_usart3_rx.Instance->PAR = (uint32_t) & (USART3->DR);
    //memory buffer 1
    hdma_usart3_rx.Instance->M0AR = (uint32_t)(sbus_rx_buf[0]);
    //memory buffer 2
    hdma_usart3_rx.Instance->M1AR = (uint32_t)(sbus_rx_buf[1]);
    //data length
    hdma_usart3_rx.Instance->NDTR = SBUS_RX_BUF_NUM;
    //enable double memory buffer
    SET_BIT(hdma_usart3_rx.Instance->CR, DMA_SxCR_DBM);
    //enable DMA
    __HAL_DMA_ENABLE(&hdma_usart3_rx);

}

注:此处需要更改的关键字如下:

huart3 — 对应串口句柄

hdma_usart3_rx — 对应串口DMA接收句柄

USART3 — 对应串口句柄

sbus_rx_buf[0] — 对应DMA第一缓冲区

sbus_rx_buf[1] — 对应DMA第二缓冲区

DMA_use

void DMA_receive(void)
{
	if(huart3.Instance->SR & UART_FLAG_RXNE)
    {
        __HAL_UART_CLEAR_PEFLAG(&huart3);
    }
    else if(USART3->SR & UART_FLAG_IDLE)
    {
        static uint16_t this_time_rx_len = 0;
        __HAL_UART_CLEAR_PEFLAG(&huart3);
        if ((hdma_usart3_rx.Instance->CR & DMA_SxCR_CT) == RESET)
        {
            /* Current memory buffer used is Memory 0 */
            //disable DMA
            __HAL_DMA_DISABLE(&hdma_usart3_rx);
            //get receive data length, length = set_data_length - remain_length
            this_time_rx_len = SBUS_RX_BUF_NUM - hdma_usart3_rx.Instance->NDTR;
            //reset set_data_lenght
            hdma_usart3_rx.Instance->NDTR = SBUS_RX_BUF_NUM;
            //set memory buffer 1
            hdma_usart3_rx.Instance->CR |= DMA_SxCR_CT;
            //enable DMA
            __HAL_DMA_ENABLE(&hdma_usart3_rx);
            if(this_time_rx_len == RC_FRAME_LENGTH)
            {
               sbus_to_rc(sbus_rx_buf[0], &rc);
            }
        }
        else
        {
            /* Current memory buffer used is Memory 1 */
            //disable DMA
            __HAL_DMA_DISABLE(&hdma_usart3_rx);
            //get receive data length, length = set_data_length - remain_length
            this_time_rx_len = SBUS_RX_BUF_NUM - hdma_usart3_rx.Instance->NDTR;
            //reset set_data_lenght
            hdma_usart3_rx.Instance->NDTR = SBUS_RX_BUF_NUM;
            //set memory buffer 0
            DMA1_Stream1->CR &= ~(DMA_SxCR_CT);
            //enable DMA
            __HAL_DMA_ENABLE(&hdma_usart3_rx);
            if(this_time_rx_len == RC_FRAME_LENGTH)
            {
                sbus_to_rc(sbus_rx_buf[1], &rc);
            }
        }
    }
}

注:此处需要更改的关键字如下:

huart3 — 对应串口句柄

hdma_usart3_rx — 对应串口DMA接收句柄

USART3 — 对应串口句柄

sbus_rx_buf[0] — 对应DMA第一缓冲区

sbus_rx_buf[1] — 对应DMA第二缓冲区

SBUS_RX_BUF_NUM — DMA缓冲区给的空间长度

RC_FRAME_LENGTH — DMA接收到的目标数据长度

sbus_to_rc — 处理DMA接收到的数据的函数

DMA1_Stream1 — 对应的DMA数据流

最后需要在串口回调函数里调用 - DMA_receive()

eg: - 此处以串口3的回调函数为例

void USART3_IRQHandler(void)
{
  /* USER CODE BEGIN USART3_IRQn 0 */
	DMA_receive();
  /* USER CODE END USART3_IRQn 0 */
  HAL_UART_IRQHandler(&huart3);
  /* USER CODE BEGIN USART3_IRQn 1 */
  /* USER CODE END USART3_IRQn 1 */
}

对DMA的理解

DMA_init()

  • 使能DMA串口接收
  • 使能串口空闲中断
  • 先暂时关闭DMA,以便对DMA进行配置
  • 配置DMA外设地址 - 此处用于串口接收,所以配置为串口的DR数据寄存器
  • 配置DMA第一缓冲区地址
  • 配置DMA第二缓冲区地址
  • 配置DMA数据长度 - 此处一般配置为实际接收数据的两倍
  • 使能双缓冲区配置
  • 使能DMA - DMA配置完成后打开DMA

DMA_use

  • 如果接收到数据并且串口有空闲中断触发
  • 先关闭DMA
  • 获取这一次接收到的数据长度
  • 重新设定下一次接收的数据长度
  • 重新设定下一次接收的缓冲器的地址
  • 打开DMA-使能DMA
  • 如果这一次接收到的数据长度等于我DMA接收目标数据长度
  • 则对DMA接收到的数据进行解析处理 - sbus_to_rc ()
  • 下一次就使用另外一个缓冲区进行接收
  • 最后在串口中断回调函数里调用就可以

DBUS

在串口前面加一个反相器

UART_DMA_DBUS-DEMO_第1张图片




你可能感兴趣的:(嵌入式(学习笔记),stm32,物联网)