为什么需要这个概念了,因为从机发送数据之后主机可能来不及处理,比如从机发送频率是每10ms发送一次,当主机接收到数据处理需要15ms,那么此时主机就会出现丢帧的概念,因此最好的解决办法是,定义一个缓冲区,当接受到数据后存储下来,然后一帧一帧的处理,这样就不会出现丢帧的情况。
下面以CAN通信举例
typedef struct
{
uint32_t source_address : 8;
uint32_t destination_address : 8;
uint32_t cmd_type : 8;
uint32_t reserved0 : 2;
uint32_t prior : 3;
uint32_t reserved1 : 3;
}can_id_redefine_t;
typedef union
{
uint32_t ext_id;
can_id_redefine_t bits;
} can_id_redefine_u;
typedef struct
{
can_id_redefine_u id;
uint8_t buff[8];
}can_tx_data_t;
typedef struct {
can_rx_data_t buffer[CIRCLE_BUFFER_SIZE]; // 缓冲区数组
int head; // 缓冲区头部指针
int tail; // 缓冲区尾部指针
int count; // 缓冲区中元素的数量
} circleBuffer_t;
// 初始化环形缓冲区
void circle_buffer_init(circleBuffer_t *rb)
{
rb->head = 0;
rb->tail = 0;
rb->count = 0;
// memset(rb->buffer, 0, CIRCLE_BUFFER_SIZE);
}
// 向环形缓冲区添加数据
int circle_add_data(circleBuffer_t *rb, can_rx_data_t data)
{
if (rb->count == CIRCLE_BUFFER_SIZE)
{
return -1; // 缓冲区已满
}
memcpy(&rb->buffer[rb->head], &data, sizeof(data));
rb->head = (rb->head + 1) % CIRCLE_BUFFER_SIZE;
rb->count++;
return 0;
}
// 从环形缓冲区读取数据
int circle_get_data(circleBuffer_t *rb, can_rx_data_t *data)
{
if (rb->count == 0)
{
return -1; // 缓冲区为空
}
memcpy(data, &rb->buffer[rb->tail], sizeof(rb->buffer[rb->tail]));
rb->tail = (rb->tail + 1) % CIRCLE_BUFFER_SIZE;
rb->count--;
return 0;
}
// 检查环形缓冲区是否为空
int circle_empty(circleBuffer_t *rb)
{
return rb->count == 0;
}
// 检查环形缓冲区是否已满
int circle_full(circleBuffer_t *rb)
{
return rb->count == CIRCLE_BUFFER_SIZE;
}