找回密码
 注册
关于网站域名变更的通知
查看: 340|回复: 3
打印 上一主题 下一主题

单片机C语言环形缓冲buffer之串口应用

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2022-6-15 09:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
前言# t3 d! E% c: H( R- O  H$ J
单片机开发过程中,如串口通讯中,大家往往会遇到数据传输有时候并发量很大,处理不过来导致数据丢失。实际如何确保数据不丢失?估计有点经验的朋友都会想到缓冲存储。对的,先将数据存储起来,再慢慢对数据做处理。  x9 G: C* V& p: H
5 ?1 ^8 h+ S  k, Y7 j6 n
1 环形缓冲队列" u* {! C* M( y6 V- Q
环形缓冲队列,如下图,再初始化时队列头尾相等,表示没有数据缓冲,当接收到一个数据时,队列头加1,并把这个数据存在移动到的位置下,实现数据保存。当头尾队列不相等时,尾队列指针追头队列移动,这时就可以将数据提取出来。; S, i" t* N1 H0 s

+ v, k) I2 k: m5 C7 U
, S$ V! K* O. \0 V5 L5 R- O: M5 p2 v1.1程序6 T7 c5 i6 h+ l$ H2 w/ U( u
1.11队列实现9 K$ t$ d6 k9 @, D; D# Z, A
#include "sy_fifo.h"
$ W/ y. o. b+ o#include <stdio.h>* [8 ?; l+ N& _# x+ h
#include <stdlib.h>
% }- Y# E; J+ Q* m7 y#include <string.h>( o* {: }9 ?7 ^$ e
//创建队列初始化3 U- }# F7 U! O3 p
void sy_obj_fifo_create(obj_fifo_typ_t *pfifo)" k0 Q6 H8 `# v& N* p
{0 y+ Q/ R3 F  p! w& W/ K4 z
          pfifo->_head = 0;
0 g9 J- t; E  {1 k' H  `          pfifo->_tail = 0;- G! e7 }& ^3 E9 ?* E1 o
      pfifo->cmd_pos = 0;
  I; m! [4 U( R* Y* i          pfifo->cmd_state = 0;& ~6 C7 Q# I/ l* o4 v
}8 s) u& o% M7 \- h/ u+ ?9 H: W
//队列数据压栈
9 S) I1 h3 ?* L6 ]- {unsigned int sy_obj_fifo_push(obj_fifo_typ_t *pfifo, const unsigned char data)9 B9 g) G/ O5 ~: l
{' ~: _2 K. {5 t# x4 c& s
    unsigned int pos = 0;/ G. u4 `9 q- B5 c- m. m% s3 R
        pos = (pfifo->_head+1)%QUEUE_MAX_SIZE;
! _1 r7 L1 \& P/ O    if (pfifo==NULL)1 @* {  c; Y6 ?# W2 b
    {% L1 m. g4 b2 o
        return 0;
% Y% K  b+ y$ E. }8 _& H+ w; j    }
9 N; C; R2 J; W& \" `$ _    if(pos!=pfifo->_tail)  //非满状态  s" j4 W6 I  k& h% F8 _
    {
- o( `" S8 b8 ^% Z! a- w& x3 ?                 pfifo->_data[pfifo->_head] = data;+ a5 W; R0 R3 h3 }, U2 z& Q- ?
         pfifo->_head = pos;
' n9 E, ~3 r4 @- H) c7 D               ; j6 B' }7 q9 Q9 d. H, X
                return 1;
1 f5 r" `- y3 W- g2 z3 m0 y- `    }
* a5 q  Z6 _$ s  H1 _" t5 s4 f; s   return 0;/ V' e5 y6 D, Z6 `" @- F0 d
}3 U& X: G; L4 @
//数据占用大小
: n0 {' S9 ^! ^- n1 E4 j+ ]1 S4 Hunsigned int sy_obj_fifo_get_occupy_size(obj_fifo_typ_t *pfifo)
0 n) {7 r* |9 Q; H1 B5 J0 ?3 t{  X* m2 ]% @0 p5 J2 y
    if (pfifo==NULL) return 0;
( b+ N1 k( V8 A( L$ E   return (((pfifo->_head+QUEUE_MAX_SIZE-pfifo->_tail)%QUEUE_MAX_SIZE)*CMD_MAX_SIZE);) R* K5 p+ c& L6 O8 P) J9 H! ^1 }( a$ w3 ?
}5 Q: R3 y; z* Z" w! i! \
//从队列中提取指定长度数据 ,这里只是提示一个例子,具体根据自己实际项目实现
0 b2 e; Y, u' L; p9 c2 v: Gunsigned int sy_obj_fifo_read(obj_fifo_typ_t *pfifo, unsigned char *buf,const unsigned int size)
* P- [+ z( ]- T  Y8 _; _8 _6 X{( }) ~( j  J3 ]7 l9 y
5 R0 j8 v+ L  ?2 |. T
        unsigned int i= 0;
2 e5 ^# k! D/ ^& t0 E2 }        unsigned int data_len = 0;
! [7 _4 J1 x2 Z: P
' O0 V, A2 u, I& Q    if ((size==0) || (pfifo==NULL) || (buf==NULL))
$ Z! ^4 T7 G. U3 q    {7 a' Q; P9 }  ~, W+ g: E9 R
           return 0;
6 |, o" H  s: V7 B+ {  m    }
+ n) T3 \" G3 c7 T. [6 K/ `' M8 m  O! O+ p( ^
        if(sy_obj_fifo_get_occupy_size(pfifo)<size) return 0; //数据长度不足,退出
2 n, g" [  A% a' i+ H6 {
8 b7 H/ T/ S9 y  for(i= 0;i<size;i++){
0 F7 C9 _& Z2 ^
3 l4 S- }/ Y, f9 m' r    if( pfifo->_tail!= pfifo->_head)                                          //非空状态
3 h3 A+ b6 j) i* K2 q# M- G( ]    {
; ?/ T: G; K; D- C  l% O/ z) h2 f      
' n" |- J& m, ]          *buf =  pfifo->_data[ pfifo->_tail];
  i  g) Y/ R. }, E" @: `                  buf++;% M6 u5 K5 s' R* y6 o- F" T
          pfifo->_tail = (pfifo->_tail+1)%QUEUE_MAX_SIZE;& ^# H* V4 |. B0 S; r- p
          data_len++;
  S! L; P4 O2 _6 M' ~    }  $ r3 @! t- W, C" a- e0 ~4 Q
  }$ k# p' ~5 ?7 W8 x2 s8 A! c; B  m
    return data_len;2 m' U5 z$ b# x" R
}  F- K; G( M2 v% O/ N, p0 M
1.12 头文件实现
" N, L0 q! ?1 }6 N0 ^1 k
8 t( x" r0 e& I. O#ifndef __SY_FIFO_H
! w9 r7 S3 k# Q) o; ~7 `#define __SY_FIFO_H' v. `: s4 a$ e+ n  E* |
#define QUEUE_MAX_SIZE 1000
6 Q  T5 i4 y/ M6 Btypedef struct" V! }6 E& c1 }
{1 V' H# R7 A' m) ^- }/ J
        unsigned int cmd_state;
* I: z$ n2 v& |5 l" h% l" A$ }        unsigned int cmd_pos;$ s3 S% }9 M1 [9 s+ q
    unsigned int _head;                                                       //队列头
5 L6 m. f  C" d! P: ~6 F# m: O    unsigned int _tail;                                                       //队列尾/ q( z0 [: j: n
    unsigned char _data[QUEUE_MAX_SIZE];
# v3 [# w1 B& y* g: m}obj_fifo_typ_t;
: n2 {# r' b# c' {+ f7 W' tvoid sy_obj_fifo_create(obj_fifo_typ_t *pfifo);
7 {) }4 K' k6 L$ N2 O& {. H6 Iunsigned int sy_obj_fifo_push(obj_fifo_typ_t *pfifo, const unsigned char data);; `0 {; p1 V7 ]# h% I8 Z4 F
unsigned int sy_obj_fifo_read(obj_fifo_typ_t *pfifo, unsigned char *buf,const unsigned int size);
4 `" v! |6 D/ Y+ f7 Eunsigned int sy_obj_fifo_get_occupy_size(obj_fifo_typ_t *pfifo);; I. I1 x8 p; i  {1 p4 T/ }( A, g

. R: Y' |8 o1 k, U#endif* |. r7 f9 ?8 e4 w7 I; O
1.13 demo8 f& l) A3 s6 m- C0 q/ z% E  L3 S
.......................................
3 Y2 B1 z7 F: A4 G: S6 [2 ]obj_fifo_typ_t  obj_usart_buff; //定义一个实例# |  M* O5 ]7 E4 l1 q% G9 x) W
void main(void){
* J8 ?1 p" D% n) f) r5 E* Xunsigned int data_size = 0;, O7 L$ y  D! W/ ?; U
unsigned  char buff[20] = {0};
0 V3 g5 \' r8 m# u# w( ]2 a/ Q4 e..............//user handle8 ?  }; Y9 W- R" E4 H
sy_obj_fifo_create(&obj_usart_buff); //创建一个环形队列实例& T4 S( w3 G. w# ~) \" ]" C0 |" d* Y. q
        while(1){
$ g8 s$ O$ ^) Z$ C  ~8 d0 A        data_size = sy_obj_fifo_read(&obj_usart_buff,buff,10);//取10个数据
- t5 q1 `6 _0 n: o8 y+ i        if(data_size == 10)* d$ j; T& O# L" _. n, J, B
        // user handle0 `  X! W# ]& m" _; `
        }( |) J, G: J# a
}
. U) L% t$ E/ c! P. G4 c- ^5 ^; d+ F1 R' r
//串口为例将串口接收到的数据压入队列中& R7 u" _" H! i; X. ^
void UART0_IRQHandler(void)
! l  x1 V" B! W- I8 [5 y{1 g: Y4 F' [) J# g( I  l) Y5 A
        unsigned char data = 0;# T, I8 n/ ~9 }3 O
    if (UART_GetITIdentity(UART0) == UART_IT_RX)
# k7 a& T$ L/ p. A    {: d! c" K8 @! X4 Z
                 data = UART_ReceiveData(UART0);. x6 y$ }+ L+ X* l. Y" m4 _9 u$ O
                sy_obj_fifo_push(&obj_usart_buff, data); //将数据存到队列中1 A9 F" S0 f# T: T
    }: _3 j) j3 I0 j7 t( ]
    else if (UART_GetITIdentity(UART0) == UART_IT_TX)
3 D# z2 L2 \' k8 _    {
3 w1 G; ?& G! y0 l- i' Q# k3 i8 y: U        UART_ClearTxITPendingBit(UART0);
* `2 U8 |9 [. {9 i4 e    }5 z8 \0 V/ o+ U2 E

该用户从未签到

2#
发表于 2022-6-15 11:13 | 只看该作者
感谢分享!!!!楼主

该用户从未签到

3#
发表于 2022-6-15 14:22 | 只看该作者
感谢分享!!!!楼主
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-11-4 11:08 , Processed in 0.140625 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表