- HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
参数:
huart: 指向串口结构体(通过STM32CubeMX软件配置串口时会生成,包含串口通信相关的信息)的指针。
pData: 指向发送数据块的指针
Size: 发送数据的数量
Timeout: 超时周期
返回值:HAL status:HAL_OK ,HAL_ERROR,HAL_BUSY ,HAL_TIMEOUT
接收函数:
- HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
参数:
huart: 指向串口结构体的指针。
pData: 指向接收数据块的指针
Size: 接收数据的数量
Timeout: 超时周期
返回值:HAL status,HAL_OK ,HAL_ERROR,HAL_BUSY ,HAL_TIMEOUT
必须在指定的时间内接收到指定数量的数据才会返回HAL_OK。
中断模式: 非堵塞模式。和UART相关的中断:发生完成中断,结束中断和错误中断。
发送函数: 用于开启中断发送
- HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
参数:
huart: 指向串口结构体的指针。
pData: 指向发送数据块的指针
Size: 发送数据的数量
返回值:HAL status:HAL_OK ,HAL_ERROR,HAL_BUSY
接收函数:用于开启中断接收
- HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
参数:
huart: 指向串口结构体的指针。
pData: 指向接收数据块的指针
Size: 接收数据的数量
返回值:HAL status,HAL_OK ,HAL_ERROR,HAL_BUSY ,HAL_TIMEOUT
必须接收到指定数量的数据才会触发中断。
相关的回调函数:
HAL_UART_TxCpltCallback():发送完成后,通过中断处理函数调用。
HAL_UART_RxCpltCallback():接收完成后,通过中断处理函数调用。
HAL_UART_ErrorCallback():传输过程中出现错误时,通过中断处理函数调用。
可以在回调函数里定制自己的代码。
DMA模式:非堵塞模式。
发送函数: 用于开启DMA发送
- HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
参数:
huart: 指向串口结构体的指针。
pData: 指向发送数据块的指针
Size: 发送数据的数量
返回值:HAL status,HAL_OK ,HAL_ERROR,HAL_BUSY
接收函数:用于开启DMA接收
- HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
参数:
huart: 指向串口结构体的指针。
pData: 指向接收数据块的指针
Size: 接收数据的数量
返回值:HAL status,HAL_OK ,HAL_ERROR,HAL_BUSY ,HAL_TIMEOUT
必须接收到指定数量的数据才会完成一次DMA传输。
相关的回调函数(使用回调函数需要开启串口中断):
HAL_UART_TxHalfCpltCallback():一半数据(half transfer)发送完成后,通过中断处理函数调用。
HAL_UART_TxCpltCallback():发送完成后,通过中断处理函数调用。
HAL_UART_RxHalfCpltCallback():一半数据(half transfer)接收完成后,通过中断处理函数调用。
HAL_UART_RxCpltCallback():接收完成后,通过中断处理函数调用。
HAL_UART_ErrorCallback():传输过程中出现错误时,通过中断处理函数调用。
可以在回调函数里定制自己的代码。
暂停DMA传输:
- HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart)
恢复DMA传输:
- HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart)
停止DMA传输:
- HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart)
参数:huart: 指向串口结构体的指针。
返回值:HAL status,HAL_OK
下面通过简单的例子说明:
发板的USART3使用的是PB10和PB11引脚,但是使能USART3的时候默认引脚是PC10和PC11。因此需要先配置PB10和PB11引脚,在使能USART。相关的电路图如下:
轮询模式:
在STM32CubeMX软件中,分别配置PB10和PB11为串口收发,接着使能USART3,最后配置串口通信相关的参数:
生成MDK工程并打开,在main.c文件中,定义全局变量用于收发:
- uint8_t aTxBuffer[] = "** UART__ComPolling ** \r\n";
- uint8_t aRxBuffer[32];
在主函数的while循环之前,发送一个字符串,如果发送失败,点亮LED:
- HAL_GPIO_WritePin(GPIOG,GPIO_PIN_6,GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOD,GPIO_PIN_4,GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOD,GPIO_PIN_5,GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOK,GPIO_PIN_3,GPIO_PIN_SET);
- if(HAL_UART_Transmit(&huart3,(uint8_t *)aTxBuffer,32,5000)!= HAL_OK)
- {
- HAL_GPIO_WritePin(GPIOD,GPIO_PIN_4,GPIO_PIN_RESET);
- }
在while循环中,等待接收到指定数量的字符,然后将接收的字符发送出去,超时时间设置为1秒(单位为ms):
- while(HAL_UART_Receive(&huart3, (uint8_t *)aRxBuffer, 5, 1000) != HAL_OK)
- {
- HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_5);
- }
- if(HAL_UART_Transmit(&huart3,(uint8_t *)aRxBuffer,5,1000) == HAL_OK)
- {
- HAL_GPIO_TogglePin(GPIOG,GPIO_PIN_6);
- }
- HAL_Delay(1000);
编译下载,使用串口调试助手,调试过程如下:
中断模式:
在上面配置的基础上,使能串口中断,并配置优先级,也可以改变优先级分组:
在生成的MDK工程中,定义全局变量用于收发:
- uint8_t aTxBuffer[] = "** UART__IT ** \r\n";
- uint8_t aRxBuffer[32];
- uint8_t Rx_flag = 0;
通过Rx_flag控制发送接收的数据。在主函数的while循环之前开启发送和接收中断:
- HAL_GPIO_WritePin(GPIOG,GPIO_PIN_6,GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOD,GPIO_PIN_4,GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOD,GPIO_PIN_5,GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOK,GPIO_PIN_3,GPIO_PIN_SET);
-
- HAL_UART_Transmit_IT(&huart3,(uint8_t *)aTxBuffer,32);
- HAL_UART_Receive_IT(&huart3,(uint8_t *)aRxBuffer,12);
在while循环中将接收的数据发送出去:
- if(Rx_flag == 1)
- {
- HAL_UART_Transmit_IT(&huart3,(uint8_t *)aRxBuffer,32);
- Rx_flag = 0;
- }
在usart.c文件中声明外部变量:
- extern uint8_t aRxBuffer[32];
- extern uint8_t Rx_flag;
加入收发回调函数,在接收回调函数里将Rx_flag置1控制发送,并在此开始中断接收:
- void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle)
- {
- HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_4);
- }
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
- {
- Rx_flag = 1;
- HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_5);
- HAL_UART_Receive_IT(&huart3,(uint8_t *)aRxBuffer,12);
- }
编译下载,使用串口调试助手,调试过程如下:
DMA模式:
在上面配置的基础上,使能DMA,并为发送和接收选择DMA通道:
在生成的MDK工程中定义如下全局变量用于收发:
- uint8_t aTxBuffer[] = "** UART__DMA ** \r\n";
- uint8_t aRxBuffer[32];
- uint8_t Rx_flag = 0;
通过Rx_flag控制发送接收的数据。在主函数的while循环之前开启DMA发送和接收:
- HAL_GPIO_WritePin(GPIOG,GPIO_PIN_6,GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOD,GPIO_PIN_4,GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOD,GPIO_PIN_5,GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOK,GPIO_PIN_3,GPIO_PIN_SET);
- HAL_UART_Transmit_DMA(&huart3,(uint8_t *)aTxBuffer,32);
- HAL_UART_Receive_DMA(&huart3,(uint8_t *)aRxBuffer,12);
在while循环中将接收的数据发送出去:
- if(Rx_flag == 1)
- {
- HAL_UART_Transmit_DMA(&huart3,(uint8_t *)aRxBuffer,32);
- Rx_flag = 0;
- }
- if(Rx_flag == 2)
- {
- HAL_GPIO_TogglePin(GPIOG,GPIO_PIN_6);
- Rx_flag = 0;
- }
在usart.c文件中声明外部变量:
- extern uint8_t aRxBuffer[32];
- extern uint8_t Rx_flag;
加入收发回调函数,在接收回调函数里将Rx_flag置1控制发送,并在此开始中断接收,通过控制LED简单的验证发送和接收一半数据的回调函数:
- void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle)
- {
- HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_4);
- }
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
- {
- Rx_flag = 1;
- HAL_UART_Receive_DMA(&huart3,(uint8_t *)aRxBuffer,12);
- }
- void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)
- {
- HAL_GPIO_TogglePin(GPIOK,GPIO_PIN_3);
- }
- void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
- {
- Rx_flag = 2;
- }
编译下载,使用串口调试助手,调试过程如下:
最后,关于串口重定向可以参考一下代码,需要包含stdio.h,可以替换成中断或DMA模式,这样就可以使用printf和scanf函数:
- int fputc(int ch,FILE *fp)
- {
- HAL_UART_Transmit(&huart3,(uint8_t *)&ch,1,5000);
- return ch;
- }
- int fgetc(FILE *fp)
- {
- uint8_t ch;
- HAL_UART_Receive(&huart3,(uint8_t *)ch,1,5000);
- return ch;
- }