完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
|
|
相关推荐
1个回答
|
|
写在前面
最近使用STM32做串口数据收发,遇到了一些问题。折腾了一番,在此记录一下。 0 需求
为了实现需求,先进行两个小实验 3. 模块+上位机实验 : 验证4G模块与平台之间数据收发正常。 4. 电路板串口数据接收实验 :排除电路板硬件异常问题。 1.1 模块+上位机实验 平台发布消息,模块TX引脚输出。通过CH340与串口调试助手相连,接收并显示数据。验证模块能否正常收发数据。 ---------------------补一张串口接收数据图-------------- 可以正常收发数据,排除模块问题。 ASCII编码对照表_911查询 1.2 电路板串口数据接收实验 实验硬件:UART1(COM3) , UART3(COM1)实验。 实验现象:UART1 接收到的消息通过UART1打印到串口;UART3 接收到的消息亦通过UART1打印到串口。(UART1做串口调试使用) 实验结论: 排除电路板硬件异常原因,UART1 & UART3 可以正常收发数据。 示例代码: while(1) { if(USART_RX_STA&0x8000) { LED0 = 0; //点亮LED显示接收到消息 len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度 printf("rnUART1发送的消息为:rn"); HAL_UART_Transmit(&UART1_Handler,(uint8_t*)USART_RX_BUF,len,1000); //发送接收到的数据 while(__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_TC)!=SET); //等待发送结束 printf("rnrn");//插入换行 USART_RX_STA=0; } else if(USART3_RX_STA&0x8000) { LED0 = 1; //熄灭LED显示接收到消息 len=USART3_RX_STA&0x3fff;//得到此次接收到的数据长度 printf("rnUART3发送的消息为:rn"); HAL_UART_Transmit(&UART1_Handler,(uint8_t*)USART3_RX_BUF,len,1000); //发送接收到的数据 while(__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_TC)!=SET); //等待发送结束 printf("rnrn");//插入换行 USART3_RX_STA=0; } } 1.3 问题来了! 当以上两个小测试完成时,可以确定整个系统软件与硬件无误。也就是说,当电路板上插上4G模块时,即可实现单片机与平台通信的功能! 然而,当平台发布数据时,单片机未能接收到数据。通过软件调试等操作发现,UART3并未进入到接收到数据中断。用示波器测量模块TX引脚,平台发布消息时确实有信号输出!迷惑行为,,,,,, 2 开始分析 2.1 串口数据格式 如下图,可以看出
以上两个小测试确实可以验证软件与硬件无误。那么为什么单片机可以接收上位机传来的数据,而不能接收4G模块转发来的数据呢?二者数据有何区别? 验证方法 : 上位机和平台同时发送信息,测其输出信号。测试数据 11(0011_0001 0011_0001)
查看串口助手,果然!默认勾选了“发送新行” 再次测试,勾选了“发送新行”数据可以被接收;不勾选了“发送新行”,数据不被接收!可以看出“发送新行”即为单片机识别数据的“校验”格式。那么程序中一定有与“校验”相关的代码,那就找到他!
3 代码分析 关于串口接收的代码如下,一眼就可看到关于0x0a,0x0d的判断,确认是结尾校验无误了。若要修改为 ‘**’ 校验,改为0x2a,0x2a即可。修改后测试成功,没图。 if(huart->Instance==USART3)//如果是串口1 { if((USART3_RX_STA&0x8000)==0)//接收未完成 { if(USART3_RX_STA&0x4000)//接收到了0x0d { if(aRx3Buffer[0]!=0x0a)USART3_RX_STA=0;//接收错误,重新开始 else USART3_RX_STA|=0x8000; //接收完成了 } else //还没收到0X0D { if(aRx3Buffer[0]==0x0d)USART3_RX_STA|=0x4000; else { USART3_RX_BUF[USART3_RX_STA&0X3FFF]=aRx3Buffer[0] ; USART3_RX_STA++; if(USART3_RX_STA>(USART_REC_LEN-1))USART3_RX_STA=0;//接收数据错误,重新开始接收 } } } }
新的问题收测试时出现寄存器数据累加情况,具体表现为:
{ if((USART3_RX_STA&0x8000)==0) //接收未完成 USART3_RX_STA最高位判断 { if(USART3_RX_STA&0x4000) //接收到了第一个0x2a USART3_RX_STA次高位判断 { if(aRx3Buffer[0]!=0x0a) { USART3_RX_STA=0; //接收错误,重新开始 } else USART3_RX_STA|=0x8000; //接收完成了 } else //还没接收到第一个0x2a { if(aRx3Buffer[0]==0x0d) { USART3_RX_STA|=0x4000; } else { USART3_RX_BUF[USART3_RX_STA&0X3FFF]=aRx3Buffer[0] ; //0X3FFF USART3_RX_STA 低14位是数据 USART3_RX_STA++; if(USART3_RX_STA>(USART_REC_LEN-1)) { USART3_RX_STA=0;//接收数据错误,重新开始接收 } } } } }
可以看出,与猜测一致。串口接收缓冲buff并没有进行数据清除。当数据(带校验)未临时,之前的数据会一直寄存在buff中,直到最终发送完毕。(当然数据累加有一定上限,USART_REC_LEN) 若要消除数据累加的情况,就必须在接收完一次不带校验的数据后,及时清除缓冲buff。实际使用中,两次接收数据之间有一定间隔,若能在间隔之中清除buff,即可规避。故加入以下代码,测试一下。 if (time_10_ms) //定时器 10ms { time_10_ms = 0 ; memset(USART3_RX_BUF, 0, sizeof USART3_RX_BUF); }
总结 没啥写的,强迫症凑一凑。 |
|
|
|
只有小组成员才能发言,加入小组>>
3310 浏览 9 评论
2991 浏览 16 评论
3492 浏览 1 评论
9055 浏览 16 评论
4086 浏览 18 评论
1174浏览 3评论
603浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
596浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2333浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1894浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-21 14:43 , Processed in 1.099198 second(s), Total 78, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号