How to Implement FIFO Buffer in Embedded C: Simple Guide
To implement a
FIFO buffer in embedded C, create a circular buffer using an array with two pointers: head for writing and tail for reading. Increment pointers modulo buffer size to wrap around, ensuring data is read in the order it was written.Syntax
A FIFO buffer in embedded C typically uses an array and two index variables:
- buffer[]: stores data
- head: index where new data is written
- tail: index where data is read
- size: total buffer capacity
Use modulo operation to wrap head and tail when they reach the end.
c
typedef struct {
uint8_t buffer[SIZE];
uint16_t head;
uint16_t tail;
uint16_t size;
} FIFO_Buffer;
// Write data: buffer[head] = data; head = (head + 1) % size;
// Read data: data = buffer[tail]; tail = (tail + 1) % size;Example
This example shows a simple FIFO buffer storing bytes, with functions to add and remove data safely.
c
#include <stdio.h> #include <stdint.h> #include <stdbool.h> #define SIZE 5 typedef struct { uint8_t buffer[SIZE]; uint16_t head; uint16_t tail; uint16_t size; } FIFO_Buffer; void fifo_init(FIFO_Buffer *fifo) { fifo->head = 0; fifo->tail = 0; fifo->size = SIZE; } bool fifo_is_full(FIFO_Buffer *fifo) { return ((fifo->head + 1) % fifo->size) == fifo->tail; } bool fifo_is_empty(FIFO_Buffer *fifo) { return fifo->head == fifo->tail; } bool fifo_enqueue(FIFO_Buffer *fifo, uint8_t data) { if (fifo_is_full(fifo)) { return false; // Buffer full } fifo->buffer[fifo->head] = data; fifo->head = (fifo->head + 1) % fifo->size; return true; } bool fifo_dequeue(FIFO_Buffer *fifo, uint8_t *data) { if (fifo_is_empty(fifo)) { return false; // Buffer empty } *data = fifo->buffer[fifo->tail]; fifo->tail = (fifo->tail + 1) % fifo->size; return true; } int main() { FIFO_Buffer fifo; fifo_init(&fifo); // Add data 1,2,3 fifo_enqueue(&fifo, 1); fifo_enqueue(&fifo, 2); fifo_enqueue(&fifo, 3); uint8_t val; while (fifo_dequeue(&fifo, &val)) { printf("%d ", val); } return 0; }
Output
1 2 3
Common Pitfalls
Common mistakes when implementing FIFO buffers include:
- Not handling buffer full condition, causing data overwrite.
- Confusing
headandtailpointers leading to incorrect reads or writes. - Forgetting to use modulo operation, causing index overflow.
- Not checking if buffer is empty before reading, causing invalid data access.
c
/* Wrong: No check for full buffer, overwrites data */ buffer[head] = data; head++; /* Right: Check full and wrap index */ if (!fifo_is_full(&fifo)) { buffer[head] = data; head = (head + 1) % size; }
Quick Reference
- Initialize: Set
head = tail = 0. - Enqueue: Write at
head, thenhead = (head + 1) % size. - Dequeue: Read at
tail, thentail = (tail + 1) % size. - Full: When next
headequalstail. - Empty: When
head == tail.
Key Takeaways
Use a circular array with head and tail indexes to implement FIFO buffer.
Always check for full and empty conditions to avoid data loss or invalid reads.
Increment indexes using modulo to wrap around the buffer size.
Keep head as the write position and tail as the read position.
Test your buffer with edge cases like full and empty states.