接收发送循环队列C语言版

1.适用于任何通信方式,主要是定时发送场景,已经线程之间的数据交互,可自定义数据类型,不局限于基本数据类型。

2.接口完善,实用性强,已分享给一部分人使用,反响非常好。

3.关注作者不迷路,更多使用的C实用库待你挖掘。

4.无需移植可直接使用。

/*********************************************************************************
  *Copyright(C) -
  *FileName: queue.c
  *Author: 我不是阿沸
  *Version: 6.1.0
  *Date: 2023.08.20
  *Description:  循环数据队列,用于带操作系统的串口发送与接收,或者线程间数据量很大的通信。  
  *Others:  使用接口前一定调用初始化接口,这里适配了rt_thread与FreeRTOS数据安全接口,如需要使用可以打开相关
  			宏定义,其他操作系统数据安全需自行实现  
  *History:  
  	 1.Date:2023/04/03
       Author:我不是阿沸 
       Modification:增加数据安全保护,适配RT-Thread与FreeRTOS 
     2.Date:2023/05/16
       Author:我不是阿沸 
       Modification:修改相关接口实现方式 
     3.Date:2023/07/18
       Author:我不是阿沸 
       Modification:增加超时机制 
     4.Date:2023/08/20
       Author:我不是阿沸 
       Modification:修改原有固定数据类型为自定义数据类型 
	 5.其他修改 
**********************************************************************************/


#include <stdio.h> 
#include <string.h>


#define FREERTOSLOCK 0
#define RTTHREADLOCK 0
#define QUEUEDELAY(x) ;//SYSTEMDELAY(x)

#if FREERTOSLOCK
typedef struct{
	void * queue;
	int size;
	int number;
	StaticSemaphore_t xMutexBuffer;
  	SemaphoreHandle_t xSemaphore;
	int rear;  //队尾
	int front; //对头 
}LzQueue; //队列结构体 

#elif RTTHREADLOCK

/**
  * @brief  队列管理类 
  * @param  队列数据缓存首地址.
  * @param  队列中元素的大小 
  * @param  队列中元素的个数 
  * @param  队列保护信号量 
  * @param  队列头 
  * @param  队列尾 
  */
typedef struct{
	void * queue;
	int size;
	int number;
	struct rt_mutex rt_mutex_t;
	int rear;  //队尾
	int front; //对头 
}LzQueue; //队列结构体 


#else


typedef struct{
	void * queue;
	int size;
	int number;
	int rear;  //队尾
	int front; //对头 
}LzQueue; //队列结构体

#endif

#if FREERTOSLOCK
#define QUEUEDELAY(x) vTaskDelay(x)
#endif


void queueInitiate(LzQueue *Q, void * buffer, int number, int size);
int isFull(LzQueue * Q);
int isEmpty(LzQueue * Q);
int putQueue(LzQueue * Q, void * d);
int putQueueBt(LzQueue * Q, void * d, int outtime);
int getQueue(LzQueue *Q, void * d);
void clearQueue(LzQueue *Q);
int putQueueNoWait(LzQueue * Q, void * d);


/**
  * @brief  初始化队列
  * @param  队列管理者地址.
  * @param  队列数据缓存地址 
  * @param  队列元素数量 
  * @param  队列元素大小
  * @retval None
  */ 
void queueInitiate(LzQueue *Q, void * buffer, int number, int size){
   
	#if FREERTOSLOCK
    Q->xSemaphore = xSemaphoreCreateMutexStatic(&(Q->xMutexBuffer));
    if(Q->xSemaphore == NULL) while(1);
    if ( xSemaphoreGive( Q->xSemaphore ) != pdTRUE ) {
        /* 如果要释放一个互斥量,必须先有第一次的获取*/
    }
	
    xSemaphoreTake(Q->xSemaphore, portMAX_DELAY); 
	#elif RTTHREADLOCK
	if(RT_EOK != rt_mutex_init( &(Q->rt_mutex_t), "linze Q lock", RT_IPC_FLAG_FIFO)){
		//while(1);
		return;
	}
	
	#endif
		Q->queue = buffer;
		Q->number = number;
		Q->size = size;
		Q->front = 0;  //初始化对头 ,指向队列头部的前一个位置 
		Q->rear = 0;  //初始化队尾 ,指向队列尾部的具体数据
	
	#if FREERTOSLOCK
    xSemaphoreGive(Q->xSemaphore );
	#elif RTTHREADLOCK
		rt_mutex_release(&(Q->rt_mutex_t));
	#endif
}

/**
  * @brief  判断队列是否为满 
  * @param  队列管理者地址.
  * @retval 队列满返回 1,否则返回 0 
  */ 
int isFull(LzQueue * Q){
	#if FREERTOSLOCK
    xSemaphoreTake(Q->xSemaphore, portMAX_DELAY); 
	#elif RTTHREADLOCK
		rt_mutex_take(&(Q->rt_mutex_t), RT_WAITING_FOREVER);
  #endif
	if(((Q->rear+1)%Q->number) == Q->front)
    {
			#if FREERTOSLOCK
        xSemaphoreGive(Q->xSemaphore ); 
			#elif RTTHREADLOCK
				rt_mutex_release(&(Q->rt_mutex_t));
			#endif
        return 1;  //队列满返回1 
    }
	#if FREERTOSLOCK
		xSemaphoreGive(Q->xSemaphore );
	#elif RTTHREADLOCK
		rt_mutex_release(&(Q->rt_mutex_t));
	#endif
	return 0;  //队列没满返回0 	
} 

/**
  * @brief  判断队列是否空  
  * @param  队列管理者地址.
  * @retval 队列空返回 1,否则返回 0 
  */ 
int isEmpty(LzQueue *Q){
	#if FREERTOSLOCK
		BaseType_t xReturn = pdPASS;
		xSemaphoreTake(Q->xSemaphore, portMAX_DELAY);
	#elif RTTHREADLOCK
		rt_mutex_take(&(Q->rt_mutex_t), RT_WAITING_FOREVER);
	#endif
	if(Q->rear == Q->front){
		#if FREERTOSLOCK
				xSemaphoreGive(Q->xSemaphore );
		#elif RTTHREADLOCK
			rt_mutex_release(&(Q->rt_mutex_t));
		#endif
				return 1;  //队列空返回1
	}
	#if FREERTOSLOCK
    xSemaphoreGive(Q->xSemaphore );
	#elif RTTHREADLOCK
			rt_mutex_release(&(Q->rt_mutex_t));
	#endif
    return 0;  //队列空返回1
}


/**
  * @brief  添加数据到队列  
  * @param  队列管理者地址, 需要添加的数据 
  * @retval 添加成功返回 1,失败返回 0 
  */ 
int putQueue(LzQueue * Q, void * d) {
	while( isFull(Q) ) {  //判断队列是否满,满了就无法添加数据
		QUEUEDELAY(1);
	}
	#if FREERTOSLOCK
		xSemaphoreTake(Q->xSemaphore, portMAX_DELAY);
	#elif RTTHREADLOCK
		rt_mutex_take(&(Q->rt_mutex_t), RT_WAITING_FOREVER);
	#endif
	memcpy((unsigned char *)(Q->queue)+(Q->rear*Q->size), d, Q->size);
    
	Q->rear = (Q->rear+1)% (Q->number);
	#if FREERTOSLOCK
		xSemaphoreGive(Q->xSemaphore );
	#elif RTTHREADLOCK
			rt_mutex_release(&(Q->rt_mutex_t));
	#endif
	return 1;
}

/**
  * @brief  添加数据到队列,不带等待  
  * @param  队列管理者地址
  * @param  需要添加的数据 
  * @retval 添加成功返回 1,失败返回 0 
  */ 
int putQueueNoWait(LzQueue * Q, void * d) {
	if( isFull(Q) ) {  //判断队列是否满,满了就无法添加数据
		return 0;
	}
	#if FREERTOSLOCK
		xSemaphoreTake(Q->xSemaphore, portMAX_DELAY);
	#elif RTTHREADLOCK
		rt_mutex_take(&(Q->rt_mutex_t), RT_WAITING_FOREVER);
	#endif
	memcpy((unsigned char *)(Q->queue)+(Q->rear*Q->size), d, Q->size);
    
	Q->rear = (Q->rear+1)% (Q->number);
	#if FREERTOSLOCK
		xSemaphoreGive(Q->xSemaphore );
	#elif RTTHREADLOCK
			rt_mutex_release(&(Q->rt_mutex_t));
	#endif
	return 1;
}


/**
  * @brief  添加数据到队列,带等待超时机制 
  * @param  队列管理者地址, 
  * @param  需要添加的数据 
  * @param  等待时间 
  * @retval 成功返回 1,失败返回 0 
  */ 
int putQueueBt(LzQueue * Q, void * d, int outtime) {
	while(isFull(Q))
    {
        outtime--;
        QUEUEDELAY(1);
        if(outtime < 1) return 0;
    }
	#if FREERTOSLOCK
    xSemaphoreTake(Q->xSemaphore, portMAX_DELAY);
	#elif RTTHREADLOCK
		rt_mutex_take(&(Q->rt_mutex_t), RT_WAITING_FOREVER);
	#endif
    memcpy((unsigned char *)(Q->queue)+(Q->rear*Q->size), d, Q->size);
	Q->rear = (Q->rear+1)% (Q->number);
    #if FREERTOSLOCK
	xSemaphoreGive(Q->xSemaphore );
	#elif RTTHREADLOCK
			rt_mutex_release(&(Q->rt_mutex_t));
	#endif
	return 1;
}

/**
  * @brief  从队列获取数据 
  * @param  队列管理者地址, 
  * @param  数据目标存放地址 
  * @retval 成功返回 1,失败返回 0 
  */ 
int getQueue(LzQueue *Q, void * d){

	if(isEmpty(Q)){
		return 0;
	} 
	#if FREERTOSLOCK
		xSemaphoreTake(Q->xSemaphore, portMAX_DELAY);
	#elif RTTHREADLOCK
		rt_mutex_take(&(Q->rt_mutex_t), RT_WAITING_FOREVER);
	#endif
    memcpy(d, (unsigned char *)(Q->queue)+(Q->front*Q->size), Q->size);
	Q->front = (Q->front+1)%(Q->number);
	#if FREERTOSLOCK
		xSemaphoreGive(Q->xSemaphore );
	#elif RTTHREADLOCK
		rt_mutex_release(&(Q->rt_mutex_t));
	#endif
	return 1;
} 

/**
  * @brief  清空队列所有数据 
  * @param  队列管理者地址 
  * @retval None
  */ 
void clearQueue(LzQueue *Q)
{
	#if FREERTOSLOCK
		xSemaphoreTake(Q->xSemaphore, portMAX_DELAY);
	#elif RTTHREADLOCK
		rt_mutex_take(&(Q->rt_mutex_t), RT_WAITING_FOREVER);
	#endif
	Q->front =0;
    Q->rear = 0;
	#if FREERTOSLOCK
		xSemaphoreGive(Q->xSemaphore);
	#elif RTTHREADLOCK
		rt_mutex_release(&(Q->rt_mutex_t));
	#endif
}



/****演示示例****/
typedef struct{
	int age;
	int high;
	double xg;
	char name[40];
}test;

typedef struct{
	char buffer[20];
	int len;
}test1;

LzQueue lz;
test t1[20];


//添加数据到队列,模拟串口发送数据,但不直接调用硬件接口,这样就可以提高效率
//应为串口发送需要一定的时间,有可能会阻碍当前线程的运行,可搭配任务栈使用 
//在开一个线程专门获取这个队列的数据进行发送(多个串口一样的),提高了效率以及通信的可靠性 
int fun1(void){
	test t;
	if(!isEmpty(&lz)){
		getQueue(&lz, (void*)&t);
		printf("name:%s, age:%d...\n", t.name, t.age);
	}
	
} 

int fun2(test * t){
	if(!isFull(&lz)){
		putQueueNoWait(&lz, (void*)t);
	}
}

int main(void){
	queueInitiate(&lz, (void *)&t1, 20, sizeof(test));
	test t2 = {22, 180, 120, "I'm not Ah Fei"};
	printf("name:%s, age:%d...\n", t2.name, t2.age);
	while(1){
		fun2(&t2);
		fun1();
		
	}
	return 0;	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值