OpenEdv-开源电子网

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

利用循环队列接收串口数据实例!!!

[复制链接]

15

主题

866

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
7206
金钱
7206
注册时间
2016-11-30
在线时间
622 小时
发表于 2019-3-19 17:11:02 | 显示全部楼层 |阅读模式
发现坛子里总是有人在问串口接收的问题,所以分享一下我一直用的一个方案,希望能帮到大家。

总体思路是:
1.利用串口接收中断进行数据接收。利用串口空闲中断统计接收到完整的数据包的个数。
ps:如果是485接口,利用串口空闲中断也可以判断总线是否处于空闲状态,方便判断485何时进行发送。
2.使用循环队列,需要开辟一个较大的全局buf,建议至少开辟大于数据包最大长度的3倍空间。
3.串口接收中断中使用以下2个函数把数据入队到循环队列里边
HAL_UART_Receive(&hlpuart1,&data,1,1000);//串口接收数据
Enqueue_One_Byte(&queue_rs485,data);//数据直接放入循环队列
4.主程序中直接判断数据包个数大于0再开始进行数据处理。
5.数据包大于0的情况下,再按照通信协议,逐字节进行判断,错误就直接出队扔掉,
正确则继续判断,直到捕获一包正确的数据就把整包数据出队。
6.出队正确后再按照通信协议进行数据处理就可以了。


串口接收程序.zip

20.47 MB, 下载次数: 2360

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

使用道具 举报

2

主题

685

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3447
金钱
3447
注册时间
2017-7-4
在线时间
869 小时
发表于 2020-10-4 15:04:43 | 显示全部楼层
回复 支持 1 反对 0

使用道具 举报

0

主题

27

帖子

0

精华

初级会员

Rank: 2

积分
165
金钱
165
注册时间
2019-3-15
在线时间
30 小时
发表于 2020-3-18 15:36:17 | 显示全部楼层
看看吧,我是直接收到两包后比较处理的。循环列队学习一下。
回复 支持 1 反对 0

使用道具 举报

7

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
55
金钱
55
注册时间
2018-2-27
在线时间
27 小时
发表于 2019-3-19 17:56:51 | 显示全部楼层
赞 ,谢谢大佬 ,我去琢磨琢磨
回复 支持 反对

使用道具 举报

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4306
金钱
4306
注册时间
2018-6-30
在线时间
808 小时
发表于 2019-3-19 18:29:27 | 显示全部楼层
不错,环形队列用来处理485数据比较好,谢谢分享
业精于勤荒于嬉;行成于思毁于随!
回复 支持 反对

使用道具 举报

0

主题

9

帖子

0

精华

初级会员

Rank: 2

积分
174
金钱
174
注册时间
2019-5-9
在线时间
65 小时
发表于 2019-5-9 13:42:14 | 显示全部楼层
正是需要的
回复 支持 反对

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
31
金钱
31
注册时间
2019-5-6
在线时间
4 小时
发表于 2019-9-21 08:45:51 | 显示全部楼层
可以 有点东西的
回复 支持 反对

使用道具 举报

0

主题

5

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2019-10-29
在线时间
8 小时
发表于 2020-3-17 16:29:35 | 显示全部楼层
楼主这样开辟太占空间了,有没有办法可以队列元素满了,处理过了便清空队列呢
回复 支持 反对

使用道具 举报

15

主题

866

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
7206
金钱
7206
注册时间
2016-11-30
在线时间
622 小时
 楼主| 发表于 2020-3-18 09:14:08 | 显示全部楼层
daqunZhu 发表于 2020-3-17 16:29
楼主这样开辟太占空间了,有没有办法可以队列元素满了,处理过了便清空队列呢

循环队列本来就是边读边清的,至于空间大小,你得根据你的数据长度去进行考量
回复 支持 反对

使用道具 举报

0

主题

14

帖子

0

精华

新手上路

积分
49
金钱
49
注册时间
2020-10-3
在线时间
8 小时
发表于 2020-10-4 11:15:25 | 显示全部楼层
有点复杂哈哈哈哈,对菜鸡不是那么友好
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2017-12-12
在线时间
5 小时
发表于 2020-11-3 19:00:42 | 显示全部楼层
牛逼啊,顶一个
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2020-12-8
在线时间
4 小时
发表于 2021-1-11 09:18:05 | 显示全部楼层
学习下,谢谢大佬
回复 支持 反对

使用道具 举报

10

主题

560

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1739
金钱
1739
注册时间
2014-6-27
在线时间
943 小时
发表于 2021-1-11 11:09:37 | 显示全部楼层
想法很好,但是思路不对,队列不是这么用的。首先,中断接收,不会丢数据,你应该考虑在接收到一帧数据(按照协议)后,再放队列,其次,队列使用不用这么复杂,一般队列出数据平均速度大于队列进数据的,就是说队列一 有数据马上处理的,所以队列缓存一般几个深度就行,8或者16,队列何来空和满?就算满了,就从头放,只要处理平均速度大于进队列数据,先来的数据就不会被覆盖。
void write_rf_fifo(u64 dat)//写FIFO,如果是一帧数据,写数据首地址
{
       
                                                                                                                                fifo_buf[write_fifo_cnt].rev_dat=dat;

                                                                                                                                write_fifo_cnt%=  RF_FIFO_BUF_MAX_LEN;
                                                                                       
                                       
}
u64 read_rf_fifo()//读FIFO,读写变量不一样就读,如果是一帧数据,返回数据首地址
{
                                u64 x;
                                        x=fifo_buf[read_fifo_cnt++].rev_dat;
                read_fifo_cnt%=  RF_FIFO_BUF_MAX_LEN;
                                return x;
}
if(write_fifo_cnt!=read_fifo_cnt)//读写不一样,FIFO有数据,处理
                                                        {
                                                                  
read_rf_fifo();
                                                                                       
//处理
                                                        }
回复 支持 反对

使用道具 举报

1

主题

7

帖子

0

精华

新手上路

积分
21
金钱
21
注册时间
2021-1-13
在线时间
5 小时
发表于 2021-1-27 22:37:25 | 显示全部楼层
同小白
回复 支持 反对

使用道具 举报

1

主题

7

帖子

0

精华

新手上路

积分
21
金钱
21
注册时间
2021-1-13
在线时间
5 小时
发表于 2021-1-27 22:41:35 | 显示全部楼层
TinyBoy 发表于 2021-1-11 11:09
想法很好,但是思路不对,队列不是这么用的。首先,中断接收,不会丢数据,你应该考虑在接收到一帧数据(按 ...

我也小白,可以请问大佬一下吗?接收到一帧数据后,怎么计算得到它的帧头和帧尾,怎么求这一帧数据的和?仅仅知道求帧数据的长度是  数据&3fff   求低八位是0xff
QQ截图20210127223549.png
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-24 11:46

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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