串口环形收发原理及实现

一、环形收发队列构建
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_flag
        for(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));//读取接收到的数据
	}
}
  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值