|
众所周知,STM32串口通讯,接收及发送都没有设计硬件FIFO,这对大部分程序员来说,算是一个硬伤。但实际上,由于STM32串口可以利用DMA收发,这样比固定16字节的FIFO更灵活。
在编写串口接收的bsp层代码时,同时启动DMA接收和空闲中断,就可以实现一个硬件接收缓冲,在空闲中断中,
实现数据从硬件接收缓冲的读取。
串口接收bsp层接收缓冲两层结构
--第一层FIFO硬件接收缓冲 (第一层硬件FIFO接收缓冲,利用DMA自动传输,不占用CPU时间,一般大小可设置为16-1024字节)
--第二层FIFO软件接收缓冲 (第二层软件FIFO接收缓冲,在DMA传输完毕中断中处理,缓冲可设置的比较大,一般是1024~8192字节)
但实际上,由于STM32串口可以利用DMA收发,这样比固定16字节的FIFO更灵活。
同时启动DMA接收和空闲中断,就可以实现一个硬件接收缓冲,空闲中断中,实现数据从硬件接收缓冲的读取。
在3至10Mbps串口通讯的情况下,只有这一个办法。逐个字符中断式接收来不及。
发送一般没有问题,这里主要说接收。波特率低的话,中断可以。波特率高的话,如果是5Mbps,2.2微秒需要接收一个11位串口字符,中断方式显然不现实。
HAL库的串口中断函数,并没有认真考虑DMA和空闲中断,非常不专业。
中断函数应该展开(高速收发仅打开发送完成中断和空闲中断),DMA中断应该跟根据用户定义存在别名。
没有空闲中断,应该算是HAL库不完善。
另外,接收完数据,不应该自以为是的关闭串口,应该由用户决定是否关闭。
HAL库串口空闲中断处理代码:
/* UART in mode Transmitter end --------------------------------------------*/
if(((isrflag & USART_SR_TC) != RESET) && ((crlits & USART_CR1_TCIE) != RESET))
{
UART_EndTransmit_IT(huart);
return;
}
/* UART in mode Receiver end -----------------------------------------------*/
if(((isrflags & USART_SR_IDLE) != RESET) && ((crlits & USART_CR1_IDLEIE) != RESET))
{
/* Clear the UART IDLE pending flag */
__HAL_UART_CLEAR_IDLEFLAG(huart);
return;
}
}
|
|