完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
在调试程序时发现,甲方提供的通信协议,只有帧头和信息位,没有帧尾,没有校验位。 刚开始时按照甲方提供的通信协议,简单的写了一个串口中断接收程序。但是在测试中发现:发送协议 FEFE,000,00000000,002,002,002,?000,设备可以正常接收,但在帧尾部添加一个字节或者减少一个字节再发送,设备依然响应。
以下为错误的代码。 // if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) // { // Counter_USART++; // c=USART3->DR; // clear=USART3->DR;//清除中断标志位 // if(c==0x35 && Start_Rec==0 && Counter_USART==1) // { // Buf_USART3[0]=c; // Start_Rec=1; // } // else if(Buf_USART3[0]==0x35 && c==0x35 && Start_Rec==1 && Counter_USART==2) // { // Buf_USART3[1]=c; // Start_Rec=2; // } // else if(Buf_USART3[1]==0x35 && c==0x61 &&Start_Rec==2 && Counter_USART==3) // { // Buf_USART3[2]=c; // Start_Rec=3; // } // else if(Buf_USART3[2]==0x61 && c==0x61 &&Start_Rec==3 && Counter_USART==4) // { // Buf_USART3[3]=c; // Start_Rec=4; // } // else if(Start_Rec==4 && Counter_USART<35 && c!= 0x35) // { // Counter_Rec++; // Buf_USART3[3+Counter_Rec]=c; // } // else // { // Counter_USART=0; // Start_Rec=0; // memset(Buf_USART3,0xFF,50); // } // if(Counter_USART>34) // { // Counter_USART=0; // Start_Rec=0; // memset(Buf_USART3,0xFF,50); // } // if(3+Counter_Rec==33) // { // Finish_Rec=1; // Start_Rec=0; // Counter_Rec=0; // Counter_USART=0; // } // else // Finish_Rec=0; 经分析发现,代码中只使用了接收数据中断。带有正确枕头,错误的位数,接收程序无法判断该包数据是否已经接受完成。经过查找资料发现有这几种方法可以解决这个问题。 1、设置接收超时 2、在协议中添加帧尾或者 协议前加一个字节长度不就完了,根据这个区接收,然后接收完了,告诉APP层或者协议解析层。这种方法实现的前提是大家都按这个做,否则通信失败,适合公司内部使用。 3、开启串口IDLE中断 我使用的是第三种方法 IDLE中断什么时候发生? IDLE就是串口收到一帧数据后,发生的中断。什么是一帧数据呢?比如说给单片机一次发来1个字节,或者一次发来8个字节,这些一次发来的数据,就称为一帧数据,也可以叫做一包数据。 如何判断一帧数据结束,就是我们今天讨论的问题。因为很多项目中都要用到这个,因为只有接收到一帧数据以后,你才可以判断这次收了几个字节和每个字节的内容是否符合协议要求。 看了前面IDLE中断的定义,你就会明白了,一帧数据结束后,就会产生IDLE中断。这个中断真是太TMD有用了。省去了好多判断的麻烦。 如何配置好IDLE中断? 下面我们就配置好串口IDLE断 这是串口CR1寄存器,其中,对bit4写1开启IDLE中断,对bit5写1开启接收数据中断。(注意:不同系列的STM32,对应的寄存器位可能不同) (RXNE中断和IDLE中断的区别? 当接收到1个字节,就会产生RXNE中断,当接收到一帧数据,就会产生IDLE中断。比如给单片机一次性发送了8个字节,就会产生8次RXNE中断,1次IDLE中断。) 这是状态寄存器,当串口接收到数据时,bit5就会自动变成1,当接收完一帧数据后,bit4就会变成1. 需要注意的是,在中断函数里面,需要把对应的位清0,否则会影响下一次数据的接收。比如RXNE接收数据中断,只要把接收到的一个字节读出来,就会清除这个中断。IDLE中断,如何是F0系列的单片机,需要用ICR寄存器来清除,如果是F1系列的单片机,清除方法是“先读SR寄存器,再读DR寄存器”。(我怎么知道?手册上写的) 程序如下: 首先代开IDLE中断和RXNE中断 USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //20190703 USART_ITConfig(USART3, USART_IT_IDLE, ENABLE); //20190705 USART_Cmd(USART3, ENABLE); 然后是中断处理函数 void USART3_IRQHandler(void) { u8 c,clear; if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) { Buf_USART3[Counter_USART++]=USART_ReceiveData(USART3); } if(USART_GetITStatus(USART3,USART_IT_IDLE) != RESET)//接收到一帧数据 { USART3->SR;//先读SR USART3->DR;//再读DR Finish_Rec=1;//j接收完成标志位 } } 这样串口接收到的数据放在Buf_USART3[Counter_USART++]中,当一帧数据接收完成后 对Finish_Rec=1;置位,表示已经完整的接收完一帧数据,告诉应用层,准备处理信息。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1800 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1629 浏览 1 评论
1096 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
735 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1684 浏览 2 评论
1944浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
745浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
578浏览 3评论
601浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
564浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-27 04:32 , Processed in 0.782005 second(s), Total 74, Slave 58 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号