找回密码
 注册
查看: 285|回复: 3
打印 上一主题 下一主题

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
前言
! M/ H# V* E0 I8 ~" D5 x单片机开发过程中,如串口通讯中,大家往往会遇到数据传输有时候并发量很大,处理不过来导致数据丢失。实际如何确保数据不丢失?估计有点经验的朋友都会想到缓冲存储。对的,先将数据存储起来,再慢慢对数据做处理。8 I  w4 n8 h/ t+ ^$ _1 T

* E+ X5 N% A7 t; b% B1 环形缓冲队列. F8 R# u% v! u7 W
环形缓冲队列,如下图,再初始化时队列头尾相等,表示没有数据缓冲,当接收到一个数据时,队列头加1,并把这个数据存在移动到的位置下,实现数据保存。当头尾队列不相等时,尾队列指针追头队列移动,这时就可以将数据提取出来。: T$ P# t) e0 V3 E" {) G

' t3 n  m4 O5 T( ~2 ?: }# h( Y+ A+ g3 ?
1.1程序& L; J- t$ n- o, M6 {- w- i
1.11队列实现* d& M, }5 W* y4 M/ a1 o
#include "sy_fifo.h"
! \9 F3 b5 A+ `/ R: N4 s#include <stdio.h>
2 [+ A& C5 |* y1 p7 c4 z9 a7 S( B5 X1 m#include <stdlib.h>% I) p! l: T; z6 P% Q6 T! h" y: e
#include <string.h>  n) z9 }0 O& P! }; N, i6 f( ^/ C
//创建队列初始化
' c" Q( {; [! s3 L  a# _' s7 O" H4 zvoid sy_obj_fifo_create(obj_fifo_typ_t *pfifo)* }6 E' c# d, e6 p# M6 D
{
6 E' v6 ^5 h( p8 k- A          pfifo->_head = 0;
0 @4 y/ Z9 p/ ~; T          pfifo->_tail = 0;
8 t/ l% @6 o* p      pfifo->cmd_pos = 0;. r7 f% H0 q+ J$ X2 ]3 {* p
          pfifo->cmd_state = 0;* ^  I5 A+ T# x! g( I% f
}
& v$ ?# e) f% R& A! A- j& ^! J//队列数据压栈
8 N2 Y* P6 S( p) ^6 ^unsigned int sy_obj_fifo_push(obj_fifo_typ_t *pfifo, const unsigned char data)2 g  S  y. f* o: w1 x" Y. C
{! D% C6 Q( o8 ^* J* ^
    unsigned int pos = 0;
" r" f  L& k% R: _" f. }        pos = (pfifo->_head+1)%QUEUE_MAX_SIZE;) ^1 \% ]0 g7 P
    if (pfifo==NULL)6 E: K: s& ^8 m  N6 |! m+ i0 J1 s5 k
    {
7 e3 s# }7 b& B' X5 I5 {) X        return 0;- y* a. K4 A; x8 j
    }
8 L2 C/ n1 e; o1 K5 ]4 B( H    if(pos!=pfifo->_tail)  //非满状态
6 n6 R* {$ J# @2 @" i  s& ~( I    {
% W- U* p  v5 R% H                 pfifo->_data[pfifo->_head] = data;
/ u  \- x. }, O4 W  M         pfifo->_head = pos;
- Q  g1 A: \7 i  M! U) A               
4 }, l' f7 h4 A' d                return 1;& c3 Z$ _5 ?* s2 Q; l0 e& W
    }6 `. C2 y. q, t! G) t7 S2 ?
   return 0;8 r" _# @( |# d: \2 t' S( P" w
}* L( d" J* F! I/ p0 U
//数据占用大小( o% }8 V. R4 R
unsigned int sy_obj_fifo_get_occupy_size(obj_fifo_typ_t *pfifo)/ a  O4 c$ \$ H" u
{
( X! u8 o0 n/ F2 t6 w2 |0 n    if (pfifo==NULL) return 0;
% J# G  U# P" H; e   return (((pfifo->_head+QUEUE_MAX_SIZE-pfifo->_tail)%QUEUE_MAX_SIZE)*CMD_MAX_SIZE);0 @2 d) u+ ~) f5 B3 f
}
8 Z( g3 G5 k% \6 C2 w1 Q6 z//从队列中提取指定长度数据 ,这里只是提示一个例子,具体根据自己实际项目实现
' E! P4 J  _" t2 X. t3 }unsigned int sy_obj_fifo_read(obj_fifo_typ_t *pfifo, unsigned char *buf,const unsigned int size)) _/ [+ a# I5 T. P
{: V' W% O5 D/ N3 `$ }
7 C  Y$ ~! f9 l6 f2 D
        unsigned int i= 0;
( v( X' F# U1 r& o4 d+ }        unsigned int data_len = 0;
% |1 r, z, i8 N- T1 W% L0 q9 W$ d5 \) ?+ {
    if ((size==0) || (pfifo==NULL) || (buf==NULL)); @, q" \! r/ m( c' ]
    {
' J3 N+ M$ Z" I  @  k5 u  P$ s           return 0;6 C7 t# D1 ~1 z
    }& d# P! \* `4 c+ K; j

. j$ X; y- f8 E+ d2 k3 ?& P' w        if(sy_obj_fifo_get_occupy_size(pfifo)<size) return 0; //数据长度不足,退出" I+ F! ^* g* `, l0 n" e
7 s3 j( H: C! t* V, l
  for(i= 0;i<size;i++){) {% c: k9 t9 K! e5 b0 F, w1 m( i

  G$ f6 ?0 N# Y1 L    if( pfifo->_tail!= pfifo->_head)                                          //非空状态
. c& ^' W- R* M  o9 u; A    {% h2 q  U7 {, `0 C' h+ ?' ]
      
0 h0 G- \" J9 P" J( |          *buf =  pfifo->_data[ pfifo->_tail];
$ z/ y  [+ A5 f                  buf++;, w& v1 N3 w* A9 A
          pfifo->_tail = (pfifo->_tail+1)%QUEUE_MAX_SIZE;  E9 e3 i3 P4 v+ {9 v
          data_len++;4 [: L0 k, D6 o1 @5 ^
    }  
% S0 S/ X7 [2 X7 ~$ z; B  }
3 L# t; V, i9 d    return data_len;
* U+ d* p  x7 p7 ~9 Z}5 W6 y% a+ E4 y5 [# @0 J& [
1.12 头文件实现3 M2 G) i4 Y6 x6 M! N

* Z! j0 M  ~( o7 h7 ^4 y. A#ifndef __SY_FIFO_H9 ^! u; b) L/ d4 y1 Z+ f
#define __SY_FIFO_H
9 c6 V+ a! F6 d  n% d5 ?1 {#define QUEUE_MAX_SIZE 1000
* n3 s$ s. y2 l8 D5 q( z' U  K2 F# ~typedef struct$ x5 B  H6 P$ _1 `3 l$ f
{9 G: _; f/ z% }+ U
        unsigned int cmd_state;" d% p) c& D' F$ h
        unsigned int cmd_pos;0 ~% T) `5 ^' t3 P+ r5 Z4 u$ L& O
    unsigned int _head;                                                       //队列头0 [" A. t0 l3 \0 l! ?0 w: d
    unsigned int _tail;                                                       //队列尾" J& \# k, r3 p+ `; ?
    unsigned char _data[QUEUE_MAX_SIZE];
2 ?$ W4 h# T" a6 {. W! l}obj_fifo_typ_t;
! A: p, N2 N; y9 U/ R2 b1 n8 j8 svoid sy_obj_fifo_create(obj_fifo_typ_t *pfifo);
2 b' b! s9 h2 j/ Iunsigned int sy_obj_fifo_push(obj_fifo_typ_t *pfifo, const unsigned char data);2 P) d* I6 d# s$ q- v
unsigned int sy_obj_fifo_read(obj_fifo_typ_t *pfifo, unsigned char *buf,const unsigned int size);' g8 q- r4 m/ o* n7 W
unsigned int sy_obj_fifo_get_occupy_size(obj_fifo_typ_t *pfifo);* E+ g5 c# l$ k
9 A* a1 U3 U& J( k2 Y/ K. I
#endif
9 H; \) r6 m3 `' J  M( c" Q. z1.13 demo
5 f# {* i1 a" H  m.......................................
4 @/ r& r8 R% X8 `& k/ S# Robj_fifo_typ_t  obj_usart_buff; //定义一个实例
$ @  O  ~  V, l5 Pvoid main(void){
# L' N+ |) v/ ~7 H2 H7 hunsigned int data_size = 0;
7 p' }- ?5 s8 E$ j9 w2 Y. Gunsigned  char buff[20] = {0};+ U0 l4 o6 L7 P% |/ y! b
..............//user handle
$ k: J; ~: e4 a7 H0 v9 Z  esy_obj_fifo_create(&obj_usart_buff); //创建一个环形队列实例
) b( Y1 x2 s, A; T4 Q+ @; \2 q        while(1){
) w- K' ^* N1 F2 ^        data_size = sy_obj_fifo_read(&obj_usart_buff,buff,10);//取10个数据- {0 c3 Q. \- r" R! W" O
        if(data_size == 10)- x9 V' Z2 j% I) w0 c
        // user handle
% e7 E+ p8 e9 ^& z. {7 j2 k& S        }
1 y! J* n; x" }% x3 F5 ^' W) q& T}
+ q6 U. u6 C2 J: ~) f1 _/ d8 l' Q. G! N+ P/ [7 h) q  Z# }
//串口为例将串口接收到的数据压入队列中3 @- p2 z7 T: w, c1 T
void UART0_IRQHandler(void)( z+ i5 e6 }; H+ `3 l
{
, r0 _8 o7 J, K2 O1 O* x        unsigned char data = 0;- t( ]/ }& b3 F6 D
    if (UART_GetITIdentity(UART0) == UART_IT_RX)
' p0 A& E( n# t' |    {% F+ m: L, f* _4 i4 Y
                 data = UART_ReceiveData(UART0);$ }! V2 |' X4 T0 t
                sy_obj_fifo_push(&obj_usart_buff, data); //将数据存到队列中
+ w" ~# ?. Z4 }' p    }
; A# Z! ?2 Y( O, ^* ]    else if (UART_GetITIdentity(UART0) == UART_IT_TX)
; J4 ~' K- Y9 j$ V* Y5 ^    {
! e: c6 L/ |$ L" n1 i" u        UART_ClearTxITPendingBit(UART0);
8 F6 Q" t& d9 P* }+ ^2 C7 D    }
0 A1 \" Q3 E+ z0 Z) g

该用户从未签到

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

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-5-26 01:50 , Processed in 0.062500 second(s), 23 queries , Gzip On.

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

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

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