LL库串口+DMA

  • Post author:
  • Post category:其他


由于工作中测试发现串口传输数据延时有点大,传输35个字节,115200,理论值应该在3ms左右,然而实际测试却有40ms,所以首先想到会不会是hal库执行效率低得原因,所以采用LL库,但是LL库的资料少之又少啊!自己做个记录。

使用cubemx可以直接生产LL库的代码(我的工程里是hal库和LL库混用的),LL库串口硬件初始化部分会自动生成,但是传输地址及DMA传输长度并没有设置,需要手动设置。设置步骤可参考标准库设置

初始化代码使用DMA+IDLE接收数据,

void bsp_usart_init()
{

   
    LL_DMA_SetMemoryAddress(DMA1, LL_DMA_STREAM_5, (uint32_t)bsp_usart.aRxBuffer);
    LL_DMA_SetPeriphAddress(DMA1, LL_DMA_STREAM_5, (uint32_t)(&USART2->DR));
    LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_5, bsp_usart.buf_len);
    LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_5);

    LL_DMA_SetMemoryAddress(DMA1, LL_DMA_STREAM_6, (uint32_t)bsp_usart.aTxBuffer);
    LL_DMA_SetPeriphAddress(DMA1, LL_DMA_STREAM_6, (uint32_t)(&USART2->DR));
    LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_6, 0);

    //LL_USART_EnableIT_TC(USART2);
    //LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_6);

    LL_USART_EnableIT_IDLE(USART2);
    LL_USART_EnableDMAReq_RX(USART2);
    LL_USART_EnableDMAReq_TX(USART2);
}

中断接收函数

void bsp_usart_IRQ()
{

    if (LL_USART_IsActiveFlag_IDLE(USART2))
    {
        LL_DMA_DisableStream(DMA1, LL_DMA_STREAM_5); //¹Ø±ÕDMA

        int cnt = LL_DMA_GetDataLength(DMA1, LL_DMA_STREAM_5);
        bsp_usart.rx_len = bsp_usart.buf_len - cnt; //总计数减去未传输的数据个数,得到已经接收的数据个数
        bsp_usart.recv_end_flag = 1;                // 接受完成标志位置1

        LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_5, USART_BUF_MAX_LEN);
        LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_5);
        LL_USART_ClearFlag_IDLE(USART2);
    }
    else if (LL_USART_IsActiveFlag_TC(USART2))
    {
        LL_USART_DisableIT_TC(USART2);
        LL_DMA_DisableStream(DMA1, LL_DMA_STREAM_6);
    }
}

DMA发送函数

uint8_t bsp_usart_send(uint8_t *data, uint32_t len)
{

    while (LL_USART_IsActiveFlag_TC(USART2) == 0)
    {
		
    }
    LL_DMA_ClearFlag_TC6(DMA1);

    memcpy(bsp_usart.aTxBuffer, data, len);

    LL_DMA_DisableStream(DMA1, LL_DMA_STREAM_6);
    LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_6, len);
    LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_6);

    return 0;

}

在使用LL库时,串口接收还比较容易实现,和hal库除了初始化设置DMA地址外,其他大同小异。但是DMA发送却没有那么顺利,第一次调用发送函数时,是可以正常接收到的,但是后面就没有了。

最后发现是没有清除DMA发送完成中断,使用LL库特别要注意中断及标志位的清除



版权声明:本文为for_dream1205原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。