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);
}