目录
STM32开发中循环队列的使用
在进行stm32开发时,往往会需要进行板卡间的通讯,而这时我们通常会使用到串口通讯的功能。使用串口通讯搭配循环队列就可以完成板卡间按照制定的通讯协议进行通讯的流程,从而完成各种需要的功能。以下简要介绍下循环队列的使用及参考代码。
串口通讯配合循环队列使用的大概流程
假设我们有主驱动板和从驱动板两块硬件板卡。需要完成的操作是通过主驱动板按照制定的通讯协议发送指令控制从驱动板上连接的设备完成相关的操作。我们可以通过串口通讯配合循环队列来完成。 1、主驱动板使用串口发送指令给从驱动板 2、从驱动板接收到串口指令后保存到循环队列中 3、在从驱动板主程序中进行逐条进行解析指令并控制硬件设备完成相关的操作 4、完成操作后应答主驱动板
为了结构的清晰这里将循环队列的实现代码分为queue.h和queue,c两部分。
循环队列queue.h文件
#ifndef __QUEUE_H #define __QUEUE_H #ifndef u8 typedef unsigned char u8; #endif #ifndef s8 typedef unsigned char s8; #endif #ifndef u16 typedef unsigned short u16; #endif #ifndef int16 typedef unsigned short int16; #endif #ifndef u32 typedef unsigned int u32; #endif #ifndef int32 typedef unsigned int int32; #endif #define QUEUE_DATA_TYPE u8 //定义循环队列的操作结果 #define QUEUE_INVALID -1 //循环队列无效 #define QUEUE_OK 0 #define QUEUE_FULL 2 #define QUEUE_EMPTY 3 //定义循环队列数据结构 typedef struct { QUEUE_DATA_TYPE *Start; //队列的起始地址 QUEUE_DATA_TYPE *End; //队列的结束地址 u16 MaxData; //列中允许存储的数据个数 u16 ReadLen; //读出的数据长度 u16 WriteLen; //写入的数据长度 u8 (* ReadEmpty)(); //队列读空处理函数 u8 (* WriteFull)(); //队列写满处理函数 QUEUE_DATA_TYPE Buf[1]; //队列头部存储的数据 }DataQueue; //函数接口声明 //1、创建循环队列 s8 Queue_Create(void *Buf, u32 Size,u8 (*ReadEmpty)(),u8 (*WriteFull)()); //2、从队列中读出一个数据 s8 Queue_Read(QUEUE_DATA_TYPE *Ret, void *Buf); //3、向队列中写入一个数据 s8 Queue_Write(void *Buf,QUEUE_DATA_TYPE data); //4、获取队列中剩余的数据个数 int16 Queue_Get_Reamin_Count(void *Buf); //5、获取队列最大存储个数 int16 Queue_Get_Max_Count(void *Buf); //6、清空队列 s8 QueueFlush(void *Buf); //7、队列写满处理函数 s8 QueueWriteFull(DataQueue *Buf,QUEUE_DATA_TYPE data); //8、向队列中写入多个数据 s8 QueueWriteNData(void *Buf,QUEUE_DATA_TYPE *data,u32 cnt); #endif
循环队列queue.c文件
#include "queue.h" /* 函数功能:创建循环队列 参数说明: Buf: 队列的存储空间地址 Size: 存储空间大小 ReadEmpty: 队列读空处理函数 WriteFull: 队列写满处理函数 返回值: QUEUE_OK:成功 QUEUE_INVALID:队列无效 */ s8 Queue_Create(void *Buf, u32 Size,u8 (*ReadEmpty)(),u8 (*WriteFull)()) { DataQueue *Queue; //判断队列的有效性 if(Buf != NULL && Size >= sizeof(DataQueue)) { Queue = (DataQueue *)Buf; //初始化队列 Queue->MaxData = (Size - ((u32)&Queue->Buf[0] - (u32)&Queue->Start)) / sizeof(QUEUE_DATA_TYPE); Queue->End = Queue->Buf + Queue->MaxData; Queue->Start = Queue->Buf; Queue->ReadLen = 0; Queue->WriteLen = 0; Queue->ReadEmpty = ReadEmpty; Queue->WriteFull = WriteFull; return QUEUE_OK; } else { return QUEUE_INVALID; } } /* 函数功能:从队列中读出一个数据 参数说明: Ret: 读出一个数据的存储地址 Buf: 队列的存储空间地址 返回值: QUEUE_OK:成功 QUEUE_EMPTY:队列为空 QUEUE_INVALID:队列无效 */ s8 Queue_Read(QUEUE_DATA_TYPE *Ret, void *Buf) { s8 err; DataQueue *Queue; err = QUEUE_INVALID; if(Buf != NULL) { Queue = (DataQueue *)Buf; if(Queue->ReadLen != Queue->WriteLen) { *Ret = *(Queue->Buf + Queue->ReadLen); Queue->ReadLen++; if(Queue->ReadLen >= Queue->MaxData) { Queue->ReadLen = 0; } err = QUEUE_OK; } else { err = QUEUE_EMPTY; } } return err; } /* 函数功能:向队列中写入一个数据 参数说明: Buf: 队列的存储空间地址 data:待写入的数据 返回值: QUEUE_OK:成功 QUEUE_INVALID:队列无效 */ s8 Queue_Write(void *Buf,QUEUE_DATA_TYPE data) { s8 err; DataQueue *Queue; err = QUEUE_INVALID; if(buf != NULL) { Queue = (DataQueue *)Buf; *(Queue->Buf + Queue->WriteLen) = data; Queue->WriteLen++; if(Queue->WriteLen >= Queue->MaxData) { Queue->WriteLen = 0; } err = QUEUE_OK; } return err; } /* 函数功能:获取队列中剩余的数据个数 参数说明: Buf: 队列的存储空间地址 返回值: QUEUE_INVALID:队列无效 count:剩余数据个数 */ int16 Queue_Get_Reamin_Count(void *Buf) { u16 count; DataQueue *Queue; Queue = (DataQueue *)Buf; if(Buf != NULL) { if(Queue->WriteLen >= Queue->ReadLen) { count = Queue->WriteLen - Queue->ReadLen; } else { count = Queue->MaxData - (Queue->ReadLen - Queue->WriteLen); } return count; } return QUEUE_INVALID; } /* 函数功能:获取队列最大存储个数 参数说明: Buf: 队列的存储空间地址 返回值: max:剩余数据个数 QUEUE_INVALID:队列无效 */ int16 Queue_Get_Max_Count(void *Buf) { int16 max = QUEUE_INVALID; if(Buf != NULL) { max = ((DataQueue *)Buf)->MaxData; } return max; } /* 函数功能:清空队列 参数说明: Buf: 队列的存储空间地址 返回值: QUEUE_OK:成功 QUEUE_INVALID:队列无效 */ s8 QueueFlush(void *Buf) { DataQueue *Queue; s8 err = QUEUE_INVALID; if(Buf != NULL) { Queue = (DataQueue *)Buf; Queue->Start = Queue->Buf; Queue->WriteLen = 0; Queue->ReadLen = 0; err = QUEUE_OK; } return err; } /* 函数功能:队列写满处理函数 参数说明: Buf: 队列的存储空间地址 data:待写入的数据 返回值: QUEUE_OK:成功 QUEUE_INVALID:队列无效 */ s8 QueueWriteFull(DataQueue *Buf,QUEUE_DATA_TYPE data) { return QueueWrite((void *)Buf,data); } /* 函数功能:向队列中写入多个数据 参数说明: Buf: 队列的存储空间地址 data:待写入的数据起始地址 cnt:写入数据的个数 返回值: QUEUE_OK:成功 QUEUE_INVALID:队列无效 */ s8 QueueWriteNData(void *Buf,QUEUE_DATA_TYPE *data,u32 cnt) { s8 err; u32 i; DataQueue *Queue; err = QUEUE_INVALID; if(Buf != NULL) { Queue = (DataQueue *)Buf; Queue->MaxData = (sizeof(Buf)- ((u32)&Queue->Buf[0] - (u32)&Queue->Start))/sizeof(QUEUE_DATA_TYPE); for(i=0; i<cnt; i++) { *(Queue->Buf + Queue->WriteLen) = *(data + i); Queue->WriteLen++; if(Queue->WriteLen >= Queue->MaxData) { Queue->WriteLen = 0; } } err = QUEUE_OK; } return err; }