串口DMA配置错误笔记 —— 已解决

一、DMA发送

        1、配置问题

        2、发送问题

二、DMA接收

        1、配置问题

        2、接收问题


一、DMA发送

1、配置问题

        使用DMA发送时需要将DMA配置成内存到寄存器搬运关闭寄存器的地址增长,如果要搬运的多个字节就需要开启内存的地址增长

    /* 串口 */
    hdma_usart2_tx.Instance = DMA1_Channel3;
    hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_usart2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart2_tx.Init.MemInc = DMA_MINC_ENABLE;
    //!!! 设置成9数据位需要使用半字对齐 即每次增长2字节
    hdma_usart2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_usart2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_usart2_tx.Init.Mode = DMA_NORMAL;
    hdma_usart2_tx.Init.Priority = DMA_PRIORITY_LOW;
    HAL_DMA_Init(&hdma_usart2_tx);

        需要将DMA的通道连接到串口寄存器,一般来说所有DMA通道都可以连接串口寄存器,但部分芯片的DMA的部分通道可能不支持连接,需要查看用户手册。如果是HAL库,连接后还需要使用__HAL_LINKDMA将串口句柄和DMA句柄进行链接。


    HAL_DMA_ChannelMap(&hdma_usart2_tx, DMA_CHANNEL_MAP_USART2_WR);

    __HAL_LINKDMA(&huart2, hdmatx, hdma_usart2_tx);

        串口和DMA的时钟都不要忘记开启

    __HAL_RCC_USART2_CLK_ENABLE();
    __HAL_RCC_DMA1_CLK_ENABLE();

2、发送问题

        如果使用     HAL_UART_Transmit_DMA(&huart2,(uint8_t *)data,43);  进行发送需要确保发送完毕前data的内存没有被释放,DMA发送调用完后不会阻塞,如果函数结束后data的数据还没搬运完就会出错,最方便的办法就是将data设置为全局变量。

    uint16_t data[43];

        如果上一次的数据没有发送完却再次开启DMA发送会导致发送失败,即进入HAL_BUSY,建议开启DMA中断,在中断中调用会自动清除发送完毕标志位允许下一次传输

    void DMA1_Channel3_IRQHandler(void)
    {
        HAL_DMA_IRQHandler(&hdma_usart2_tx);
    }

二、DMA接收

1、配置问题

        需要配置成寄存器到内存,同样关闭寄存器增长开启内存增长

    //需要先开启DMA再开启串口
    hdma_usart1_rx.Instance = DMA1_Channel2;
    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_rx.Init.Mode = DMA_NORMAL;
    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
    HAL_DMA_Init(&hdma_usart1_rx);

2、接收问题

        进行DMA接收时最好不要到接收的内存中读取数据,如果需要读取数据要先关闭DMA接收

    //读取DMA
    HAL_UART_DMAStop(huart);

    //读取数据...

    //再次开启DMA
    HAL_UART_Receive_DMA(&huart1,rx_buf.buf,RX_BUF_MAX);

        开启DMA接收时如果串口数据寄存器DR里有数据DMA就会立即搬运一次,如果不想接收该数据可以开启DMA前先清空DR

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值