HC06蓝牙2.0模块连接不稳定 和 STM32串口不传输数据(串口接收中断)的一些问题

HC06蓝牙2.0模块连接不稳定和STM32串口不传输数据(串口接收中断)的一些问题(推荐)

1、蓝牙

最近,在一个项目中使用到蓝牙,但是调试过程出现了很多问题。
刚开始使用的是HC06蓝牙,刚开始使用较为正常,可以实现蓝牙模块和电脑设备直接连接,而且数据接收正常。

在接下来的设计中,考虑到适配问题,就设计了配套的蓝牙接收模块,同样是HC06贴片模块。但问题随之出现。

连接不稳定!!!
模块之间在没有数据传输时,模块连接稳定,且在数据量小的时候也没有问题,这个小数据量是指:一秒传输1个数据或者两个数据。

当传输量大的时候,比如一秒十个数据,这个时候模块之间会出现数据传输阻塞,出现数据传输卡顿,造成数据丢失,并最终造成模块连接因为空中通信阻塞而断开。

在测试中,也测试过是否与蓝牙传输波特率是否有关,但实际测试之后,阻塞问题不会因为波特率改变而出现解决或者改善。

在后来的了解中得知,蓝牙一般选择协议4.0以上,产品的数据实时性才有所保证,而协议2.0,虽然使用广泛,但很难保证实时性,也就是没法做到大量数据同步到另一个模块。所以在后来的设计中也重新更换了别的蓝牙(新蓝牙使用的是蓝牙5.0协议)

2、STM32串口的问题
在使用STM32串口过程中,发现电路只有在复位之后才会有数据传输,只要中途掉电,再次上电,数据传输就会消失,或者在重新编译下载之后传输也是正常的。在排除程序卡死、复位电路错误等问题之后,只能 进一步寻找软件程序上的问题。因此,一步一步进行编译调试发现,STM32串口中断还真的有BUG。

先说在网上找到的一个几乎一模一样的问题的帖子:串口接收中断异常 主要的描述:现在发现一部分板子(另外一些正常工作)掉电之后再次上电串口没有数据输出,输入也没反应,单片机正常工作(设定了DA)。按复位键之后正常工作,串口可发送可接收。 重新下完程序,则正常运行。断电之后出现上述情况~~~
在这个帖子中主要给出的问题源头是STM32串口中断机制有问题。
详细的介绍着这个地方:串口接收中断异常(2)

在我们串口初始化程序中会有串口中断使能:
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

在USART配置中只打开了接收中断!没有数据送过来应该是不可能进入中断的!
但是使能了接收中断,那么ORE中断也同时被开启了。
只要接收中断打开,即RXNEIE设置为1,那么ORE中断也自动打开了。
可是USART_GetITStatus(USART1, USART_IT_ORE )== RESET!!!
找到USART_GetITStatus(USART1, USART_IT_RXNE)函数,发现只有当USART_IT_ERR中断使能时,才能读到ORE中断。
在这里要指出这个BUG:产生ORE中断了,但使用USART_GetITStatus()函数却无法读到这个中断被SET起来!

既然找到了是什么中断,那么把相应的中断标志位清除,就应该可以了吧?
USART_ClearITPendingBit(USART1, USART_IT_ORE);
但是,结果是没有任何效果!清除之后,马上读ORE中断状态,USART_GetITStatus(USART1, USART_IT_ORE)==RESET.程序仍然跑死在接收中断。再使用另一个函数USART_GetFlagStatus(USART1, USART_FLAG_ORE) = SET,原来ORE标志位还没有清除。

他的解决办法:
串口中断程序中使用if (USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET)//注意!不能使用if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)来判断。

在我的实际应用中,虽然改了这个读取状态的函数,但是并没有实际的作用,也就是没有解决串口不工作的问题。
也增加了对不同中断标志位的判断,也仍然没有解决串口不工作的问题。

由于项目中串口传输是单向的,所以也就将串口接收中断使能给关掉了,关掉之后,一切传输正常,不管什么时候只要上电,就能实现数据的正常传输。

这也从侧面说明,这个串口非正常传输的主要问题,根源还是在串口接收中断上。还是需要在调试模式下,一句一句查看问题。

有时间再探索这个项目中具体的原因。

若是有朋友也遇到相关问题,可以按照上述给出的链接中的解决方案,应该可以解决大部分人的疑惑,当然,如果有人和我一样,也可以留言,我尽快补一补这个漏洞。

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个使用STM32F103ZET6控制器,通过USART3串口HC08蓝牙模块进行数据通信的例程。在本程序中,我们使用了STM32CubeMX来进行初始化配置,所以您需要使用STM32CubeMX软件生成代码,并将其导入到您的开发环境中。本例程还使用了HAL库提供的函数。 ```c #include "main.h" #include "stdio.h" #include "string.h" UART_HandleTypeDef huart3; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART3_UART_Init(void); char rx_data[1]; int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART3_UART_Init(); while (1) { if(HAL_UART_Receive_IT(&huart3, (uint8_t *)rx_data, 1) == HAL_OK) //启用串口中断 { if(rx_data[0] == '1') //判断接收到的数据 { char buffer[20]; sprintf(buffer, "SEND DATA 1\r\n"); //将数据格式化 HAL_UART_Transmit(&huart3, (uint8_t *)buffer, strlen(buffer), 0xFFFF); //发送数据 } else if(rx_data[0] == '2') { char buffer[20]; sprintf(buffer, "SEND DATA 2\r\n"); HAL_UART_Transmit(&huart3, (uint8_t *)buffer, strlen(buffer), 0xFFFF); } } } } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) //UART接收中断回调函数 { if(huart->Instance == USART3) { HAL_UART_Receive_IT(&huart3, (uint8_t *)rx_data, 1); //重新启用接收中断 } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.HSIState = RCC_HSI_OFF; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } } static 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(); } } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOB_CLK_ENABLE(); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_RESET); GPIO_InitStruct.Pin = GPIO_PIN_14; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); } void Error_Handler(void) { } #ifdef USE_FULL_ASSERT void assert_failed(uint8_t *file, uint32_t line) { } #endif ``` 在本例程中,我们使用串口3和HC08蓝牙模块进行数据通信。当接收到数据时,我们会检查数据的内容,并根据数据内容发送不同的数据。在此之前,我们先启用了串口3的中断功能,在接收到数据时,会触发中断回调函数。在中断回调函数中,我们重新启用了接收中断,以便能够继续接收数据。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值