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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
前言" g2 k* F5 Y7 R
单片机开发过程中,如串口通讯中,大家往往会遇到数据传输有时候并发量很大,处理不过来导致数据丢失。实际如何确保数据不丢失?估计有点经验的朋友都会想到缓冲存储。对的,先将数据存储起来,再慢慢对数据做处理。8 B4 O" g$ m' @% W( x% e. t8 `

: B: f/ |7 W) ?: B8 r/ p% Q- j" h1 环形缓冲队列
5 v$ l0 W- y1 U6 k9 u环形缓冲队列,如下图,再初始化时队列头尾相等,表示没有数据缓冲,当接收到一个数据时,队列头加1,并把这个数据存在移动到的位置下,实现数据保存。当头尾队列不相等时,尾队列指针追头队列移动,这时就可以将数据提取出来。
& h( x5 k' |* c$ ^# d! t
- T! h$ f2 G/ ?# Y) x5 _4 f6 h0 |- b* c  q) m6 W% a
1.1程序
1 b# G" q+ \7 H1.11队列实现+ f& Z  k# t$ y1 ]4 D/ u4 X& L
#include "sy_fifo.h"
3 S8 l) o' G& `1 x#include <stdio.h>1 G( s3 v2 L( m1 Z$ s
#include <stdlib.h>/ m# C% @- c' B* k8 m6 A
#include <string.h>
2 D2 d  Z$ l3 {* [9 E8 ]//创建队列初始化
  x: l, k6 \$ W* lvoid sy_obj_fifo_create(obj_fifo_typ_t *pfifo)
3 Q4 g6 d* N: r3 j$ D/ P{. u7 Q+ ~" M& g1 S( J3 Q# G
          pfifo->_head = 0;
! ^" n' ^9 Z* z" O% ~! H* m          pfifo->_tail = 0;
$ H8 a+ z- G; f9 c      pfifo->cmd_pos = 0;- s. c( p5 i2 B5 n2 B& Q
          pfifo->cmd_state = 0;6 |! R* `( W0 A5 ~$ B
}* U. C5 f# R/ ^$ @  t6 C+ J
//队列数据压栈
; y. {/ Q  k+ p6 f) G1 h) Zunsigned int sy_obj_fifo_push(obj_fifo_typ_t *pfifo, const unsigned char data)
( O7 p% B; J0 T6 k6 c: o0 W{
* r7 I, f  h2 g$ ]& l! O5 |    unsigned int pos = 0;
. N  G' X8 x/ X  [# Q6 K        pos = (pfifo->_head+1)%QUEUE_MAX_SIZE;+ c7 L# ~) c: F+ [. e. T) C( o
    if (pfifo==NULL)
# O5 k- [4 ?2 `$ O1 d    {
. }! a) X6 a, h8 Q1 D        return 0;) `" M7 m1 R% U1 G* n+ Y) G
    }
5 Y2 c+ r2 q/ U8 P5 X    if(pos!=pfifo->_tail)  //非满状态, f1 ~1 o3 I3 k4 b
    {8 Y- p6 r& W5 F( s& o% H! K+ A8 y
                 pfifo->_data[pfifo->_head] = data;6 a% c2 r/ i+ W( |. g% Q; a$ s
         pfifo->_head = pos;
+ O. \0 j1 ]( S2 g6 s               - B; C1 j4 h; z5 Z# q; g/ X+ m9 C
                return 1;6 _. v8 H4 \3 S5 B
    }. Y8 X: H; R9 S4 ^7 K
   return 0;& ~0 l) a) |& S$ N1 h; Q5 R
}
; ]/ Y5 G' k# C8 u% l5 ^8 K0 ]5 W" R//数据占用大小
( ]/ F+ \# _2 l* }" l9 xunsigned int sy_obj_fifo_get_occupy_size(obj_fifo_typ_t *pfifo): f: B2 C* J1 s9 i  X% r
{
/ [' D' j+ S# j) c  n3 l+ e- \1 R    if (pfifo==NULL) return 0;: Y+ k/ D* e; x' K
   return (((pfifo->_head+QUEUE_MAX_SIZE-pfifo->_tail)%QUEUE_MAX_SIZE)*CMD_MAX_SIZE);
5 Z; S* D% j! L% x}+ B. l# F$ d$ H2 x1 N& i
//从队列中提取指定长度数据 ,这里只是提示一个例子,具体根据自己实际项目实现
5 W$ R; y9 k  l( Z3 O0 ]; p# Yunsigned int sy_obj_fifo_read(obj_fifo_typ_t *pfifo, unsigned char *buf,const unsigned int size)3 R% i* k; d0 _' {, f
{
. A0 h1 m/ r( ?, }( H6 o: F/ B
$ Z3 I4 _* ]5 q( [4 T+ |4 ?        unsigned int i= 0;- B) q: R  C# ?- ]; `+ n$ n7 r: D
        unsigned int data_len = 0;& n; Y3 j' {' w
8 m& j9 |! E( ^+ N# Y! q
    if ((size==0) || (pfifo==NULL) || (buf==NULL))% T3 d& u. e7 q7 P$ D3 p% O, H% ]
    {
; Q, A) u4 M# d, Z# P2 \           return 0;2 \& c7 n3 S" c$ @; s' u
    }
! L5 r3 d; H; m- Q( O; o% D5 _, t& O( ?0 R/ B1 o5 t
        if(sy_obj_fifo_get_occupy_size(pfifo)<size) return 0; //数据长度不足,退出
9 j, ]+ i, o  @  c: J
% w) N1 E8 l% U* R  for(i= 0;i<size;i++){# U! y3 O! L1 H9 g
  c3 `6 ~$ r8 [! P$ v6 }, f5 y2 s
    if( pfifo->_tail!= pfifo->_head)                                          //非空状态
+ ~- B, _9 h4 Y% d+ u- P    {
1 K& Y$ f7 ]% W' e       1 S8 ]  y4 K4 r; L; O9 g. w) g
          *buf =  pfifo->_data[ pfifo->_tail];) ~/ |" u6 G( \1 V
                  buf++;+ ]& `, T* Y) z
          pfifo->_tail = (pfifo->_tail+1)%QUEUE_MAX_SIZE;
; k4 _3 O4 D+ A/ O          data_len++;/ n% s0 [7 e! w% P2 l) b
    }  
( [/ O) a/ ]4 ^  F" Q* E  }
" F1 c. i2 q: P9 S& x0 Q    return data_len;
+ ~" s' F0 g' ^8 Z}5 {0 ~: V- |  L. s" T" D3 j
1.12 头文件实现
5 A; J* R$ q" C4 o* t" Q. ]
- o3 S  M" U& z# P% L+ ^. `9 v#ifndef __SY_FIFO_H  P1 v% M9 @; M
#define __SY_FIFO_H
6 o& L1 ^+ [8 Q# p% C$ y#define QUEUE_MAX_SIZE 10006 `* j, `1 W* v- t/ t2 W3 i7 y. @
typedef struct! a: j; {6 E9 x4 O  Z' s: @
{  z0 L. c5 q  B0 c6 V) X
        unsigned int cmd_state;: p1 p! R, Z7 J
        unsigned int cmd_pos;2 _0 x  `# \$ L1 \- j) m6 u+ v
    unsigned int _head;                                                       //队列头
$ m0 e8 o6 e) ~: S9 l8 {    unsigned int _tail;                                                       //队列尾7 r# }& m8 N. x, z0 j' {4 s1 l6 a
    unsigned char _data[QUEUE_MAX_SIZE];, M2 F6 Q9 P9 @% u/ c+ I$ W3 J
}obj_fifo_typ_t;
5 V6 P. o6 Z7 C' |! svoid sy_obj_fifo_create(obj_fifo_typ_t *pfifo);
9 h6 k, h: @. \unsigned int sy_obj_fifo_push(obj_fifo_typ_t *pfifo, const unsigned char data);
/ d; h; v* F6 A& s+ n. Zunsigned int sy_obj_fifo_read(obj_fifo_typ_t *pfifo, unsigned char *buf,const unsigned int size);6 q9 I0 R& m3 t& U" C1 _
unsigned int sy_obj_fifo_get_occupy_size(obj_fifo_typ_t *pfifo);
3 F: \- q+ a* m3 L6 V" W6 _# L0 S" j2 n
#endif
$ D  Z5 |5 Y) `3 w/ l: Q1.13 demo; n; m* c) u& P5 U1 E! y( Y8 I
......................................./ A2 G' z6 q1 g! }3 F
obj_fifo_typ_t  obj_usart_buff; //定义一个实例
( J/ I& I+ o8 T3 P3 _/ A% ]void main(void){0 Y3 T3 ^3 K( Y6 J, k8 ~6 H
unsigned int data_size = 0;
/ s& B7 x: e  a' Funsigned  char buff[20] = {0};
; R3 C1 D; ]5 k6 n+ z5 D..............//user handle2 I! O  a+ Q+ j1 G$ U
sy_obj_fifo_create(&obj_usart_buff); //创建一个环形队列实例+ U+ l2 P* f- G4 Z
        while(1){, ^' R/ z, U2 U7 c
        data_size = sy_obj_fifo_read(&obj_usart_buff,buff,10);//取10个数据
. L+ p; b+ H; y4 S5 C5 ?9 q        if(data_size == 10)
; y3 `3 `/ Z! g+ y        // user handle
6 m' c! F! u4 z3 b' U& k5 p        }
8 [$ p1 |" B1 w& k! y: L6 Q3 s}
- O/ I0 a, ?( @! v9 i% ?# W" W0 W: o$ Y) E# Y* g( i1 I9 P  W
//串口为例将串口接收到的数据压入队列中
  x6 t; n, r) w" H. y2 X& ]void UART0_IRQHandler(void)
7 j! Y+ z, b1 G3 A# s{
; z* t& v$ ^( @8 [        unsigned char data = 0;5 a  F$ X% V7 H2 i4 G
    if (UART_GetITIdentity(UART0) == UART_IT_RX)
! k$ w( A- Q* z  I8 E  r    {$ G/ X& q* N, e" U. b4 Z' `8 Q- L1 z% s
                 data = UART_ReceiveData(UART0);" o4 X1 k8 }5 J, y+ Z; x1 F2 a
                sy_obj_fifo_push(&obj_usart_buff, data); //将数据存到队列中
8 G/ l+ o- A; K6 [3 q    }6 L+ \, M; R4 [- ], z* ~, e
    else if (UART_GetITIdentity(UART0) == UART_IT_TX)- }0 o. G( O/ {: f' K4 O. e
    {% p' B6 O3 S8 ]( F$ h* E
        UART_ClearTxITPendingBit(UART0);0 _4 f. z' W) L& O2 M* x% `5 ~  v
    }* A: L8 m$ {$ G

该用户从未签到

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

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-7-20 08:56 , Processed in 0.125000 second(s), 23 queries , Gzip On.

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

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

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