基于linux的C语言的一维循环队列的设计(适用于低速串行数据的收发使用)

  • Post author:
  • Post category:linux


在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。

图1 测试代码源程序

4.编译Makefile文件为:

图2 Makefile源代码

5.编译脚本build_myapp.sh为如下所示:

图3 编译脚本源代码

6.进行队列写入和队列读取数据的测试结果如下:

图4 一维队列读写测试结果



版权声明:本文为q544344318原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。