在linux应用程序开发过程中,通常会涉及到从低速数据接口(如串口、SPI接口、i2c接口)接收数据并处理数据内容,但由于低速数据接口的硬件FIFO一般仅有64byte或32byte大小,一般不超过128byte。为了linux应用程序正确读取低速数据接口数据而又不影响到系统其他接口功能,
一般会在应用程序中使用循环队列缓存接收的数据,然后再一次从循环队列中读取数据再进行处理。
本节介绍
一种一维循环队列的C语言程序的设计,该队列主要适用于串口、SPI接口、I2C接口等以字节为最小单位的低速数据接口的数据缓存。
本队列在ubuntu上使用gcc和arm-gcc交叉编译都编译通过,并在实际RS232串口和RS422串口的接收中使用验证的。
1.首先编写一维队列的头文件app_queue.h。
#ifndef SRC_APP_QUEUE_H_
#define SRC_APP_QUEUE_H_
#include <pthread.h>
#define MAX_BUFF_SIZE (4*1024*1024) //4MB
typedef struct Queue
{
unsigned char *buffer; //队列缓存指针
// unsigned int max_size; //队列最大空间
unsigned int read_index; //读数据位置
unsigned int write_index; //写数据位置
unsigned int count; //队列数据量
// unsigned long recv_time; //
pthread_mutex_t mutex;
}queue;
//参数声明
extern queue dataqueue;
extern unsigned char databuff[MAX_BUFF_SIZE];
int write_Queue_Chars(queue *dst_queue, unsigned char *buffer, unsigned int length);
int read_Queue_Chars(queue *src_queue, unsigned char *buffer, unsigned int length);
void init_Queue(queue *src_queue, unsigned char* buf);
void init_Queue_All(void);
#endif
2.然后编写一维队列的源文件app_queue.c。
#include <stdio.h>
#include <string.h>
#include "app_queue.h"
queue dataqueue;
unsigned char databuff[MAX_BUFF_SIZE]={0};
/******************************************************************************
*FUNCATION NAME : int write_Queue_Chars(queue *dst_queue, unsigned char *buffer, unsigned int length)
*CREATE DATE : 2022-10-31
*CREATE BY : LSL
*FUNCTION : 一维队列写字符串数据
*MODIFY DATE :
*INPUT : queue *dst_queue 待写入的队列指针
unsigned char *buffer 待写入的数据指针
unsigned int length 待写入的帧数据字节数
*OUTPUT :
*RETURN : 0 成功 -1失败
*OTHERS :
******************************************************************************/
int write_Queue_Chars(queue *dst_queue, unsigned char *buffer, unsigned int length)
{
int rst = -1;
int write_len, temp_len;
if(NULL==dst_queue || NULL==buffer)
{
printf("write_queue_chars err 1\n");
return rst;
}
pthread_mutex_lock(&dst_queue->mutex);
if(dst_queue->write_index + length < MAX_BUFF_SIZE)
{
write_len = length;
memcpy(&dst_queue->buffer[dst_queue->write_index], buffer, write_len);
dst_queue->write_index += write_len;
}
else
{
write_len = MAX_BUFF_SIZE - dst_queue->write_index;
memcpy(&dst_queue->buffer[dst_queue->write_index], buffer, write_len);
temp_len = write_len;
write_len = length - temp_len;
memcpy(&dst_queue->buffer[0], buffer+temp_len, write_len);
dst_queue->write_index = write_len;
}
dst_queue->count += length;
if(dst_queue->count >= MAX_BUFF_SIZE)//队列缓存已满.丢弃队列数据
{
printf("the queue buffer is fulled err\n");
dst_queue->count -= MAX_BUFF_SIZE;
}
pthread_mutex_unlock(&dst_queue->mutex);
return length;
}
/******************************************************************************
*FUNCATION NAME : int read_Queue_Chars(queue *src_queue, unsigned char *buffer, unsigned int length)
*CREATE DATE : 2022-10-31
*CREATE BY : LSL
*FUNCTION : 一维队列读取字符串数据
*MODIFY DATE :
*INPUT : queue *dst_queue 待读取的队列指针
unsigned char *buffer 待读取的数据指针
unsigned int length 待读取的帧数据字节数
*OUTPUT :
*RETURN : 大于0 实际读取的帧数据字节数 -1失败
*OTHERS :
******************************************************************************/
int read_Queue_Chars(queue *src_queue, unsigned char *buffer, unsigned int length)
{
int rst = -1;
int read_len ,temp_len,read_size;
int data_len;
if(NULL==src_queue || NULL==buffer || length==0)
{
printf("read_queue_chars err 1\n");
return rst;
}
if(src_queue->count==0)
{
return rst;
}
pthread_mutex_lock(&src_queue->mutex);
if(src_queue->count >=length)//队列数据量大于所读数据量
{
data_len = length;
if(src_queue->read_index+data_len < MAX_BUFF_SIZE)
{
read_len = data_len;
memcpy(buffer, &src_queue->buffer[src_queue->read_index], data_len);
src_queue->read_index += data_len;
}
else if(src_queue->read_index+data_len >= MAX_BUFF_SIZE)
{
read_len= MAX_BUFF_SIZE - src_queue->read_index;
memcpy(buffer, &src_queue->buffer[src_queue->read_index], read_len);
src_queue->read_index = 0;
temp_len = read_len;
read_len = data_len - temp_len;
memcpy(buffer+temp_len, &src_queue->buffer[src_queue->read_index], read_len);
src_queue->read_index = read_len;
}
src_queue->count -= data_len;
read_size=data_len;
}
else//队列数据量少于所读数据
{
data_len = src_queue->count;
if(src_queue->read_index+data_len < MAX_BUFF_SIZE)
{
read_len = data_len;
memcpy(buffer, &src_queue->buffer[src_queue->read_index], data_len);
src_queue->read_index += data_len;
}
else if(src_queue->read_index+data_len >= MAX_BUFF_SIZE)
{
read_len= MAX_BUFF_SIZE - src_queue->read_index;
memcpy(buffer, &src_queue->buffer[src_queue->read_index], read_len);
src_queue->read_index = 0;
temp_len = read_len;
read_len = data_len - temp_len;
memcpy(buffer+temp_len, &src_queue->buffer[src_queue->read_index], read_len);
src_queue->read_index = read_len;
}
src_queue->count -= data_len;
read_size=data_len;
}
pthread_mutex_unlock(&src_queue->mutex);
return read_size;
}
/******************************************************************************
*FUNCATION NAME : void init_queue(queue *src_queue, unsigned char* buf,unsigned int size)
*CREATE DATE : 2022-10-31
*CREATE BY : LSL
*FUNCTION : 初始化队列配置(一维队列)
*MODIFY DATE :
*INPUT :
*OUTPUT :
*RETURN :
*OTHERS :
******************************************************************************/
void init_Queue(queue *src_queue, unsigned char* buf)
{
src_queue->buffer = buf;
src_queue->count = 0;
src_queue->read_index = 0;
src_queue->write_index = 0;
}
/******************************************************************************
*FUNCATION NAME : void init_queue_all(void)
*CREATE DATE : 2022-10-31
*CREATE BY : LSL
*FUNCTION : 初始化队列配置
*MODIFY DATE :
*INPUT :
*OUTPUT :
*RETURN :
*OTHERS :
******************************************************************************/
void init_Queue_All(void)
{
init_Queue((queue *)&dataqueue, (unsigned char *)&databuff[0]); //初始化数据队列
}
3.测试代码源文件文件如下所示:main.c。
4.编译Makefile文件为:
5.编译脚本build_myapp.sh为如下所示:
6.进行队列写入和队列读取数据的测试结果如下:
版权声明:本文为q544344318原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。