完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
设计思路
这里设计的难点在于,如何把控tail这个写地址,每增加一个数据时tail自增,在写的过程中,如果使用缓冲区的所有空间,那么head等于tail的时候,这个情况可能是空或者满,需要在程序设计时候,多加留意。 在实际项目使用中,仍需要考虑的两个问题: 读多个字节时,缓冲区内可读数量比用户想读的个数少,这时候是逐字节把可读的都读出来,还是直接报错? 写多个字节时,缓冲区内可写数量比用户想写的个数少,这时候是逐字节把可写的都写满,还是直接报错? 鉴于这样的问题,在读多字节和写多字节这两个接口上增加一个变量mode,用于设定接口在读写多字节时遇到长度超出范围,是逐字节继续处理还是直接报错。 还有,相比于上一篇文章中参考的源码,这里的设计思路采用的是地址指针的方式,而不是偏移量。 并且为了区别于缓冲区空或者满,将牺牲掉一个字节的空间:当缓冲区空的时候head等于tail,当缓冲区满的时候head在tail相邻的后一个位置。 本次的设计,使用head指向缓冲区中可读数据的首地址,使用tail指向缓冲区中可读数据的末地址(同时这也是可写数据的首地址): 数据流是55 04 18 02 07 B7这样的一连串16进制数,接收端先收到的是0x55,后收到的是0x04,以这样的顺序逐字节通过物理层接口接收。这也是一个数据包的常规帧结构,也符合人从左到右的阅读顺序。 所以在这里以head指向的是数据包的头,tail指向数据包的尾,head到tail之间就是一个可读数据的范围,同时,tail指向的是可写区域的首地址,当有新的数据进来时,新的数据会被从tail地址继续写到内存,而后tail在环内递增。 知道了循环缓冲区的这几个属性:缓冲区大小、缓冲区在内存中的地址范围、存取数据时的读写地址。可根据这些属性,构造一个循环缓冲区的结构体: typedef struct{ uint32_t size; uint8_t *head; uint8_t *tail; uint8_t *buff; }rb_t; ringbuffer简写rb,其中 size表示用户申请成功的或定义的buffer空间大小; head是一个地址指针,指向缓冲区读的首地址; tail也是个地址指针,指向缓冲区读的末地址(也就是写的首地址); buff还是一个指针,一直指向用户定义或者程序动态申请的内存buffer首地址。 当我们需要使用环形缓冲区前,需要定义数组变量或者申请内存,作为数据实际存储的地方,同时定义一个rb_t的结构体,用于关联数组变量或者内存空间。 功能模块将完成以下接口: 初始化 可读数量 可写数量 读一个字节 读多个字节 写一个字节 写多个字节 查看指定偏移的数据 查看指定数据是否在缓冲区并取其在内存的地址 复位清空 关于命名,暂且做个说明:dcclib是DigCore_Library的简写,这是功能模块库层的代码;rb是ringbuffer模块简写。 |
|
|
|
可读数量
head指向的是可读数据的首地址,该地址内是有数据可以读的; hail指向的是可读数据的末地址,该地址内没有数据可读,同时tail指向的是一个空的字节,作为写的首地址。 |
|
|
|
|
|
|
|
|
|
|
|
读多个字节
读多个字节,必然是基于读一个字节的基础上实现的。这里相比于前一篇文章提到的参考项目源码,不同的是增加了读模式的选择,当要读的数据个数大于可读数量时,可以利用mode来选择是否仍然逐字节地把能读的都读出来。 如果在调用接口时mode设为FORCE的强制读取,要读的数据个数大于可读数量时,将以RET_RB_RDWRN的错误返回码,旨在说明读取的数据不足,但是也已经把可读的都读出了! |
|
|
|
只有小组成员才能发言,加入小组>>
11976 浏览 0 评论
5400 浏览 3 评论
17325 浏览 6 评论
2385 浏览 1 评论
3008 浏览 1 评论
1194浏览 2评论
1717浏览 2评论
594浏览 1评论
571浏览 1评论
942浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-4-20 07:18 , Processed in 1.148851 second(s), Total 76, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号