目录
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)。