STM32接收不定长数据

硬件

STM32L475

方案

使用通过修改HAL库,加入IDLE中断,实现不定长数据接收
在这里插入图片描述

参考资料

LAT0534_UART_IDLE中断使用_接收不定长串口数据_V0.3
关于资料下载,包括源码,参考的手册:https://www.dianyuan.com/eestar/article-3471.html

cubemx配置

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实现过程

首先接入接受的数据缓冲区,并设置缓冲区的大小

//Store the revceived bytes number
uint32_t Rev_Size = 0;
//Receive buffer
uint8_t UART_RX_Buf[15];

然后修改HAL库的usart.c文件
加入extern uint32_t Rev_Size;变量声明
修改HAL_StatusTypeDef HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart)该函数

#else
//修改后的代码
	CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE| USART_CR1_IDLEIE));
//  CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));//修改前的代码
  CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
#endif /* USART_CR1_FIFOEN */

修改HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)该函数,这里需要注意一下加入代码的位置。

__HAL_UNLOCK(huart);
		
		/* Enable the UART IDLE Interrupt*/   //加入的代码
		SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
		
    /* Enable the UART Parity Error Interrupt */
    SET_BIT(huart->Instance->CR1, USART_CR1_PEIE);

修改void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)函数,光放文档里面的是 USART_SR_IDLE需要换成 USART_ISR_IDLE,NDTR换成CNDTR(具体原因看技术手册和源码)

#if defined(USART_CR1_FIFOEN)
    if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U)
        && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U)
            || ((cr3its & USART_CR3_RXFTIE) != 0U)))
#else
		//加入的代码
		if(((isrflags & USART_ISR_IDLE) != RESET) && ((cr1its & USART_CR1_IDLEIE) != RESET))
 {
		//Record the received bytes number
		Rev_Size = huart->RxXferSize - huart->hdmarx->Instance->CNDTR;
		//clear the IDLE flag
		__HAL_UART_CLEAR_IDLEFLAG(huart);
		//Abord the received process
		HAL_UART_AbortReceive_IT(huart);
		return;
 }

    if (((isrflags & USART_ISR_RXNE) != 0U)
        && ((cr1its & USART_CR1_RXNEIE) != 0U))
#endif /* USART_CR1_FIFOEN */
    {
      if (huart->RxISR != NULL)
      {
        huart->RxISR(huart);
      }
      return;
    }
  }

在main.c里面进行函数修改
添加中断,该中断是在开启接收后,当接收到的数据没有到达最大的接收位的时候,但是总线上停止了数据传输,总线进入空闲状态,则产生中止中断。,并进入该函数进行数据处理。


```c
void HAL_UART_AbortReceiveCpltCallback (UART_HandleTypeDef *huart)
{
 //Print received Bytes
	printf("\n\r[IDLE]Received %d Bytes:",Rev_Size);
	for(uint16_t i = 0; i < Rev_Size; i++)
	{
	printf(" 0x%02X", UART_RX_Buf[i]);
	}
	//Re-start receiving
	HAL_UART_Receive_DMA(&huart1, UART_RX_Buf, 15);
 /* NOTE : This function should not be modified, when the callback is needed,
 the HAL_UART_AbortTransmitCpltCallback can be implemented in the user 
file.
 */
}

该中断的解释

```c
/**
  * @brief  Abort ongoing Receive transfer (Interrupt mode).
  * @param  huart UART handle.
  * @note   This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode.
  * @note   This procedure is executed in Interrupt mode, meaning that abort procedure could be
  *         considered as completed only when user abort complete callback is executed (not when exiting function).
  * @retval HAL status
  */​

HAL_UART_Receive_DMA(&huart1, UART_RX_Buf, 15);接收中断的启动函数,通过启动接收,并在中止中断里面再次开启实现循环接收。其中15是最大的可接受的数据。
具体使用,需要注意的是,printf函数需要自己加入printf支持。

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	printf("123456789\r\n");
	HAL_UART_Receive_DMA(&huart1, UART_RX_Buf, 15);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}


结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值