【ESP8266】app_IR_TxRx_demo中的RingBuf代码透析
来源:互联网 发布:淘宝小野妹子是正品吗 编辑:程序博客网 时间:2024/05/18 02:48
在裸机单片机开发中,有时候需要用到先入先出队列(FIFO),可是一般的裸机开发环境是没有一个库函数给开发者使用队列的,这个时候需要自己写队列函数。后来,我在开发ESP8266和基于cc2530的contiki系统时,都发现这些系统下面有一个RingBuf文件,说明这个RingBuf就是为了解决裸机单片机开发中队列的问题。下面我来分析一下ESP8266中的RingBuf代码。
阅读代码时第一步都是先看数据结构,那么来看看RINGBUF数据结构。
typedef struct{ uint8_t* p_o; /**< Original pointer */ uint8_t* volatile p_r; /**< Read pointer */ uint8_t* volatile p_w; /**< Write pointer */ volatile int32_t fill_cnt; /**< Number of filled slots */ int32_t size; /**< Buffer size */}RINGBUF;
该结构体很简单,p_o是用来保存初始地址的指针,p_r是读取指针,p_w是写入指针,fill_cnt用来计数的,每写入一个数据就加1,size是保存该数组队列的大小。
初始化函数RINGBUF_Init:
/** \brief init a RINGBUF object* \param r pointer to a RINGBUF object* \param buf pointer to a byte array* \param size size of buf* \return 0 if successfull, otherwise failed*/int16_t RINGBUF_Init(RINGBUF *r, uint8_t* buf, int32_t size){ if (r == NULL || buf == NULL || size < 2) return -1; //如果r和buf传入的参数为空、size数组大小小于2,则初始化失败 r->p_o = r->p_r = r->p_w = buf; //初始化p_o,p_r,p_w r->fill_cnt = 0; //初始化fill_cnt r->size = size; //初始化size return 0;}
写入一个数据RINGBUF_Put:
/*** \brief put a character into ring buffer* \param r pointer to a ringbuf object* \param c character to be put* \return 0 if successfull, otherwise failed*/int16_t RINGBUF_Put(RINGBUF *r, uint8_t c){ if (r->fill_cnt >= r->size){ printf("BUF FULL\n"); return -1; // 如果缓冲区满了,则返回-1错误 } r->fill_cnt++; // 每写入一个字节,则加1计数 *r->p_w++ = c; // 把数据放入缓冲区,并指向下一个地址 if (r->p_w >= r->p_o + r->size) // 如果写入指针超过了缓冲区末尾,则 r->p_w = r->p_o; // 把指针指向原点,这就是RING的含义 return 0;}
读取数据RINGBUF_Get:
/*** \brief get a character from ring buffer* \param r pointer to a ringbuf object* \param c read character* \return 0 if successfull, otherwise failed*/int16_t RINGBUF_Get(RINGBUF *r, uint8_t* c, int32_t length){ int32_t cnt = 0; if (r->fill_cnt <= 0) return -1; // 如果缓冲区为空,则返回-1错误 if (length>r->fill_cnt){ length = r->fill_cnt; // 最大只能读取缓冲区拥有数据的长度 } int i; cnt = r->fill_cnt; for (i = 0; i<length; i++) { r->fill_cnt--; // 每读取一个字节,计数减1 *c = *r->p_r++; // 返回数据给*c *c++; if (r->p_r >= r->p_o + r->size) // 如果读取指针超过了缓冲区末尾,则 r->p_r = r->p_o; // 把指针指向原点 } return 0;}
主函数及其他,这里使用VS2013开发环境测试该RingBuf:
#define RX_RCV_LEN 128RINGBUF IR_RX_BUFF;uint8_t ir_rx_buf[RX_RCV_LEN];#define READ10CHAR_TEST 0int _tmain(int argc, _TCHAR* argv[]){ //RINGBUF初始化 //把ir_rx_buf初始化为一个RingBuf,使用IR_RX_BUFF结构体保存信息,长度为sizeof(ir_rx_buf) RINGBUF_Init(&IR_RX_BUFF, ir_rx_buf, sizeof(ir_rx_buf)); int i = 10; while (i--){#if READ10CHAR_TEST RINGBUF_Put(&IR_RX_BUFF, '1'+i);#else RINGBUF_Put(&IR_RX_BUFF, i); //放入10个字节到IR_RX_BUFF中#endif }#if READ10CHAR_TEST uint8_t data[11] = {0}; RINGBUF_Get(&IR_RX_BUFF, data, 10); //从IR_RX_BUFF读取1个字节 printf("RingBuf pop : %s \r\n", data); //打印该字节#else uint8_t data; while (IR_RX_BUFF.fill_cnt){ i = 10; while (i--){ RINGBUF_Get(&IR_RX_BUFF, &data, 1); //从IR_RX_BUFF读取1个字节 printf("RingBuf pop : %d \r\n", data); //打印该字节 } }#endif return 0;}
当READ10CHAR_TEST置0时,每次从RINGBUF读取一字节,打印出的信息为:
RingBuf pop : 9
RingBuf pop : 8
RingBuf pop : 7
RingBuf pop : 6
RingBuf pop : 5
RingBuf pop : 4
RingBuf pop : 3
RingBuf pop : 2
RingBuf pop : 1
RingBuf pop : 0
请按任意键继续…
当READ10CHAR_TEST置1时,一次性从RINGBUF读取10字节,打印出的信息为:
RingBuf pop : :987654321
请按任意键继续…
扩展
后面扩展了一下这个RingBuf的功能,增加了两个函数。
//清空缓冲区int16_t RINGBUF_Clr(RINGBUF *r){ memset(r->p_o, 0, r->size); r->p_r = r->p_w = r->p_o; r->fill_cnt = 0; return 0;}//读取第index个数据uint8_t RINGBUF_Read(RINGBUF *r, int32_t index){ uint8_t data = 0; if (r->fill_cnt <= 0) return 0; // 如果缓冲区为空,则返回0 if (index > r->fill_cnt){ index = r->fill_cnt; // 最大只能读取缓冲区拥有数据的长度 } if (r->p_r + index >= r->p_o + r->size){ // 如果读取的index超过了缓冲区末尾,则 //r->p_r = r->p_o; // 从头开始计算index index = index - (r->p_o + r->size - r->p_r); } data = r->p_r[index]; //读取第index个数据 return data;}
- 【ESP8266】app_IR_TxRx_demo中的RingBuf代码透析
- C中的->透析
- ESP8266开发中的流水账
- arduino esp8266 接线和代码、
- ESP8266
- ESP8266
- 透析设计模式中的 策略模式
- ESP8266之24C02 IIC驱动代码
- 利用EasyTransfer转移ESP8266中的数据
- ringbuf的一个简单实现
- 一、ESP8266之维航机器人软件编辑器在ESP8266中的应用
- 透析struts中的redirect="true"与redirect="false"
- 【esp8266】MCU下arduino uno添加LED开关代码示例
- TCP粘包处理-RingBuf方法
- 一个环形缓冲(ringbuf)的简单实现
- 透析教育、透析考研
- 透析Office
- 透析适配器!
- 我的第一篇博客
- Uva 10006 Carmichael Numbers(数论、快速幂、素数筛法)
- Android 开发之 App 启动时间统计
- HDU 2044 一只小蜜蜂...
- poj2388Who's in the Middle
- 【ESP8266】app_IR_TxRx_demo中的RingBuf代码透析
- POJ 2418 (简单map)
- poj1511——Invitation Cards(SPFA+邻接表)
- HDU5477 A Sweet Journey
- 运用js简单制作图片的左右移动
- 数字间的转换(进制转换、小数化分数)
- ubuntu下安装vim失败,不满足依赖关系
- hdoj 1513 Palindrome (LCS 变形)
- 系统蓝屏故障之显卡驱动问题