闲来没事自己写了一个串口缓冲区玩,利用数组实现,运行在Linux环境底下,gcc编译和自测试通过。
#include
#include
/* 缓冲区大小 */
#define SERIAL_BUFFER_SIZE 250
/* 错误代码:取负值是为了与正常数值区别开来 */
#define CODE_SUCCESS -1
#define CODE_NO_OPERATE -2
#define CODE_INVALID_ARG -11
#define CODE_BUFFER_OVERFLOW -12
#define _8_BIT_SYSTEM 1
#define _16_BIT_SYSTEM 0
#define _32_BIT_SYSTEM 0
/* 数据类型:视编译器而定,GCC编译器的定义 */
#if _8_BIT_SYSTEM
typedef unsigned char u8;
typedef char s8;
typedef unsigned int u16;
typedef int s16;
#endif
#if _16_BIT_SYSTEM
typedef unsigned char u8;
typedef char s8;
typedef unsigned int u16;
typedef int s16;
typedef unsigned long u32;
typedef long s32;
#endif
/* 串口缓冲区结构体定义 */
typedef struct SerialBuffer_Str{
u8 WriteIndex;
u8 ReadIndex;
u8 Buffer[SERIAL_BUFFER_SIZE];
u8 ZeroFlag;
}SerialBuffer_Str;
/* 功能函数声明区 */
s16 SerialBuffer_Init(SerialBuffer_Str *p_SBstr);
s16 SerialBuffer_Read(SerialBuffer_Str *p_SBstr);
s16 SerialBuffer_Write(SerialBuffer_Str *p_SBstr,u8 *p_wdata);
/* 自测试用例声明区 */
void SerialBuffer_Test(SerialBuffer_Str *p_SBstr);
/*******************************************
* 函数名:SerialBuffer_Init
* 作用:初始化缓冲区结构体
* 输入参数:缓冲区结构体地址
* 输出参数:无
* 返回值:成功则返回 -1
*******************************************/
s16 SerialBuffer_Init(SerialBuffer_Str *p_SBstr)
{
if(p_SBstr == NULL){
/* 检查输入参数的有效性 */
return CODE_INVALID_ARG;
}
p_SBstr->WriteIndex=0;
p_SBstr->ReadIndex=1;
/* 初始化 读索引值>写索引值(表示缓冲区为空) */
p_SBstr->ZeroFlag=0;
/* 标准C库函数,移植时需注意 */
memset(p_SBstr->Buffer,0,SERIAL_BUFFER_SIZE);
return CODE_SUCCESS;
}
/*******************************************
* 函数名:SerialBuffer_Read
* 作用:读取缓冲区中的数据
* 说明:必须始终保持读索引值不大于写索引值(防止读到无效数据)
* 输入参数:缓冲区结构体地址
* 输出参数:无
* 返回值:从缓冲区中读到的数据,异常返回为负值
*******************************************/
s16 SerialBuffer_Read(SerialBuffer_Str *p_SBstr)
{
s16 ret;
if(p_SBstr == NULL){
/* 检查输入参数的有效性 */
return CODE_INVALID_ARG;
}
if(p_SBstr->ZeroFlag >= 2){
/* 当写索引值归零了两次或以上,某些未读数据会被覆盖掉 */
return CODE_BUFFER_OVERFLOW;
}
if((p_SBstr->ZeroFlag==1)&&(p_SBstr->WriteIndex >= p_SBstr->ReadIndex)){
/* 当写索引值归零之后,再次超过了读索引值,某些未读数据会被覆盖掉 */
return CODE_BUFFER_OVERFLOW;
}
if((p_SBstr->ZeroFlag==0) && (p_SBstr->ReadIndex > p_SBstr->WriteIndex)){
/* 读索引值大于写索引值,表示缓冲区为空,不作任何处理*/
return CODE_NO_OPERATE;
}
ret=p_SBstr->Buffer[p_SBstr->ReadIndex];
if(p_SBstr->ReadIndex >= (SERIAL_BUFFER_SIZE-1)){
p_SBstr->ReadIndex=0;
p_SBstr->ZeroFlag--;
}
else{
p_SBstr->ReadIndex++;
}
return ret;
}
/*******************************************
* 函数名:SerialBuffer_Write
* 作用:写数据到缓冲区中
* 说明:写时不对缓冲区作任何检查,尽量简短。
* 检查放在读函数中(方便移植到中断处理函数中)
* 输入参数1:缓冲区结构体地址
* 输入参数2:数据的地址(某个寄存器地址)
* 输出参数:无
* 返回值:成功则返回 -1
*******************************************/
s16 SerialBuffer_Write(SerialBuffer_Str *p_SBstr,u8 *p_wdata)
{
if(p_SBstr == NULL){
/* 检查输入参数的有效性 */
return CODE_INVALID_ARG;
}
if(p_SBstr->WriteIndex >= (SERIAL_BUFFER_SIZE-1)){
p_SBstr->WriteIndex=0;
p_SBstr->ZeroFlag++;
}
else{
p_SBstr->WriteIndex++;
}
p_SBstr->Buffer[p_SBstr->WriteIndex] = *p_wdata;
return CODE_SUCCESS;
}
void main(void)
{
SerialBuffer_Str Uart0_Buffer_Str;
SerialBuffer_Init(&Uart0_Buffer_Str);
SerialBuffer_Test(&Uart0_Buffer_Str);
}