stm32 环形缓冲区

 

/*========================ringbuff.H========================================*/

#ifndef __RingBuff__H

#define USER_RINGBUFF 1 //使用环形缓冲区形式接收数据

#if USER_RINGBUFF

/**如果使用环形缓冲形式接收串口数据***/

#define RINGBUFF_LEN 200 /*最好是2^N,此时就可以进行用取模运算 https://www.cnblogs.com/rechen/p/5143841.html*/

#define FLASE 1

#define TRUE 0

#define TIMEOUT 3

typedef struct

{

u16 Head; //消费者模型,从队头删除

u16 Tail; //生产者模型,从队尾添加

u16 Lenght; //接收数据的长度为ringBuff.Lenght=Ring_Buff.Tail-Ring_Buff.Head

u8 Ring_Buff[RINGBUFF_LEN];

}RingBuff_t;

typedef struct

{

bool bTimeoutCountEn;

bool bTimeout;

u16 Timeoutcount;

u16 Timelimt; //一般为几个字符传送的时间

}Timeout_t;

void RingBuff_Init(void);

u8 Write_RingBuff(u8 data);

u8 Read_RingBuff(u8 *rData);

#endif //end of USER_RINGBUFF

#endif //end of __RingBuff__H

/*========================ringbuff.c========================================*/

#include "ringbuff.h"

RingBuff_t ringBuff;//创建一个ringBuff的缓冲区

Timeout_t RcvTimeout={0,0,0,TIMEOUT};

void RingBuff_Init(void)

{

//初始化相关信息

ringBuff.Head = 0;

ringBuff.Tail = 0;

ringBuff.Lenght = 0;

}

/**

*

*

*

* 说明:被接收中断函数调用

*/

u8 Write_RingBuff(u8 data)

{

#if 0

//if((ringBuff.Tail -ringBuff.Head)== RINGBUFF_LEN) //判断缓冲区是否已满

if(ringBuff.Lenght== RINGBUFF_LEN)

{

return FLASE;

}

ringBuff.Ring_Buff[(ringBuff.Tail++)&(MRINGBUFF_LEN-1)] = data //前提.Tail和.Head数据类型是unsigned int,且MRINGBUFF_LEN是2的词幂,ringBuff.Lenght=Ring_Buff.Tail-Ring_Buff.Head

#else

if(ringBuff.Lenght >= RINGBUFF_LEN) //判断缓冲区是否已满

{

return FLASE;

}

ringBuff.Ring_Buff[ringBuff.Tail]=data;

ringBuff.Tail = (ringBuff.Tail+1)%RINGBUFF_LEN;//防止越界非法访问

#endif

ringBuff.Lenght++;

return TRUE;

}

/**

*

*

*

* 说明:原则上不用做接收完成的判断,当缓冲区读都不可读时会有提醒

*/

u8 Read_RingBuff(u8 *rData)

{

#if 0

//if((ringBuff.Tail -ringBuff.Head)== 0) //判断缓冲区是否已空

if(ringBuff.Lenght==0)

{

return FLASE;

}

*rData =ringBuff.Ring_Buff[(ringBuff.Head++)&(MRINGBUFF_LEN-1)]; //前提.Tail和.Head数据类型是unsigned int,且MRINGBUFF_LEN是2的词幂,ringBuff.Lenght=Ring_Buff.Tail-Ring_Buff.Head

#else

if(ringBuff.Lenght == 0)//判断非空

{

return FLASE;

}

*rData = ringBuff.Ring_Buff[ringBuff.Head];//先进先出FIFO,从缓冲区头出

ringBuff.Head = (ringBuff.Head+1)%RINGBUFF_LEN;//防止越界非法访问

#endif

ringBuff.Lenght--;

return TRUE;

}

void USART1_IRQHandler(void)

{

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断

{

USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清楚标志位

Write_RingBuff(USART_ReceiveData(USART1)); //读取接收到的数据

RcvTimeout.bTimeoutCountEn =1;

RcvTimeout.Timeoutcount=0;

}

}

void TIM3_IRQHandler(void)

{

if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源

{

TIM_ClearITPendingBit(TIM3, TIM_IT_Update );

if(RcvTimeout.bTimeoutCountEn)

{

if(++RcvTimeout.Timeoutcount == RcvTimeout.Timelimt)

{

RcvTimeout.bTimeoutCountEn=0;

RcvTimeout.Timeoutcount=0;

RcvTimeout.bTimeout=1; //接收完成判断

}

}

}

}

环形队列的实现:在计算机中,也是没有环形的内存的,只不过是我们将顺序的内存处理过,让某一段内存形成环形,使他们首尾相连,简单来说,这其实就是一个数组,只不过有两个指针,一个指向列队头,一个指向列队尾。指向列队头的指针(Head)是缓冲区可读的数据,指向列队尾的指针(Tail)是缓冲区可写的数据,通过移动这两个指针(Head) &(Tail)即可对缓冲区的数据进行读写操作了,直到缓冲区已满(头尾相接),将数据处理完,可以释放掉数据,又可以进行存储新的数据了。 实现的原理:初始化的时候,列队头与列队尾都指向0,当有数据存储的时候,数据存储在‘0’的地址空间,列队尾指向下一个可以存储数据的地方‘1’,再有数据来的时候,存储数据到地址‘1’,然后队列尾指向下一个地址‘2’。当数据要进行处理的时候,肯定是先处理‘0’空间的数据,也就是列队头的数据,处理完了数据,‘0’地址空间的数据进行释放掉,列队头指向下一个可以处理数据的地址‘1’。从而实现整个环形缓冲区的数据读写。 1/** 2* @brief Write_RingBuff 3* @param u8 data 4* @return FLASE:环形缓冲区已满,写入失败;TRUE:写入成功 5* @author 杰杰 6* @date 2018 7* @version v1.0 8* @note 往环形缓冲区写入u8类型的数据 9*/ 10u8 Write_RingBuff(u8 data) 11{ 12 if(ringBuff.Lenght >= RINGBUFF_LEN) //判断缓冲区是否已满 13 { 14 return FLASE; 15 } 16 ringBuff.Ring_Buff[ringBuff.Tail]=data; 17// ringBuff.Tail++; 18 ringBuff.Tail = (ringBuff.Tail+1)%RINGBUFF_LEN;//防止越界非法访问 19 ringBuff.Lenght++; 20 return TRUE; 21} 具体见我博客:https://blog.csdn.net/jiejiemcu/article/details/80563422
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值