普通串口:
直接打开一个串口的异步功能
发送函数:
HAL_UART_Transmit(&huart5,buf,sizeof(buf),50);
//HAL_UART_Transmit(句柄,发送的内容,内容长度,允许的发送时间ms);
接收函数:(堵塞接收,在设定时间内都会访问串口数据)
HAL_UART_Receive(&huart5,buf,sizeof(buf),HAL_MAX_DELAY);
//HAL_UART_Receive(句柄,接收数组,接受数据长度,允许等待的时间);
//HAL_MAX_DELAY == 死等待发送
中断串口:
普通串口+打开全局中断
发送数据:
HAL_UART_Transmit_IT(&huart5,buf,sizeof(buf));
//HAL_UART_Transmit_IT(句柄,发送的数据,数据长度);
/*
用中断,所以较普通串口少了一个允许发送的时间
HAL_UART_Transmit(&huart5,buf,sizeof(buf),50);
*/
接收数据:(非堵塞接收,靠串口中断读取数据)
HAL_UART_Receive_IT(&huart5,buf,sizeof(buf));
//HAL_UART_Receive_IT(句柄,数据缓存,数据长度);
/*
用中断,所以较普通串口少了一个允许等待的时间
HAL_UART_Receive(&huart5,buf,sizeof(buf),HAL_MAX_DELAY);
*/
较普通串口新增功能:串口中断
(但是这个中断汇总了很多中断类型:发送完成中断、接收完成中断;所以需要使用HAL_UART_IRQHandler其内部的函数,而非直接这个外框)
串口读取完成回调函数,当串口接收到目标数据长度后,会执行这个函数。
需要在自己需要的串口数据处理函数中,重新编写这个函数的功能,来实现接受数据后的数据处理。
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_Transmit_IT(&huart5,buf,2);//返回接收的数据
/*
自己编写的串口数据处理代码
如:
if(buf[0] == 0xff) //帧头
{
if(buf[5] == 0xfa) //帧尾
}
*/
//重新打开串口接收
HAL_UART_Receive_IT(&huart5,buf,2);
}
使用举例:
但是这个中断需要接收到目标字符串长度才算完成一次接收,未达到则等待后续数据
DMA+串口空闲中断(ToIdle)发生时就是发送数据完成。
在中断的基础上添加TX和RX的DMA
使用的接收函数:
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
/*
句柄、数据接收数组、单次最大数据长度
*/
对应的回调函数:句柄、接收到的数据长度
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if(huart == &MyHuart)//判断是哪个串口进入的回调函数
{
HAL_UART_Transmit_DMA(&huart5,buf,Size);//Sizes是收到的数据长度
/*
自己编写的串口数据处理代码
如:
if(buf[0] == 0xff) //帧头
{
if(buf[5] == 0xfa) //帧尾
}
*/
//重新打开串口接收
HAL_UARTEx_ReceiveToIdle_DMA(&huart5,buf,sizeof(buf));
}
}
中断串口和DMA串口的区别:
特性 | 普通轮询(Polling) | 中断(IT) | DMA |
---|---|---|---|
原理 | CPU 不断查询标志位 | 数据到达后触发中断 | 硬件自动搬运数据,不占用 CPU |
CPU 占用 | 高(阻塞式等待) | 中(中断响应时间) | 低(仅初始化时占用) |
实时性 | 差(阻塞其他任务) | 高(及时响应) | 高(后台自动传输) |
适用场景 | 简单调试、单任务环境 | 中低速数据(如指令解析) | 高速数据(如摄像头、音频) |
函数示例 | HAL_UART_Transmit |
HAL_UART_Transmit_IT |
HAL_UART_Transmit_DMA |
接收函数示例 | HAL_UART_Receive |
HAL_UART_Receive_IT |
HAL_UART_Receive_DMA |
是否需要回调函数 | 否 | 是(如 HAL_UART_RxCpltCallback ) |
是(如 HAL_UART_RxCpltCallback ) |
空闲中断支持 | 不支持 | 不支持 | 支持(HAL_UARTEx_ReceiveToIdle_DMA ) |
硬件依赖 | 无 | 需启用 UART 中断 | 需配置 DMA 通道 |
总结:
特性 | 普通轮询(Polling) | 中断(IT) | DMA |
---|---|---|---|
工作原理 | CPU 阻塞等待数据收发完成 | 数据收发完成后触发中断回调 | 硬件自动搬运数据,空闲中断触发回调 |
函数示例(发送) | HAL_UART_Transmit(&huart, data, len, timeout) |
HAL_UART_Transmit_IT(&huart, data, len) |
HAL_UART_Transmit_DMA(&huart, data, len) |
函数示例(接收) | HAL_UART_Receive(&huart, data, len, timeout) |
HAL_UART_Receive_IT(&huart, data, len) |
HAL_UART_Receive_DMA(&huart, data, len) 或 HAL_UARTEx_ReceiveToIdle_DMA (推荐) |
CPU 占用 | 高(完全阻塞) | 中(中断响应时间) | 极低(仅初始化时占用) |
实时性 | 差 | 高 | 最高(后台自动传输) |
重启接收 | 不需要 | 需要(在回调中手动调用 HAL_UART_Receive_IT ) |
需要(在回调中调用 HAL_UARTEx_ReceiveToIdle_DMA ) |
中断配置 | 无 | 需开启 UART 全局中断(NVIC) | 需开启 UART 空闲中断 + DMA 中断 |
关闭半传输中断 | 无 | 无 | 需要(调用 __HAL_DMA_DISABLE_IT(&hdma, DMA_IT_HT) ) |
适用场景 | 单任务调试、简单指令 | 中低速数据(如协议解析) | 高速数据(如传感器流、图像传输) |