目录
STM32F103RC使用HAL库配置USART进行数据收发(代码模块)
STM32F103RC使用HAL库配置USART进行数据收发(代码模块)
一、USART初始化
UART_HandleTypeDef huart1; uint8_t Rdata; void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BandRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; if(HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } #if 1 HAL_UART_Receive_IT(&huart1,&Rdata,1); //使能接收中断,会进入回调函数 #else __HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE); //直接使能串口接收中断,不会进入回调函数 #endif }
二、USART使用的GPIO初始化
UART使用的GPIO初始化函数是在void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)函数中: void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(uartHandle->Instance == USART1) { __HAL_RCC_USART1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_AFIO_CLK_ENABLE(); //PA9(USART1_TX) GPIO_InitStruct.Pin = USART1_TX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(USART1_TX_GPIO_Port,&GPIO_InitStruct); //PA10(USART1_RX) GPIO_InitStruct.Pin = USART1_RX_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(USART1_RX_GPIO_Port,&GPIO_InitStruct); HAL_NVIC_SetPriority(USART1_IRQn,0,0); HAL_NVIC_EnableIRQ(USART1_IRQn); } }
三、USART的接收中断配置
USART的接收中断的配置有两种方式,以下简要介绍下两种配置方式的不同。 1、使用串口接收中断回调函数 2、不使用串口接收中断的回调函数
######使用串口接收中断回调函数时的配置如下: 1、函数MX_USART1_UART_Init的配置 void MX_USART1_UART_Init(void) { /* //这里是串口的初始化配置 */ HAL_UART_Receive_IT(&huart1,&Rdata,1); //使能接收中断,会进入回调函数 } 在函数void MX_USART1_UART_Init(void)中的最后使用HAL_UART_Receive_IT(&huart1,&Rdata,1)进行配置。该函数会使能接收中断,每当串口接收到1个字节后就会进入回调函数void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)中。 2、串口接收中断回调函数HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)配置 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == USART1) { QueueWrite((void *)buf_pc_to_uart,Rdata); //将串口接收到的数据写入到队列中 HAL_UART_Receive_IT(&huart1,&Rdata,1); //接收完1字节后要重新使能接收中断 } } 在串口接收回调函数中,需要先对接收的数据进行处理,需要注意的是在处理完接收数据后要重新调用HAL_UART_Receive_IT函数使能接收中断,使得下次接收完数据后能继续进入回调函数。
######不使用串口接收中断回调函数时的配置如下: 1、函数MX_USART1_UART_Init的配置 void MX_USART1_UART_Init(void) { /* //这里是串口的初始化配置 */ __HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE); //直接使能串口接收中断,不会进入回调函数 } 在函数void MX_USART1_UART_Init(void)中的最后使用__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE)进行配置。该函数会使能接收中断,但是不会进入回调函数void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)中,而是进入 void USART1_IRQHandler(void)中。 2、串口接收中断函数void USART1_IRQHandler(void)配置 void USART1_IRQHandler(void) { if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE) != RESET) { HAL_UART_Receive(&huart1,&Rdata,1,100); QueueWrite((void *)buf_pc_to_uart,Rdata); //将串口接收到的数据写入到队列中 __HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_RXNE); } HAL_UART_IRQHandler(&huart1); } 在串口中断函数中,和标准库的处理流程相同,先通过接收中断标志位是否置1判断接收中断是否触发,触发后接收数据,对接收到的数据进行处理后,清除接收中断标志位即可。
四、USART的数据发送
直接调用HAL库接口函数 HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart,uint8_t *pData,uint16_t Size,uint32_t Timeout) 或者 HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart,uint8_t *pData,uint16_t Size)即可。
五、补充
1、这里介绍的串口配置及串口的收发数据是没有使用DMA进行传输数据的,如果需要进行大数据包传输,就需要使用DMA进行数据传输了。这时就需要进一步配置DMA的发送或者接收功能了。这里不再介绍,可以自己去网上查找相关资料。 2、以上的配置我们使用的串口接收中断每次接收1个字节的数据,当需要进行不定长数据或者大数据包的接收时,就不适合采用这种接收方式了,这时可以采用串口空闲中断+DMA的方式来进行不定长数据或者大数据包的接收。一般配置流程如下: 首先、配置串口,串口GPIO及DMA完成初始化 然后、在串口初始化函数最后调用: HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart,uint8_t *pData,uint16_t Size)函数,该函数会使能串口的DMA接收并且使能串口的空闲中断。当接收到一包数据后就会进入回调函数: void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart,uint16_t Size)。