OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 20728|回复: 13

研究串口接收如何判断一帧数据接收完毕的几种方式

[复制链接]

12

主题

29

帖子

0

精华

初级会员

Rank: 2

积分
131
金钱
131
注册时间
2012-1-13
在线时间
29 小时
发表于 2017-9-10 22:48:40 | 显示全部楼层 |阅读模式
1金钱
1.设定好通讯协议,如包头+长度+数据+校验+包尾,那么中断中每收到一个字节就判断,直到收到包尾为止。这是51时代用得比较多的状态机接收流程。
但如果由于接收中断被嵌套,或干扰等原因导致一帧数据的后部分丢失,就是说接收不到包尾,那么这个状态机如何能自动复位以便接收下一帧?

2.串口空闲中断也是用得比较多的一种方法,但是波特率较高的时候,空闲中断的触发时间相应变短,使得接收中断不被打断的要求变高,如果接收中断被耽误了,从而触发空闲中断,也是收不到完整数据。

3.定时器中断代替串口空闲中断,这个可以避免串口空闲中断时间不够的问题,因为这个定时器中断可以自己设置。但是一个串口需要搭配一个定时器使用,不爽。

4.串口接收只把数据放到缓存,此外不做任何事情。然后在另一个线程不断parse这个缓存,从头开始找其中有没有符合一帧的数据,如果有就是解析,同时将这一帧从缓存中删掉,如果没有就什么也不做。这样的程序就不用管一帧是否结束,可以较好的适应各种收不全、丢数据的问题。
问题是,这个思路我在PC上位机中用过没问题,但是在STM32要是我定义的缓存是一个固定大小字节数组,当我解析到了一帧数据后,如何这帧数据从缓存中去掉,即如何做一个动态数组的结构之类的?

大家有没有什么好的办法分享?

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

4

主题

133

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3860
金钱
3860
注册时间
2016-6-11
在线时间
709 小时
发表于 2017-9-10 23:17:31 | 显示全部楼层
我是这样做得,定义帧数据结构,帧头、长度、校验、帧尾。收字节时开启定时器,如果超时,重来。
回复

使用道具 举报

3

主题

178

帖子

0

精华

高级会员

Rank: 4

积分
524
金钱
524
注册时间
2016-12-31
在线时间
195 小时
发表于 2017-9-10 23:31:39 来自手机 | 显示全部楼层
顶!!
回复

使用道具 举报

12

主题

29

帖子

0

精华

初级会员

Rank: 2

积分
131
金钱
131
注册时间
2012-1-13
在线时间
29 小时
 楼主| 发表于 2017-9-11 00:13:10 | 显示全部楼层
jxcrgt35 发表于 2017-9-10 23:17
我是这样做得,定义帧数据结构,帧头、长度、校验、帧尾。收字节时开启定时器,如果超时,重来。

超时时间如何设置?是个固定的时间,还是根据收到的长度来设置?
回复

使用道具 举报

23

主题

344

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2305
金钱
2305
注册时间
2017-7-6
在线时间
280 小时
发表于 2017-9-11 08:38:07 | 显示全部楼层
楼上,肯定是固定几十MS没收到下一个数据就判定接收完成啦,不过这种方法比较多个定时器中断而且比较频繁。
回复

使用道具 举报

17

主题

587

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4467
金钱
4467
注册时间
2013-6-27
在线时间
565 小时
发表于 2017-9-11 08:53:16 | 显示全部楼层
状态机接收方式加入:字节间超时,及帧之间超时。这样状态机不会死机可以自动复位状态机。
串口还有一直接收循环队列方式接收及解析,可以去了解。
让我们的思维驾驭在电的速度之上!
回复

使用道具 举报

2

主题

23

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
395
金钱
395
注册时间
2016-5-4
在线时间
53 小时
发表于 2017-10-25 09:08:45 | 显示全部楼层
动态数组结构用链表就可以了!查找,删除和插入都比较方便。
回复

使用道具 举报

11

主题

1041

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3696
金钱
3696
注册时间
2011-5-23
在线时间
2008 小时
发表于 2017-10-25 09:10:19 | 显示全部楼层
项目中都是4点全用的

1+4 由应用程序处理
2+3 由驱动处理,以提高驱动程序的效率,同时也要有一定的实时性。
RT-Thread RTOS 音频,WIFI,蓝牙
回复

使用道具 举报

0

主题

6

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2017-10-16
在线时间
3 小时
发表于 2017-11-6 22:41:06 | 显示全部楼层
楼上正解

随便说一下,例程里的uart3.c里就用到字节间超时处理
void USART3_IRQHandler(void)
{
        u8 res;            
        OSIntEnter();   
        if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)//½ÓÊÕµ½Êý¾Ý
        {         
                res=USART_ReceiveData(USART3);                                 
                if((USART3_RX_STA&(1<<15))==0)//&frac12;&Oacute;&Ecirc;&Otilde;&Iacute;ê&micro;&Auml;&Ograve;&raquo;&Aring;ú&Ecirc;&yacute;&frac34;&Yacute;,&raquo;&sup1;&Atilde;&raquo;&Oacute;&ETH;±&raquo;&acute;&brvbar;&Agrave;í,&Ocirc;ò&sup2;&raquo;&Ocirc;&Ugrave;&frac12;&Oacute;&Ecirc;&Otilde;&AElig;&auml;&Euml;&ucirc;&Ecirc;&yacute;&frac34;&Yacute;
                {
                        if(USART3_RX_STA<USART3_MAX_RECV_LEN)        //&raquo;&sup1;&iquest;&Eacute;&Ograve;&Ocirc;&frac12;&Oacute;&Ecirc;&Otilde;&Ecirc;&yacute;&frac34;&Yacute;
                        {
                                TIM_SetCounter(TIM7,0);//&frac14;&AElig;&Ecirc;&yacute;&AElig;÷&Ccedil;&aring;&iquest;&Otilde;
                                if(USART3_RX_STA==0)                                 //&Ecirc;&sup1;&Auml;&Uuml;&para;¨&Ecirc;±&AElig;÷7&micro;&Auml;&Ouml;&ETH;&para;&Iuml;
                                {
                                        TIM_Cmd(TIM7,ENABLE);//&Ecirc;&sup1;&Auml;&Uuml;&para;¨&Ecirc;±&AElig;÷7
                                }
                                USART3_RX_BUF[USART3_RX_STA++]=res;        //&frac14;&Ccedil;&Acirc;&frac14;&frac12;&Oacute;&Ecirc;&Otilde;&micro;&frac12;&micro;&Auml;&Ouml;&micro;         
                        }else
                        {
                                USART3_RX_STA|=1<<15;                                //&Ccedil;&iquest;&Ouml;&AElig;±ê&frac14;&Ccedil;&frac12;&Oacute;&Ecirc;&Otilde;&Iacute;ê&sup3;&Eacute;
                        }
                }
        }                                                                                           
        OSIntExit();                                                                                           
}   
回复

使用道具 举报

1

主题

3

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2018-2-25
在线时间
2 小时
发表于 2018-2-25 21:22:10 | 显示全部楼层
消息队列吧
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2018-2-26 01:27:01 | 显示全部楼层
你应该学习下modbus,疑虑就没了。
回复

使用道具 举报

8

主题

569

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2363
金钱
2363
注册时间
2015-5-8
在线时间
320 小时
发表于 2018-2-26 09:06:14 | 显示全部楼层
用链表哦
回复

使用道具 举报

33

主题

218

帖子

0

精华

高级会员

Rank: 4

积分
568
金钱
568
注册时间
2015-1-12
在线时间
75 小时
发表于 2022-2-22 15:07:08 | 显示全部楼层
学习了总结了
回复

使用道具 举报

19

主题

334

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1108
金钱
1108
注册时间
2018-11-6
在线时间
240 小时
发表于 2022-7-14 15:03:09 | 显示全部楼层
楼主如果学习过MODBUS或者使用过DMA就没有这方面的疑惑啦。

    1、2帧报文之间肯定会有一定的间隔时间
            如果接收到一个字符后,检测到3.5倍的时间都没有收到字符,就认为一帧报文接收完毕。
    2、STM32的DMA用的是空中断,也是上述原理
   
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 18:14

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表