stm32-遇到的奇怪BUG串口接收数据异常
前言:
今天在用嘉立创stm32f407vet测试串口接收GY-33模块的时候发现,不管我发送什么数据,串口调试助手上接收到的都是一堆中文乱码,或者是一些完全不相关的东西,回来还使用的中断盒DMA,但还是一堆乱码,起初还以为是没有共地,后来反复更换,但还是没有解决,也在网上找了一些教程,也是不行,最后还是在一步步调试中解决了,所以想分享一些,解决方法,供后来者提供一个解决方案.
配置如下
stm32CubeMX:
串口:
通过串口2接收GY-33的数据,然后用串口3通过蓝牙模块发到上位机查看数据
时钟:

代码:
我这里用的是printf重定向通过串口3发送接收到的GY-33的到上位机:
int fputc(int ch, FILE *p){
char c = ch;
HAL_UART_Transmit(&huart3,(uint8_t*)&c,1,50);
return ch;
}
接收回调函数:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
if (huart == &huart2)
{
//printf("1");
rebuf[i++] = rx_buffer[0]; // 将接收到的字节存入缓冲区
//HAL_UART_Transmit_IT(&huart1,rx_buffer,10);
// 帧头校验
if (rebuf[0] != 0x5A)
{
//printf("2");
i = 0;
goto restart;
}
if (i == 2 && (rebuf[1] != 0x5A))
{
//printf("3");
i = 0;
goto restart;
}
// 数据长度判断
if (i > 3)
{
//printf("3");
uint8_t expected_len = rebuf[3] + 5; // 总长度 = 帧头(2) + 命令(1) + 长度(1) + 数据 + 校验(1)
if (i < expected_len)
{
//printf("4");
goto restart; // 数据未接收完整
}
// 数据接收完整,开始处理
switch (rebuf[2]) // 命令码
{
case 0x45:
if (!Receive_ok)
{
memcpy(rgb_data, rebuf, 8); // 仅拷贝有效数据
Receive_ok = 1; // 设置接收完成标志
}
break;
case 0x15: // 原始数据命令
// TODO: 添加处理逻辑
break;
case 0x35: // 其他命令
// TODO: 添加处理逻辑
break;
default:
break;
}
i = 0; // 重置索引
}
restart:
// 重新启动接收(每次接收一个字节)
HAL_UART_Receive_DMA(&huart2, rx_buffer, 1);
}
}
主函数就是简单判断标志位将接收到的数据发到上位机:

问题重现:
因为这样由于串口错误,接收到的数据根本就不正常,所以也检测不到标志位,所以我在前面加了一个
printf("1");来串口发送是不是正常的;
这个时候神奇的现象发生了

我发送的是printf("1"),接改上位机接收到的竟然是一堆"类",我怎么也想不通,类跟1有什么关系跟 ASCII 码也没有关系啊,然后经过了很多次测试,发现还是这样,最一步步联想,串口数据接收不稳定是不是跟时钟频率有关系于是我将高速时钟由外部晶振换成了内部时钟,然后串口竟然正常了

现象:
其它代码啥都没改,就将外部高速时钟换成的内部高速时钟

后续解决方法:
后来发现是嘉立创这个外部晶振是8MHz的,而我外部时钟默认选择了最高频率26MHz导致晶振频率错误,串口发送错误


结尾:
这个问题折磨我了几个小时,因为以前配置代码的习惯,一开始配置就将内部时钟源换成外部晶振,所以出现这个问题,还真一时想不到问题所在,对此写这篇博客分享一下遇到这个问题的历程和解决的一些思路,供后面的学习者参考.
更多推荐


所有评论(0)