原理
有数据到来时,写入的 next + 1
一个数据被处理后,读出的next + 1
当 写入的 next 到头时,缓冲区开始的部分已经空出来了,可以让它回头循环起来,读 到头也是同理。这样就可以拥有一个永远也装不满,但占空间也不大的缓冲区
实现方法
//FIFO缓冲区结构定义
struct FIFO8{
unsigned char *buf;
int p; //下一个写入数据的位置
int q; //下一个读出数据的位置
int size; //缓冲区大小
int free; //缓冲区剩余大小
int flags; //溢出标志
};
//FIFO初始化
void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf)
{
fifo->size = size;
fifo->buf = buf;
fifo->free = size;
fifo->flags = 0;
fifo->p = 0;
fifo->q = 0;
}
//向FIFO传送数据并保存
int fifo8_put(struct FIFO8 *fifo, unsigned char data)
{
if(fifo->free == 0){ //fifo缓冲区满,舍弃数据
fifo->flags |= FLAGS_OVERRUN;
return -1;
}
fifo->buf[fifo->p] = data;
fifo->p++;
if(fifo->p == fifo->size){ //写入到顶端,则掉头
fifo->p = 0;
}
fifo->free--;
return 0;
}
//从FIFO获取字符
char fifo8_get(struct FIFO8 *fifo)
{
int data;
if(fifo->free == fifo->size){ //fifo缓冲区空
return -1;
}
data = fifo->buf[fifo->q];
fifo->q++;
if(fifo->q == fifo->size){
fifo->q = 0;
}
fifo->free++;
return data;
}
//获取FIFO缓冲区状态
int fifo8_status(struct FIFO8 *fifo)
{
return fifo->size - fifo->free;
}
至此,FIFO缓冲区的定义就结束了。接下来是使用
extern struct FIFO8 keyfifo;
char keybuf[32];
fifo8_init(&keyfifo, 32, keybuf);
for (;;) {
io_cli();
if(fifo8_status(&keyfifo) == 0){
io_stihlt();
} else {
i = fifo8_get(&keyfifo);
io_sti();
sprintf(s, "%02x", i);
boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);
putfont8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);
}
}
struct FIFO8 keyfifo;
//键盘中断函数
void inthandler21(int *esp)
{
unsigned char data;
io_out8(PIC0_OCW2, 0X61);
data = io_in8(PORT_KEYDAT);
fifo8_put(&keyfifo, data); // 向缓冲区中写入数据
return;
}