STM32UART三种收发模式基于HAL库

文章介绍了STM32中UART通信的三种模式:阻塞模式、中断模式和DMA模式。在阻塞模式下,发送和接收通过循环实现。中断模式下,发送和接收在特定事件(如半发送、接收完成)时触发中断回调。而DMA模式利用其计数功能实现不定长数据收发,并通过检测空闲中断来判断数据传输结束。
摘要由CSDN通过智能技术生成

2.1 阻塞模式

函数原型

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
    
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)

使用方法

    /* USER CODE BEGIN 2 */
    uint8_t buffer[] = {0};
    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1)
    {
        /* USER CODE END WHILE */
        HAL_UART_Receive(&huart1,buffer,1,0xFFFF);
        HAL_UART_Transmit(&huart1,buffer,1,0xFFFF);
        /* USER CODE BEGIN 3 */
    }

2.2 中断模式

函数原型:

HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size);

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

UART中断发送模式

发送一个字符进入一次中断

当发送一半或者发送完成可以使用中断回调函数处理中断事件

//中断服务函数
void USART1_IRQHandler(void)
{
	//HAL库公共中断服务函数,该函数调用有关中断的所有回调函数并清除中断标志位
	HAL_UART_IRQHandler(&huart1);
    
}
//回调函数都为弱定义,用户用哪个重写哪个
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    //当发送完成时进入该中断回调函数
    
    //在HAL库公共中断服务函数中关闭中断并清除标志位,需要重新打开中断
    HAL_UART_Transmit_IT(&huart1, (uint8_t *)pData, Size);
}

UART中断接收模式

当接收一半或者接收完毕可以使用中断回调函数处理中断事件

//中断服务函数
void USART1_IRQHandler(void)
{
	//HAL库公共中断服务函数,该函数调用有关中断的所有回调函数并清除中断标志位
	HAL_UART_IRQHandler(&huart1);
}
//回调函数都为弱定义,用户用哪个重写哪个
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    //当接收完成时进入该中断回调函数
    
    //在HAL库公共中断服务函数清除标志位,需要重新打开中断
    HAL_UART_Receive_IT(&huart1, (uint8_t *)pData, Size);
}

回调函数

__weak void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart);
__weak void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart);
__weak void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart);
__weak void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart);//错误回调
__weak void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);//接收一半
__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);//接收完成回调函数
__weak void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);//发送一半
__weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);//发送完成回调
__weak void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size);//接收事件回调

2.3 DMA不定长数据收发

DMA与中断的使用方式相同

与中断不同的是,DMA具有计数的特点,可以利用这一特点实现DMA不定长数据的收发,具体实现如下:

函数原型:

HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)
HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

发送完成中断与接收完成中断是收发指定数量的字节后进入中断,不能收发随机字节数据。

解决办法:可以通过判断空闲中断标志位来确定数据是否收发完毕,进入空闲中断处理数据。

//打开空闲中断
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);

//打开DMA接收
HAL_UART_Receive_DMA(&huart1,(uint8_t *data, size);
//当产生空闲中断的时候会进入中断服务函数
void USART1_IRQHandler(void)
{
    //但是没有空闲中断的中断回调函数,所以需要通过判断空闲中断标志位的方式
    if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) != RESET)
    {
        //清除中断标志位
        __HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_IDLE);
        //关闭DMA
        HAL_UART_DMAStop(&huart1);
        //获取指定长度的数据
        uint8_t len = MAXSIZE - __HAL_DMA_GET_COUNTER(huart3.hdmarx);
        /* 处理指定长度的数据 */
        ...
        //重新打开DMA接收
        HAL_UART_Receive_DMA(&huart1,(uint8_t*)data,size);
    }
	//HAL库公共中断服务函数,该函数调用有关中断的所有回调函数并清除中断标志位
	HAL_UART_IRQHandler(&huart1);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

指针到处飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值