可能出现的情景:
在单任务系统中,按键后若某功能的程序执行事件很长,在次期间再有按键是无效的,因为此时CPU没有为键盘服务。这在连续快速输入按键时,很有可能造成漏键。
解决漏键问题的方式是采用FIFO,在键盘查询中断内一旦发现有新的按键,则把键值压入FIFO中。即使主循环周期较长,在两次读取键值之间用户进行了多次按键操作,这些键值会依次存于FIFO中,等待主循环的读取,只要缓冲区足够大,多次连续按键就不会漏掉。而且在主循环中通过GetKey()函数可以随时读FIFO获取键值。这种方法是非阻塞的。
FIFO数据结构体:
-
typedef struct
-
{
-
int16_t front;
-
int16_t rear;
-
int16_t count;
-
uint8_t *store;
-
uint8_t entry_size;
-
int16_t max_entries;
-
}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. 初始化函数
-
#define B_EMPTY -1
-
-
B_RET rbuf_init(str_rbuf * rbuf, uint8_t * store, uint8_t entry_size, int16_t max_entries)
-
{
-
if (0x7FFF == max_entries)
-
{
-
return (B_RET_INVALID);
-
}
-
rbuf->store = store;
-
rbuf->entry_size = entry_size;
-
rbuf->max_entries = max_entries;
-
rbuf->front = B_EMPTY;
-
rbuf->rear = B_EMPTY;
-
rbuf->count = 0;
-
return (B_RET_OK);
-
}
比如:
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清空操作
-
B_RET rbuf_clear(str_rbuf * rbuf)
-
{
-
rbuf->front = B_EMPTY;
-
rbuf->rear = B_EMPTY;
-
rbuf->count = 0;
-
return (B_RET_OK);
-
}
可变的参数,都回到初始化状态。
3. 写数据到FIFO中
-
B_RET rbuf_push(str_rbuf * rbuf, uint8_t * data)
-
{
-
if (rbuf->count >= (rbuf->max_entries))
-
{
-
return (B_RET_FULL);
-
}
-
if (rbuf->front >= (rbuf->max_entries - 1)) // rbuf->front的范围【0, rbuf->max_entries - 1】,为数组的下标
-
{
-
rbuf->front = B_EMPTY;
-
}
-
rbuf->front++;
-
rbuf->count++;
-
for (uint8_t i = 0; i < rbuf->entry_size; i++) // 这里是循环读一个元素(元素可能是1个字节,或者多个字节)
-
{
-
rbuf->store[((rbuf->front * rbuf->entry_size) + i)] = data[i];
-
}
-
return (B_RET_OK);
-
}
4. 从FIFO中读数据
-
B_RET rbuf_pull(str_rbuf * rbuf, uint8_t * data)
-
{
-
if (rbuf->count == 0)
-
{
-
return (B_RET_EMPTY);
-
}
-
if (rbuf->rear >= (rbuf->max_entries - 1))
-
{
-
rbuf->rear = B_EMPTY;
-
}
-
rbuf->rear++;
-
rbuf->count--;
-
for (uint8_t i = 0; i < rbuf->entry_size; i++) // 这里是循环读一个元素(元素可能是1个字节,或者多个字节)
-
{
-
data[i] = rbuf->store[((rbuf->rear * rbuf->entry_size) + i)] ;
-
}
-
-
/* FIFO 数据读取完了,则读写指针回到起点,而不是说读写指针一直往上累加。需要注意这里。*/
-
if (rbuf->count == 0)
-
{
-
rbuf->front = B_EMPTY;
-
rbuf->rear = B_EMPTY;
-
}
-
return (B_RET_OK);
-
}
5. 读指定位置处的元素
-
/* 实现纯粹读指定地址的数据,不改写读指针参数 */
-
B_RET rbuf_read(str_rbuf * rbuf, uint8_t index, uint8_t * data)
-
{
-
if (rbuf->count == 0)
-
{
-
return (B_RET_EMPTY);
-
}
-
-
for (uint8_t i = 0; i < rbuf->entry_size; i++)
-
{
-
data[i] = rbuf->store[((index * rbuf->entry_size) + i)] ;
-
}
-
return (B_RET_OK);
-
}
6. 读取FIFO中元素的实际个数
-
/* 返回buffer 里面数据的长度 */
-
uint16_t rbuf_nr_of_items(str_rbuf * rbuf)
-
{
-
return ( rbuf->count );
-
}
源代码:
-
#include "ring_buffer.h"
-
-
#define B_EMPTY -1
-
-
B_RET rbuf_init(str_rbuf * rbuf, uint8_t * store, uint8_t entry_size, int16_t max_entries)
-
{
-
if (0x7FFF == max_entries)
-
{
-
return (B_RET_INVALID);
-
}
-
rbuf->store = store;
-
rbuf->entry_size = entry_size;
-
rbuf->max_entries = max_entries;
-
rbuf->front = B_EMPTY;
-
rbuf->rear = B_EMPTY;
-
rbuf->count = 0;
-
return (B_RET_OK);
-
}
-
-
B_RET rbuf_clear(str_rbuf * rbuf)
-
{
-
rbuf->front = B_EMPTY;
-
rbuf->rear = B_EMPTY;
-
rbuf->count = 0;
-
return (B_RET_OK);
-
}
-
-
B_RET rbuf_push(str_rbuf * rbuf, uint8_t * data)
-
{
-
if (rbuf->count >= (rbuf->max_entries))
-
{
-
return (B_RET_FULL);
-
}
-
if (rbuf->front >= (rbuf->max_entries - 1))
-
{
-
rbuf->front = B_EMPTY;
-
}
-
rbuf->front++;
-
rbuf->count++;
-
for (uint8_t i = 0; i < rbuf->entry_size; i++)
-
{
-
rbuf->store[((rbuf->front * rbuf->entry_size) + i)] = data[i];
-
}
-
return (B_RET_OK);
-
}
-
-
B_RET rbuf_pull(str_rbuf * rbuf, uint8_t * data)
-
{
-
if (rbuf->count == 0)
-
{
-
return (B_RET_EMPTY);
-
}
-
if (rbuf->rear >= (rbuf->max_entries - 1))
-
{
-
rbuf->rear = B_EMPTY;
-
}
-
rbuf->rear++;
-
rbuf->count--;
-
for (uint8_t i = 0; i < rbuf->entry_size; i++)
-
{
-
data[i] = rbuf->store[((rbuf->rear * rbuf->entry_size) + i)] ;
-
}
-
-
/* FIFO 数据读取完了,则读写指针回到起点,不管FIFO 里面是不是存满了。*/
-
if (rbuf->count == 0)
-
{
-
rbuf->front = B_EMPTY;
-
rbuf->rear = B_EMPTY;
-
}
-
return (B_RET_OK);
-
}
-
-
/* 实现纯粹读指定地址的数据,不改写读指针参数 */
-
B_RET rbuf_read(str_rbuf * rbuf, uint8_t index, uint8_t * data)
-
{
-
if (rbuf->count == 0)
-
{
-
return (B_RET_EMPTY);
-
}
-
-
for (uint8_t i = 0; i < rbuf->entry_size; i++)
-
{
-
data[i] = rbuf->store[((index * rbuf->entry_size) + i)] ;
-
}
-
return (B_RET_OK);
-
}
-
#ifndef RING_BUFFER_H_
-
#define RING_BUFFER_H_
-
-
#include <asf.h>
-
#include <inttypes.h>
-
-
typedef enum
-
{
-
B_RET_OK,
-
B_RET_FULL,
-
B_RET_EMPTY,
-
B_RET_INVALID,
-
B_RET_ERROR
-
}B_RET;
-
-
typedef struct
-
{
-
int16_t front;
-
int16_t rear;
-
int16_t count;
-
uint8_t *store;
-
uint8_t entry_size;
-
int16_t max_entries;
-
}str_rbuf;
-
-
B_RET rbuf_init(str_rbuf * rbuf, uint8_t * store, uint8_t entry_size, int16_t max_entries);
-
B_RET rbuf_push(str_rbuf * rbuf, uint8_t * data);
-
B_RET rbuf_pull(str_rbuf * rbuf, uint8_t * data);
-
B_RET rbuf_read(str_rbuf * rbuf, uint8_t index, uint8_t * data);
-
B_RET rbuf_clear(str_rbuf * rbuf);
-
uint16_t rbuf_nr_of_items(str_rbuf * rbuf);
-
-
#endif /* RING_BUFFER_H_ */
阅读(2394) | 评论(0) | 转发(0) |