573|5

1047

帖子

3

资源

纯净的硅(中级)

【NUCLEO-L552ZE测评】+如何接收完整的串口数据(已解决) [复制链接]

本帖最后由 hujj 于 2021-1-21 14:08 编辑

    在测试串口通讯时,我在主循环中写入下面的代码,将接收的字符数尽量设大点,就可以接收到完整的数据:

      if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_RXNE))
      {
          HAL_UART_Receive(&huart2,aBT_Buff,64,100);
          LCD_write_ASCII(0,4,1,aBT_Buff);
          nBT_size = 64;
		  printf("%s \r\n", aRxBuffer);
		  
		  if(aRxBuffer[0]=='D'){  //通过串口设置日期时间(格式=DyyyymmddHHMMSS)
		      year = (aRxBuffer[1]-0x30)*1000+(aRxBuffer[2]-0x30)*100+(aRxBuffer[3]-0x30)*10+(aRxBuffer[4]-0x30);
			  month = (aRxBuffer[5]-0x30)*10+(aRxBuffer[6]-0x30);
			  day = (aRxBuffer[7]-0x30)*10+(aRxBuffer[8]-0x30);
			  hour = (aRxBuffer[9]-0x30)*10+(aRxBuffer[10]-0x30);
			  minute = (aRxBuffer[11]-0x30)*10+(aRxBuffer[12]-0x30);
			  second = 0;
			  DS1307_write_date();
		  }
      }

 

    我用上面的代码,通过串口调试助手向单片机发送固定格式的日期时间字符串(D202001201525),单片机能够完整的接收并且完成日期时间的设置,下图是通过串口调试助手向单片机发送数据,并收到返回的数据,说明接收和返回内容完全一致:

BLE_12.jpg

    在单片机上也显示出了接收到的正确数据,并且DS1307日历模块的数据也得到更新:

BLE_13.jpg

    这是发送字符串测试,可以正确地被单片机接收并返回:

BLE_10.jpg

    在单片机的屏幕上正确地显示出来:

BLE_15.jpg

    但同样的代码放在被主循环调用的函数中,却只能接收到首个字节的数据,后面的字节全部丢失了,代码如下:

void BT05_Init(void)
{
	uint8_t ReceSize;
	
	printf("AT\r\n");

    if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_RXNE))
    {
        HAL_UART_Receive(&huart2,aBT_Buff,64,1000);
    }

    LCD_write_ASCII(0,3,1,(uint8_t *)"BT05=");
	LCD_write_ASCII(30,3,1,aBT_Buff);
    BT_display();

	if(aBT_Buff[0]==0x4F){  //蓝牙模块有回应,开始设置
    	printf("AT+INQ\r\n");
        if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_RXNE))
        {
            HAL_UART_Receive(&huart2,aBT_Buff,64,1000); //接收蓝牙返回的信息
        }
        LCD_write_ASCII(30,4,1,aBT_Buff);
	    BT_display();

		LCD_write_ASCII(100,5,1,(uint8_t *)"BT05_Init OK!  ");
	}
	else{                                     //蓝牙模块无回应
        LCD_write_ASCII(100,5,1,(uint8_t *)"BT05_Init Fail!");
	}
}

 

    串口调试助手发送“OK”,模拟蓝牙回应:

BLE_11.jpg

    在单片机屏幕上显示接收到的数据,只接收到“O”,第二行的五组十六进制数据分别是接收缓存数组的前五个,只有第一组是0x4F,其他都是0x00:

BLE_14.jpg

    我想通过中断方式来接收,多次尝试也没有获得成功,中断处理的代码如下,不知道是哪里不对:

void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */

  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */

	HAL_UART_Receive(&huart2,aBT_Buff,64,100);

//    HAL_UART_Receive_IT(&huart2, aRxBuffer, 64);
	if (HAL_UART_Transmit_IT(&huart2, aRxBuffer, 64) != HAL_OK)
    {
        Error_Handler();
    }

  /* USER CODE END USART2_IRQn 1 */
}

 

    在测试过程中我将中断处理里面的USER CODE之间的代码注释掉,在主循环中的轮询方式竟然也只能接收一个字符的数据,不知是什么原因。

 

此帖出自stm32/stm8论坛

赞赏

1

查看全部赞赏


回复

1998

帖子

3

资源

版主

你判断的这个是接收标志位,感觉是接收到第一个字符之后就开始处理。而不是接收结束之后开始处理数据。而且你两段代码好像不太一致。第二段明显比较乱,而且为什么设置多个接收?

点评

    第一段是测试串口用的,第二段则是实际与蓝牙通讯用的,使用第二段代码时,第一段会注释掉,不会同时使用。     第一段代码仅仅是接收、显示、发送返回的功能,第二段代码添加了判断和处  详情 回复 发表于 2021-1-21 09:16

回复

1047

帖子

3

资源

纯净的硅(中级)

w494143467 发表于 2021-1-20 20:49 你判断的这个是接收标志位,感觉是接收到第一个字符之后就开始处理。而不是接收结束之后开始处理数据。而且 ...

    第一段是测试串口用的,第二段则是实际与蓝牙通讯用的,使用第二段代码时,第一段会注释掉,不会同时使用。

    第一段代码仅仅是接收、显示、发送返回的功能,第二段代码添加了判断和处理,所以显得有点乱。

    在接收和发送函数中指定了缓存区的长度,应该是接收全部数据后再返回吧,从第一段代码中也应该证实这一点,难道没有接收完毕就会返回吗?另外我尝试过使用while循环,每次接收一个字节(长度为1),然而却没有接收到数据。

 

点评

你是直接读数据吧?看看你CubeMX配置的缓存是多大。建议用中断,进入中断后,读取数据保存在缓存数组中,中断是接收一个字节进入一次。  详情 回复 发表于 2021-1-21 13:32

回复

1998

帖子

3

资源

版主

hujj 发表于 2021-1-21 09:16     第一段是测试串口用的,第二段则是实际与蓝牙通讯用的,使用第二段代码时,第一段会注释掉 ...

你是直接读数据吧?看看你CubeMX配置的缓存是多大。建议用中断,进入中断后,读取数据保存在缓存数组中,中断是接收一个字节进入一次。


回复

1047

帖子

3

资源

纯净的硅(中级)

    经过反复测试和仔细分析,串口有时只能接收1个字符应该是尚未完整接收到数据就开始调用接收函数了,按照这个思路,曾尝试在发送命令之后延时100毫秒再调用接收函数,但效果不理想,后来改为加个等待的循环,等到有接收标志时才调用接收函数,代码如下:

void BT05_Init(void)
{
	uint8_t ReceSize;
	
	printf("AT\r\n");

    while(!__HAL_UART_GET_FLAG(&huart2,UART_FLAG_RXNE));//添加的代码
    if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_RXNE))
    {
        HAL_UART_Receive(&huart2,aBT_Buff,64,1000);
    }

    LCD_write_ASCII(0,3,1,(uint8_t *)"BT05=");
	LCD_write_ASCII(30,3,1,aBT_Buff);
    BT_display();
  
    if(aBT_Buff[0] == 0x4F){	  //蓝牙模块有回应,开始设置
    	printf("AT+INQ\r\n");
        while(!__HAL_UART_GET_FLAG(&huart2,UART_FLAG_RXNE));
        if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_RXNE))
        {
            HAL_UART_Receive(&huart2,aBT_Buff,64,1000); //接收蓝牙返回的信息
        }
        LCD_write_ASCII(30,4,1,aBT_Buff);
        BT_display();

		LCD_write_ASCII(100,5,1,(uint8_t *)"BT05_Init OK!  ");
	}
	else{                                     //蓝牙模块无回应
        LCD_write_ASCII(100,5,1,(uint8_t *)"BT05_Init Fail!");
	}
}

 

    这个函数的作用是搜索当前可用的从蓝牙设备,从屏幕上显示的信息是搜索到了一个从蓝牙设备:

BLE_16.jpg

 

    在此感谢大家的关心和帮助,尤其是w494143467版主!


回复

1047

帖子

3

资源

纯净的硅(中级)

进一步优化代码,while后面的if语句都是多余的了,可以优化如下:

        while(!__HAL_UART_GET_FLAG(&huart2,UART_FLAG_RXNE));
        HAL_UART_Receive(&huart2,aBT_Buff,64,1000); //接收蓝牙返回的信息


回复
您需要登录后才可以回帖 登录 | 注册

最新文章 更多>>
    关闭
    站长推荐上一条 1/9 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2021 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表