HAL库写Flash操作引起的串口ORE错误不再接收的解决

一、问题

       使用内部EEPROM(Flash的一部分)储存数据,在写入数据到STM32L0单片机时,出现串口接收数据丢失甚至串口不再接收的现象。在正常情况下在没有写数据到Flash中去的时候所有串口数据都能正常接收,没有数据丢包现象,但是当执行一次写入操作就会导致串口数据丢失,导致接收ORE错误或帧错误等。

二、原因

       经查阅手册得知在Flash写入操作过程中,系统时钟停止,这意味着写入Flash期间无法访问Flash中的代码和数据。造成了串口那边RDR寄存器有值了,来不及取出下一个值装进移位寄存器出现了ORE错误。 在HAL库的串口中断里,如果出现ORE错误则会先去读取RDR寄存器的值进入中断回调函数。但执行完之后会关闭串口接收中断进入错误中断回调函数。也就是说由于ORE错误的出现造成了接收中断关闭不再接收的现象。具体串口中断处理参考HAL库的底层函数

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart);

三、解决方法

       编写错误中断回调函数开启接收中断。

/*******************************************************************************
*函 数 名:HAL_UART_ErrorCallback
*功能说明:串口错误回调函数
*形   参:huart:触发中断的串口
*返 回 值:无
*******************************************************************************/
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{		
	if (huart->Instance == USART1)
	{
		HAL_UART_Receive_IT(huart, &gUart1.Temp, RECLEN);
	}
	else if (huart->Instance == USART2)
	{
		HAL_UART_Receive_IT(huart, &gUart2.Temp, RECLEN);
	}
	else if (huart->Instance == USART4)
	{
		HAL_UART_Receive_IT(huart, &gUart4.Temp, RECLEN);
	}
	else if(huart->Instance == USART5)
	{
		HAL_UART_Receive_IT(huart, &gUart5.Temp, RECLEN);
	}
	
}

       仅供参考,具体根据串口使用的情况来编写,这边博主用到了以上四个串口。(这边还有一点需要注意,就是出ORE错误时,注意接收中断里用于存放串口数据的缓冲,如果用户一直写Flash则可能造成缓冲区溢出——博主的应用场景遇到,具体根据实际情况判断)。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用STM32 HAL库的三路串口发送和接收函数的参考代码。假设使用的是STM32F4xx系列的芯片,串口分别为USART1、USART2和USART3。 首先需要在CubeMX中配置串口。假设需要配置的串口参数如下:波特率为9600,无校验位,单停止位,数据位长度为8位,串口1使用PA9和PA10引脚,串口2使用PA2和PA3引脚,串口3使用PB10和PB11引脚。 在main.c文件中添加以下函数: ``` UART_HandleTypeDef huart1; UART_HandleTypeDef huart2; UART_HandleTypeDef huart3; void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 9600; 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; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } } void MX_USART2_UART_Init(void) { huart2.Instance = USART2; huart2.Init.BaudRate = 9600; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart2) != HAL_OK) { Error_Handler(); } } void MX_USART3_UART_Init(void) { huart3.Instance = USART3; huart3.Init.BaudRate = 9600; huart3.Init.WordLength = UART_WORDLENGTH_8B; huart3.Init.StopBits = UART_STOPBITS_1; huart3.Init.Parity = UART_PARITY_NONE; huart3.Init.Mode = UART_MODE_TX_RX; huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart3.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart3) != HAL_OK) { Error_Handler(); } } 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(); /**USART1 GPIO Configuration PA9 ------> USART1_TX PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } else if(uartHandle->Instance==USART2) { __HAL_RCC_USART2_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**USART2 GPIO Configuration PA2 ------> USART2_TX PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } else if(uartHandle->Instance==USART3) { __HAL_RCC_USART3_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /**USART3 GPIO Configuration PB10 ------> USART3_TX PB11 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); } } /** * @brief Initialises three UART devices. * @param None * @retval None */ void init_uart(void) { MX_USART1_UART_Init(); MX_USART2_UART_Init(); MX_USART3_UART_Init(); } ``` 接下来是三路串口发送和接收的函数代码: ``` /** * @brief Sends data via UART. * @param uart: UART device number (1, 2 or 3). * @param data: Pointer to data buffer. * @param len: Length of data buffer. * @retval None */ void uart_send(uint8_t uart, uint8_t* data, uint16_t len) { switch(uart) { case 1: HAL_UART_Transmit(&huart1, data, len, HAL_MAX_DELAY); break; case 2: HAL_UART_Transmit(&huart2, data, len, HAL_MAX_DELAY); break; case 3: HAL_UART_Transmit(&huart3, data, len, HAL_MAX_DELAY); break; default: break; } } /** * @brief Receives data via UART. * @param uart: UART device number (1, 2 or 3). * @param data: Pointer to data buffer. * @param len: Length of data buffer. * @retval Number of bytes received. */ uint16_t uart_receive(uint8_t uart, uint8_t* data, uint16_t len) { uint16_t rx_len = 0; switch(uart) { case 1: rx_len = HAL_UART_Receive(&huart1, data, len, HAL_MAX_DELAY); break; case 2: rx_len = HAL_UART_Receive(&huart2, data, len, HAL_MAX_DELAY); break; case 3: rx_len = HAL_UART_Receive(&huart3, data, len, HAL_MAX_DELAY); break; default: break; } return rx_len; } ``` 在需要使用串口的地方,可以调用uart_send()函数发送数据,调用uart_receive()函数接收数据。需要注意的是,以上代码仅供参考,具体实现应根据实际需求进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值