串口通信之环形缓冲区队列

为什么需要缓冲区

很多单片机串口只有一个字节的缓存,如果遇到单片机串口中断没有及时处理寄存器的值,就会导致数据被覆盖,从而导致数据的丢失。为了防止丢失,我们应该定义一个缓冲区来保存数据,一有数据就往里面保存,需要的时候再去读取。

代码实现

下面的代码使用51单片机实现:

#define BUFFER_MAX  100      //缓冲区大小typedef struct _buffer{   unsigned char head_pos;             //缓冲区头部位置   unsigned char tail_pos;             //缓冲区尾部位置      unsigned char buffer[BUFFER_MAX];    //缓冲区数组 }uart_buffer;uart_buffer datas;unsigned char uart_read(void){   unsigned char ch;   if(datas.head_pos==datas.tail_pos)        //如果头尾位置相同表示缓冲区为空   {       return 0xFF;   }   else   {       ch = datas.buffer[datas.head_pos];    //如果缓冲区非空则取头节点值并偏移头节点       datas.head_pos++; //读取一个字节,移动一个位置       if(datas.head_pos>=BUFFER_MAX)           datas.head_pos=0;   //位置回到数组头部   }   return ch;}//这个函数在中断中使用void uart_receive(const unsigned char _buf){      datas.buffer[buffer.tail_pos]=_buf; //从尾部追加   datas.tail_pos++;   if(datas.tail_pos>=BUFFER_MAX)           //是否超过最大缓存       datas.tail_pos=0;                      //大于数组最大长度置零 形成环形队列   if(datas.tail_pos==datas.head_pos)    //如果尾部节点追到头部节点 则修改头节点偏移位置丢弃早期数据   {       datas.head_pos++;       if(datas.head_pos>=BUFFER_MAX)           buffer.head_pos=0;   }}

中断函数

void uart1(void) interrupt 4{   if(RI)   {       uart_receive(SBUF);       RI=0;          }}

主函数

void main(){   unsigned char data ;   data = uart_read();}

如果缓冲区满的话,后面的数据会覆盖最前面的数据,如果末尾追上头部,会导致数据还没被读就被覆盖了,所以缓冲区的大小要根据自己的项目需求来进行定义,防止数据未读就被覆盖了。

喜欢这篇文章,欢迎点赞,分享,关注

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年10月1日
下一篇 2021年10月1日

相关推荐