STM32F1+HAL库+不定长数据接收与分析

关于配置问题(F1的配置与F4的配置完全相同)

  1. DMA的设置 ,使用默认配置。注意接收数据的宽度统一,优先级可以不需要改变;
    Memory的递增模式一定要配置。
  2. 串口设置 ,使用默认配置。注意与通信模块的波特率相同,注意使能串口中断;
  3. 其他设置 ,RCC的设置,根据单片机的外部晶振进行设置
    (优先外部晶振,减小发生错误的概率);

关于代码问题(F1的代码与F4的代码相同)

F1的版本 main部分 存在问题版本

// An highlighted block
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_DMA_Init();
  /* USER CODE BEGIN 2 */
	__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
	HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);
  /* USER CODE END 2 */
    while (1)
  {
    /* USER CODE END WHILE */
			if(recv_end_flag ==1)
		{
			//printf("\nrx_len=%d\r\n",rx_len);
			HAL_UART_Transmit(&huart1,rx_buffer, rx_len,200);
			for(uint8_t i=0;i<rx_len;i++)
			   	 rx_buffer[i]=0;
			rx_len=0;
			recv_end_flag=0;
			HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);	
		}
}
    /* USER CODE BEGIN 3 */

F1的版本 it部分 (存在问题版本)

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
 uint32_t tmp_flag = 0;
	uint32_t temp;
  tmp_flag =  __HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); 
	if((tmp_flag != RESET))
  { 
			__HAL_UART_CLEAR_IDLEFLAG(&huart1);
			temp = huart1.Instance->SR;  
			temp = huart1.Instance->DR; 
			HAL_UART_DMAStop(&huart1);
			temp  = hdma_usart1_rx.Instance->CNDTR;
			rx_len =  BUFFER_SIZE - temp; 
		  recv_end_flag = 1;
		 // printf("%s",rx_buffer);
	//	HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);	
  }
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
  /* USER CODE END USART1_IRQn 1 */
}

F1的代码实验结果

串口发送:123123 接收:3(只接收最后一个发送的数据)
串口发送:3215 接收:5(只接收最后一个发送的数据)
1.只有正确收到发送数据的个数
所存在的问题:无法正确接收正确数据

错误原因
STM32 HAL库的DMA时钟配置跟串口,dma通道配置在两个文件里,结果先进行了串口配置,DMA通道配置,然后才是把DMA时钟打开了。导致DMA出现错误
根本原因:与cubemx的初始化顺序有关

具体相关链接:链接: https://blog.csdn.net/lutigers/article/details/103910090.

正确版本(main版本):

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  
  /* USER CODE BEGIN 2 */
	//HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
	HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);	

有人说main函数看起来好像没有意义?
可不可以把main函数的while(1)里面的部分进行省略,移植到串口中断函数里面?

根据建议修改后的版本:
修改版本+整合while(1)的内容(it文件):


void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
 uint32_t tmp_flag = 0;
	uint32_t temp;
  tmp_flag =  __HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); 
	if((tmp_flag != RESET))
  { 
			__HAL_UART_CLEAR_IDLEFLAG(&huart1);
			temp = huart1.Instance->SR;  
			temp = huart1.Instance->DR; 
			HAL_UART_DMAStop(&huart1);
			temp  = hdma_usart1_rx.Instance->CNDTR;
			rx_len =  BUFFER_SIZE - temp; 
		  HAL_UART_Transmit(&huart1,rx_buffer, rx_len,200);
			for(uint8_t i=0;i<rx_len;i++)
				{
					rx_buffer[i]=0;
				}
			rx_len=0;
			HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);	
  }
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

实践出真知,运行一下代码,会出现什么情况呢?
疯狂按串口助手的发送建?接收始终没有任何显示。
按下16进制显示,才发现无论我们像单片机发送什么,单片机始终只会回复0。
只有16进制显示下,才会显示。
分析目前的现象,按下发送键,有回复,回复为0.
有回复说明,串口空闲中断是正常运行的,但是回复不正常,说明是DMA又出现了问题

为什么会出现这样的错误?

flag_test	=HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);	

(PS:在进行多次实验中,出现正确的代码也无法以运行的情况。解决办法:换个串口,插拔一下就可以了。)

我们利用标志位的返回值来判断,究竟是哪里出现了问题。
下次再写…

第一次写,希望大家见谅,写错的地方需要大家指正。。。。。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值