OpenEdv-开源电子网

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

串口解析相关问题,请教一下论坛里的朋友们。,

[复制链接]

20

主题

99

帖子

0

精华

初级会员

Rank: 2

积分
178
金钱
178
注册时间
2020-6-21
在线时间
70 小时
发表于 2020-8-26 17:49:56 | 显示全部楼层 |阅读模式
1金钱
我有两个问题想向论坛里的朋友们请教。目前我定的协议是这样的
不定长,有包头,有数据长度和校验位

FF FF 为包头,后面一个字节为数据长度,后面数据长度个字节为内容


第一个问题:
我想的实现方法是这样的
首先定义一个数组 RES[RES_STA]
如果接收到FF,就执行1,如果没有就把[RES_STA]清零
执行1:判断是否再次接收到FF,如果没有就把RES_STA 清零 ,如果接收到就把接下收到的内容存到RES[RES_STA]中去

收到数据长度后,就接收数据长度个字节。

但是这样子做有一个问题,如果接收到和包头一样的数据,不就清零了吗?

第二个问题:
因为用了很多if的判断,很长很难看,有没有好一点的办法。

最佳答案

查看完整内容[请看2#楼]

如果是有协议的,每次发送完一帧,肯定有间隙,不会连续发,连续发你可能也处理不过来。如果有中断,则利用间隙时间做限定,把一帧数据接完,再去解析即可。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165508
金钱
165508
注册时间
2010-12-1
在线时间
2115 小时
发表于 2020-8-26 17:49:57 | 显示全部楼层
如果是有协议的,每次发送完一帧,肯定有间隙,不会连续发,连续发你可能也处理不过来。如果有中断,则利用间隙时间做限定,把一帧数据接完,再去解析即可。
回复

使用道具 举报

12

主题

3387

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8634
金钱
8634
注册时间
2020-5-11
在线时间
4082 小时
发表于 2020-8-26 18:53:24 | 显示全部楼层
以接收字节数为判断条件
int rec=0;//收到的字节数
if(rec==0)
{
if(rx==0xff)
   rec++;
}
else if(rec==1)
{
if(rx==0xff)
   rec++;
else
   rec=0;
}
else if .....................

还可以超时断帧
专治疑难杂症
回复

使用道具 举报

70

主题

6761

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
13086
金钱
13086
注册时间
2012-11-26
在线时间
3809 小时
发表于 2020-8-27 08:58:42 | 显示全部楼层
学学modbus的帧格式,参考一下,设计一个自己的帧格式
回复

使用道具 举报

2

主题

458

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4464
金钱
4464
注册时间
2018-5-14
在线时间
957 小时
发表于 2020-8-27 09:18:52 | 显示全部楼层
中断取数据并放入缓存区,来一次串口中断就打开定时器,并将定时器清零。定时器配置5ms中断。当定时器中断进入的时候,就意味着数据一帧数据接收完成。然后在主循环判断数据接收完成标志。然后判断缓存区的数据是否符合协议格式和校验。不是就清除缓存等待下一次数据,是就解析数据
回复

使用道具 举报

20

主题

99

帖子

0

精华

初级会员

Rank: 2

积分
178
金钱
178
注册时间
2020-6-21
在线时间
70 小时
 楼主| 发表于 2020-8-27 10:19:09 | 显示全部楼层
姚先起 发表于 2020-8-27 09:18
中断取数据并放入缓存区,来一次串口中断就打开定时器,并将定时器清零。定时器配置5ms中断。当定时器中断 ...

这个是不是用空闲中断。
我们老大让我用空闲中断加环队列去做

我想看看大家一般在处理这个问题的时候都是怎么做的。
回复

使用道具 举报

51

主题

2166

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10653
金钱
10653
注册时间
2017-4-14
在线时间
2780 小时
发表于 2020-8-27 10:35:01 | 显示全部楼层
回复

使用道具 举报

9

主题

219

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1426
金钱
1426
注册时间
2020-5-12
在线时间
392 小时
发表于 2020-8-27 10:41:04 | 显示全部楼层
本帖最后由 叶子君 于 2020-8-27 10:45 编辑
flyingPiggy 发表于 2020-8-27 10:19
这个是不是用空闲中断。
我们老大让我用空闲中断加环队列去做

空闲中断和定时器超时判断。我个人推荐定时器超时判断,环形队列是必须的。我的做法:用一个buff缓存接收的数据,定时器超时之后,写入环形队列。处理只要判断读环形队列,有就是读出一帧数据,这时候就可解析数据。
回复

使用道具 举报

0

主题

28

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
432
金钱
432
注册时间
2016-6-23
在线时间
66 小时
发表于 2020-8-27 10:43:38 | 显示全部楼层
你可以把包头多放一点。
回复

使用道具 举报

2

主题

458

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4464
金钱
4464
注册时间
2018-5-14
在线时间
957 小时
发表于 2020-8-27 11:08:13 | 显示全部楼层
flyingPiggy 发表于 2020-8-27 10:19
这个是不是用空闲中断。
我们老大让我用空闲中断加环队列去做

环形队列可以不需要的。给你看看我的做法typedef struct{
        uint8_t Buff[Buffsize];
        bool GetOk;
        bool GetStart;
        uint8_t GetAcc;
        uint8_t GetTimOut;
        uint8_t GetLen;
}Usart_GetBuff_Typedef;

typedef struct{
        uint8_t Buff[Buffsize];
        bool SendStatus;
        uint16_t SendLength;
        uint16_t SendAcc;
}Usart_SendBuff_Typedef;

串口接收
        if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
        {
                USART_ClearITPendingBit(USART1, USART_IT_RXNE);
                uint8_t Res = USART_ReceiveData(USART1);
                USART1_GetBuff.GetStart = 1;        //and the data receive is start
                USART1_GetBuff.Buff[USART1_GetBuff.GetAcc] = Res;//load data to get buff
                USART1_GetBuff.GetTimOut = 0;        //get data time out count clear
                USART1_GetBuff.GetAcc++;                                //get data pointer plus 1
                if(USART1_GetBuff.GetAcc >= Buffsize)//if the data is to big overflow the buff,set pointer to zero
                        USART1_GetBuff.GetAcc = 0;
        }

定时器1ms中断
void
USART1GetTimeOutCheck(void)
{
        if(USART1_GetBuff.GetStart == 1)
        {
                USART1_GetBuff.GetTimOut++;
                if(USART1_GetBuff.GetTimOut > 3)
                {
                        USART1_GetBuff.GetTimOut = 0;
                        USART1_GetBuff.GetLen = USART1_GetBuff.GetAcc;
                        USART1_GetBuff.GetOk = 1;
                        USART1_GetBuff.GetAcc = 0;
                        USART1_GetBuff.GetStart = 0;
                }
        }
}

主循环处理
                if(USART1_GetBuff.GetOk)
                {
                        USART1_GetBuff.GetOk=0;
                        USART2_Send(USART1_GetBuff.Buff,USART1_GetBuff.GetLen);
                }

回复

使用道具 举报

2

主题

582

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2690
金钱
2690
注册时间
2014-5-23
在线时间
188 小时
发表于 2020-8-27 11:25:02 | 显示全部楼层
搞个缓存区,在加个状态机
回复

使用道具 举报

9

主题

219

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1426
金钱
1426
注册时间
2020-5-12
在线时间
392 小时
发表于 2020-8-27 11:51:57 | 显示全部楼层
姚先起 发表于 2020-8-27 11:08
环形队列可以不需要的。给你看看我的做法typedef struct{
        uint8_t Buff;
        bool GetOk;

你这种做法的话,如果处理串口数据太慢的话,是不是会丢数据。
回复

使用道具 举报

2

主题

458

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4464
金钱
4464
注册时间
2018-5-14
在线时间
957 小时
发表于 2020-8-27 12:39:54 | 显示全部楼层
叶子君 发表于 2020-8-27 11:51
你这种做法的话,如果处理串口数据太慢的话,是不是会丢数据。

没丢过数据,而且处理又没有复杂的逻辑计算,就简单的存个数据。怎么会丢,总比在中断里面判断每个数据,然后再来校验来的好。
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-5-17 05:26

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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