一、环形收发队列构建
1、构造环形收发数组及其长度
#define buff_size 10
Unsigned char buff[buff_size];
2、定义环形收发读/写位置
u16 R_Buff;
u16 W_Buff;
3、结构体封装
typedef struct Qbuff
{u16 write; //写位置u16 read; //读位置u8 buff[buff_size]; //环形缓冲收发数组
}CircularBuff;
二、案例
假设环形收发数组长度为8。W/R分贝为实际的读写位置,Size为实际存储的数据的长度。
1、写入4个数据,则Write=4; Read=0; Size=4;
2、读取3个数据,则Write=4; Read=3; Size=4-3=1;
4、写入7个数据,则Write=(4+7)=11; Read=3; Size=1+7=8;
数组会先写后四个数据,写满后,再从头开些写到第3位置,(4+7)%8=3
此时,写数据长度Write-读数据长度Read=11-3=8,环形收发数组满了。
5、读取8个数据,则Write=11; Read=3+8=11; Size=11-11=0
此时,写数据长度Write=读数据长度Read=11,环形收发数组为空。
三、代码
“.h文件”
#define buff_size 500 //环形缓冲队列的容量
typedef struct Qbuff
{u16 write; //写位置u16 read; //读位置u8 buff[buff_size]; //环形缓冲收发数组
}CircularBuff;
“.c文件”
1、首先来实现队列
void init_buff(void) //初始化队列
{Cbuff.write=0;Cbuff.read=0;memset(Cbuff.buff,0,buff_size);
}u8 write_buff(u8 wdata) //入队
{if(((Cbuff.write-Cbuff.read)==buff_size)) //如果写位置减去读位置等于队列长度,就说明这个环形队列已经满{return 0;}Cbuff.buff[Cbuff.write%buff_size]=wdata; //将数据放入环形队列 Cbuff.write=Cbuff.write+1; //环形队列位置+1,如果超过了队列长度则回到队列头return 1;
}u8 read_buff(u8 *rdata) //出队
{if(Cbuff.read==Cbuff.write) //如果写位置和读的位置相等,就说明这个环形队列为空,则从头开始重新存{init_buff();return 0;}*rdata=Cbuff.buff[Cbuff.read%buff_size];Cbuff.read=Cbuff.read+1;return 1;
}
2、主循环做数据出队与数据包拆分
void move_data(void)
{int i=0;u16 size1,size2,size3; //记录三包数据的切分位置u16 len1,len2,len3; //记录三包数据的长度u8 CrcBuff1[100],CrcBuff2[100],CrcBuff3[100]; //CRC切分好的数据包if(ok_flag) //连续10ms没有接收到数据,ok_flag置1{ ok_flag=Cbuff.write; //将接收到的数据长度赋值给ok_flagfor(i=0;i<ok_flag;i++) //循环读取所有数据{if(read_buff(&data)) //缓冲非空,若有3个数据包{BuffHandle[i]=data; } } for(i=0;i<ok_flag;i++) //数据包切分,最大三包数据{if((BuffHandle[i-2]==0xF0)&&(BuffHandle[i-1]==0x10)) //判断数据头0xF0 0x10{size1=i-2; //记录切分位置len1=BuffHandle[i]; //记录数据包长度memcpy(CrcBuff1,BuffHandle+size1,len1); //获取切分好的数据包}if((BuffHandle[i-2]==0xF0)&&(BuffHandle[i-1]==0x0F)) //判断数据头0xF0 0x0F{size2=i-2; //记录切分位置len2=BuffHandle[i]; //记录数据包长度 memcpy(CrcBuff2,BuffHandle+size2,len2); //获取切分好的数据包} if((BuffHandle[i-2]==0xF0)&&(BuffHandle[i-1]==0x0F)) //判断数据头0xF0 0x0F{size3=i-2; //记录切分位置len3=BuffHandle[i]; //记录数据包长度memcpy(CrcBuff3,BuffHandle+size3,len3); //获取切分好的数据包 }}}
}
3、串口接收中断入队
void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断{ USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清除标志位write_buff(USART_ReceiveData(USART1));//读取接收到的数据}
}