目录
概述
1 CubeMX配置串口参数
1.1 STM32CUB配置参数
1.2 生成代码
2 核心代码介绍
2.1 初始化函数
2.2 中断函数
2.3 重要的用户函数
2.4 实现用户接口函数
3 接收数据函数的优化
3.1 HAL库接收函数的缺陷
3.2 改进接收函数
概述
在STM32开发中使用HAL库操作串口(UART)主要分为以下几个步骤,下面以中断接收和轮询发送为例进行详细说明:
1 CubeMX配置串口参数
1.1 STM32CUB配置参数
使用STM32 Cube工具配置UART参数,具体配置如下:
1)选择端口
STM32F103RCTX有5个串口可供使用,其中USART(1~3)为增强型串口, UART(4-5)为普通串口。
2) baud rate 和其他参数
笔者选择默认参数,其具体参数如下
注意: 关于选择Baud的注意点
使用STM32串口应该注意,系统的工作频率会影响串口数据的误差率,官方已经给了测试数据,具体如下:
3) 配置中断
4) 给IO添加User Label (可选择)
1.2 生成代码
通过以上配置,完成串口功能的参数配置 。接下来可已使用STM32CUBE工具生成代码。在生成代码前,应该选择相应的开发工具,堆栈参数等
完成以上配置后,可点击GENERATE CODE生成代码,具体架构如下:
2 核心代码介绍
2.1 初始化函数
在usart.c文件中生成串口的初始代码,其包括2个部分
1) 对串口的参数进行初始化
2)IO 参数初始化
包括开启串口和IO的时钟,配置IO的工作模式,配置中断参数
2.2 中断函数
在stm32fxx_it.c文件中实现了所有已经使能中断的中断函数,这里至关注和USART相关的中断函数。
2.3 重要的用户函数
功能 | 函数 | 说明 |
---|---|---|
中断发送 | HAL_UART_Transmit_IT() | 非阻塞发送(需等待发送完成中断) |
DMA发送 | HAL_UART_Transmit_DMA() | DMA传输(高效不占用CPU) |
DMA接收 | HAL_UART_Receive_DMA() | DMA接收 |
发送函数 | HAL_UART_Transmit() | 查询方式发送数据 |
查询接收状态 | HAL_UART_GetState(&huart1) == HAL_OK | 检查串口状态 |
接收数据回调函数 | HAL_UART_RxCpltCallback | 用于处理接收的数据 |
2.4 实现用户接口函数
串口的重要作用是发送和接收数据,STM32Hal库已经给了相应的函数接口,程序员需要了解这些函数,并合理的使用它们。
1) 发送数据函数
要使用该函数需要对其进行改造,具体写法如下:
static void user_send(const uint8_t *buff, uint16_t len )
{HAL_UART_Transmit(&UartHandle, buff, len, 1000);
}
2) 接收数据
STM32 HAL库已经提供了接收数据的函数 ,这里使用中断的方式接收数据,其函数原型如下:
通过在主函数中调用该函数就能接收数据。
3 接收数据函数的优化
3.1 HAL库接收函数的缺陷
如下是HAl库提供的接收函数,其包含3个参数
1) huart: 串口对象
2) pData: 接收数据的buff
3) Size: 接收数据的大小
/*** @brief Receives an amount of data in non blocking mode.* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),* the received data is handled as a set of u16. In this case, Size must indicate the number* of u16 available through pData.* @param huart Pointer to a UART_HandleTypeDef structure that contains* the configuration information for the specified UART module.* @param pData Pointer to data buffer (u8 or u16 data elements).* @param Size Amount of data elements (u8 or u16) to be received.* @retval HAL status*/
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{/* Check that a Rx process is not already ongoing */if (huart->RxState == HAL_UART_STATE_READY){if ((pData == NULL) || (Size == 0U)){return HAL_ERROR;}/* Set Reception type to Standard reception */huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;return (UART_Start_Receive_IT(huart, pData, Size));}else{return HAL_BUSY;}
}
使用该函数接收数据,其timeout的时间取决于Size, 当Size越大,其timeout的时间会越长。
3.2 改进接收函数
通过操作STM32的寄存器实现单个字节的接收,这样可以根据接收数据的需要,随时调整Timerout的时间。具体方法如下:
1) 在回调函数中实现接收代码
uint32_t isrflags = READ_REG(huart->Instance->SR);uint32_t cr1its = READ_REG(huart->Instance->CR1);if( huart->Instance == USART1 ){/* UART in mode Receiver */if(( isrflags & USART_SR_RXNE) != RESET ){data = huart->Instance->DR;// protocol_data_recvByte(data);}SET_BIT(huart->Instance->CR1, USART_CR1_RXNEIE);CLEAR_BIT(huart->Instance->SR, USART_SR_ORE);}
2) 初始化函数中添加触发中断语句
/* USER CODE BEGIN USART1_Init 2 */SET_BIT(huart1.Instance->CR1, USART_CR1_RXNEIE);/* USER CODE END USART1_Init 2 *
3) 在中断函数中直接调用回调函数
/* USER CODE BEGIN USART1_IRQn 0 */HAL_UART_RxCpltCallback(&huart1);/* USER CODE END USART1_IRQn 0 *