Chinaunix首页 | 论坛 | 博客
  • 博客访问: 804716
  • 博文数量: 281
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2770
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-02 19:45
个人简介

邮箱:zhuimengcanyang@163.com 痴爱嵌入式技术的蜗牛

文章分类
文章存档

2020年(1)

2018年(1)

2017年(56)

2016年(72)

2015年(151)

分类: 嵌入式

2015-12-11 11:47:47

可能出现的情景:
在单任务系统中,按键后若某功能的程序执行事件很长,在次期间再有按键是无效的,因为此时CPU没有为键盘服务。这在连续快速输入按键时,很有可能造成漏键。
解决漏键问题的方式是采用FIFO,在键盘查询中断内一旦发现有新的按键,则把键值压入FIFO中。即使主循环周期较长,在两次读取键值之间用户进行了多次按键操作,这些键值会依次存于FIFO中,等待主循环的读取,只要缓冲区足够大,多次连续按键就不会漏掉。而且在主循环中通过GetKey()函数可以随时读FIFO获取键值。这种方法是非阻塞的。
FIFO数据结构体:

点击(此处)折叠或打开

  1. typedef struct
  2. {
  3.     int16_t front;
  4.     int16_t rear;
  5.     int16_t count;
  6.     uint8_t *store;
  7.     uint8_t entry_size;
  8.     int16_t max_entries;
  9. }str_rbuf;
int16_t front: 代表写指针(这里FIFO为数组形式,front代表数组的下标)
int16_t rear: 代表读指针
int16_t count:表示目前FIFO中元素的个数
uint8_t *store: 指向FIFO缓冲区首地址的指针
uint8_t entry_size: 表示FIFO中存储元素的长度大小(字节单位)
int16_t max_entries: 表示存储元素的最大值。
其中,前三项是一直在变化的(可变参数),而后三项是初始化就已经确定,不需要改变的(固定参数)。


相关函数
1. 初始化函数

点击(此处)折叠或打开

  1. #define B_EMPTY -1

  2. B_RET rbuf_init(str_rbuf * rbuf, uint8_t * store, uint8_t entry_size, int16_t max_entries)
  3. {
  4.     if (0x7FFF == max_entries)
  5.     {
  6.         return (B_RET_INVALID);
  7.     }
  8.     rbuf->store = store;
  9.     rbuf->entry_size = entry_size;
  10.     rbuf->max_entries = max_entries;
  11.     rbuf->front = B_EMPTY;
  12.     rbuf->rear = B_EMPTY;
  13.     rbuf->count = 0;
  14.     return (B_RET_OK);
  15. }
比如:
static str_rbuf rec_buf;
static uint8_t receive_buffer[100];

// 初始化存储FIFO:rec_buf, 其指向receive_buffer,元素大小为1Byte,最大可以存储的元素个数为:100
rbuf_init ( &rec_buf, receive_buffer, 1, 100 ); 
2. FIFO清空操作

点击(此处)折叠或打开

  1. B_RET rbuf_clear(str_rbuf * rbuf)
  2. {
  3.     rbuf->front = B_EMPTY;
  4.     rbuf->rear = B_EMPTY;
  5.     rbuf->count = 0;
  6.     return (B_RET_OK);
  7. }
可变的参数,都回到初始化状态。

3. 写数据到FIFO中

点击(此处)折叠或打开

  1. B_RET rbuf_push(str_rbuf * rbuf, uint8_t * data)
  2. {
  3.     if (rbuf->count >= (rbuf->max_entries))
  4.     {
  5.         return (B_RET_FULL);
  6.     }
  7.     if (rbuf->front >= (rbuf->max_entries - 1) // rbuf->front的范围【0, rbuf->max_entries - 1】,为数组的下标
  8.     {
  9.         rbuf->front = B_EMPTY;
  10.     }
  11.     rbuf->front++;
  12.     rbuf->count++;
  13.     for (uint8_t i = 0; i < rbuf->entry_size; i++)  // 这里是循环读一个元素(元素可能是1个字节,或者多个字节
  14.     {
  15.         rbuf->store[((rbuf->front * rbuf->entry_size) + i)] = data[i];
  16.     }
  17.     return (B_RET_OK);
  18. }

4. 从FIFO中读数据

点击(此处)折叠或打开

  1. B_RET rbuf_pull(str_rbuf * rbuf, uint8_t * data)
  2. {
  3.     if (rbuf->count == 0)
  4.     {
  5.         return (B_RET_EMPTY);
  6.     }
  7.     if (rbuf->rear >= (rbuf->max_entries - 1))
  8.     {
  9.         rbuf->rear = B_EMPTY;
  10.     }
  11.     rbuf->rear++;
  12.     rbuf->count--;
  13.     for (uint8_t i = 0; i < rbuf->entry_size; i++// 这里是循环读一个元素(元素可能是1个字节,或者多个字节
  14.     {
  15.         data[i] = rbuf->store[((rbuf->rear * rbuf->entry_size) + i)] ;
  16.     }

  17.     /* FIFO 数据读取完了,则读写指针回到起点,而不是说读写指针一直往上累加。需要注意这里*/
  18.     if (rbuf->count == 0)
  19.     {
  20.         rbuf->front = B_EMPTY;
  21.         rbuf->rear = B_EMPTY;
  22.     }
  23.     return (B_RET_OK);
  24. }

5. 读指定位置处的元素

点击(此处)折叠或打开

  1. /* 实现纯粹读指定地址的数据,不改写读指针参数 */
  2. B_RET rbuf_read(str_rbuf * rbuf, uint8_t index, uint8_t * data)
  3. {
  4.     if (rbuf->count == 0)
  5.     {
  6.         return (B_RET_EMPTY);
  7.     }

  8.     for (uint8_t i = 0; i < rbuf->entry_size; i++)
  9.     {
  10.         data[i] = rbuf->store[((index * rbuf->entry_size) + i)] ;
  11.     }
  12.     return (B_RET_OK);
  13. }

6. 读取FIFO中元素的实际个数

点击(此处)折叠或打开

  1. /* 返回buffer 里面数据的长度 */
  2. uint16_t rbuf_nr_of_items(str_rbuf * rbuf)
  3. {
  4.     return ( rbuf->count );
  5. }






源代码:

点击(此处)折叠或打开

  1. #include "ring_buffer.h"

  2. #define B_EMPTY -1

  3. B_RET rbuf_init(str_rbuf * rbuf, uint8_t * store, uint8_t entry_size, int16_t max_entries)
  4. {
  5.     if (0x7FFF == max_entries)
  6.     {
  7.         return (B_RET_INVALID);
  8.     }
  9.     rbuf->store = store;
  10.     rbuf->entry_size = entry_size;
  11.     rbuf->max_entries = max_entries;
  12.     rbuf->front = B_EMPTY;
  13.     rbuf->rear = B_EMPTY;
  14.     rbuf->count = 0;
  15.     return (B_RET_OK);
  16. }

  17. B_RET rbuf_clear(str_rbuf * rbuf)
  18. {
  19.     rbuf->front = B_EMPTY;
  20.     rbuf->rear = B_EMPTY;
  21.     rbuf->count = 0;
  22.     return (B_RET_OK);
  23. }

  24. B_RET rbuf_push(str_rbuf * rbuf, uint8_t * data)
  25. {
  26.     if (rbuf->count >= (rbuf->max_entries))
  27.     {
  28.         return (B_RET_FULL);
  29.     }
  30.     if (rbuf->front >= (rbuf->max_entries - 1))
  31.     {
  32.         rbuf->front = B_EMPTY;
  33.     }
  34.     rbuf->front++;
  35.     rbuf->count++;
  36.     for (uint8_t i = 0; i < rbuf->entry_size; i++)
  37.     {
  38.         rbuf->store[((rbuf->front * rbuf->entry_size) + i)] = data[i];
  39.     }
  40.     return (B_RET_OK);
  41. }

  42. B_RET rbuf_pull(str_rbuf * rbuf, uint8_t * data)
  43. {
  44.     if (rbuf->count == 0)
  45.     {
  46.         return (B_RET_EMPTY);
  47.     }
  48.     if (rbuf->rear >= (rbuf->max_entries - 1))
  49.     {
  50.         rbuf->rear = B_EMPTY;
  51.     }
  52.     rbuf->rear++;
  53.     rbuf->count--;
  54.     for (uint8_t i = 0; i < rbuf->entry_size; i++)
  55.     {
  56.         data[i] = rbuf->store[((rbuf->rear * rbuf->entry_size) + i)] ;
  57.     }

  58.     /* FIFO 数据读取完了,则读写指针回到起点,不管FIFO 里面是不是存满了。*/
  59.     if (rbuf->count == 0)
  60.     {
  61.         rbuf->front = B_EMPTY;
  62.         rbuf->rear = B_EMPTY;
  63.     }
  64.     return (B_RET_OK);
  65. }

  66. /* 实现纯粹读指定地址的数据,不改写读指针参数 */
  67. B_RET rbuf_read(str_rbuf * rbuf, uint8_t index, uint8_t * data)
  68. {
  69.     if (rbuf->count == 0)
  70.     {
  71.         return (B_RET_EMPTY);
  72.     }

  73.     for (uint8_t i = 0; i < rbuf->entry_size; i++)
  74.     {
  75.         data[i] = rbuf->store[((index * rbuf->entry_size) + i)] ;
  76.     }
  77.     return (B_RET_OK);
  78. }

点击(此处)折叠或打开

  1. #ifndef RING_BUFFER_H_
  2. #define RING_BUFFER_H_

  3. #include <asf.h>
  4. #include <inttypes.h>

  5. typedef enum
  6. {
  7.     B_RET_OK,
  8.     B_RET_FULL,
  9.     B_RET_EMPTY,
  10.     B_RET_INVALID,
  11.     B_RET_ERROR
  12. }B_RET;

  13. typedef struct
  14. {
  15.     int16_t front;
  16.     int16_t rear;
  17.     int16_t count;
  18.     uint8_t *store;
  19.     uint8_t entry_size;
  20.     int16_t max_entries;
  21. }str_rbuf;

  22. B_RET rbuf_init(str_rbuf * rbuf, uint8_t * store, uint8_t entry_size, int16_t max_entries);
  23. B_RET rbuf_push(str_rbuf * rbuf, uint8_t * data);
  24. B_RET rbuf_pull(str_rbuf * rbuf, uint8_t * data);
  25. B_RET rbuf_read(str_rbuf * rbuf, uint8_t index, uint8_t * data);
  26. B_RET rbuf_clear(str_rbuf * rbuf);
  27. uint16_t rbuf_nr_of_items(str_rbuf * rbuf);

  28. #endif /* RING_BUFFER_H_ */


阅读(2306) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~