由于工作中测试发现串口传输数据延时有点大,传输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 版权协议,转载请附上原文出处链接和本声明。