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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
前言4 [+ n" v3 W0 a
单片机开发过程中,如串口通讯中,大家往往会遇到数据传输有时候并发量很大,处理不过来导致数据丢失。实际如何确保数据不丢失?估计有点经验的朋友都会想到缓冲存储。对的,先将数据存储起来,再慢慢对数据做处理。
  R0 r6 |( P$ y: d; D2 o# |: L* D2 k
1 环形缓冲队列
5 i4 b7 x% X' y% u6 n9 c' F环形缓冲队列,如下图,再初始化时队列头尾相等,表示没有数据缓冲,当接收到一个数据时,队列头加1,并把这个数据存在移动到的位置下,实现数据保存。当头尾队列不相等时,尾队列指针追头队列移动,这时就可以将数据提取出来。
- t, d: J" q( `) n/ X, U* b: i* U* B1 h2 R' z7 q/ C
& `2 m3 t. a; c0 l* d4 {
1.1程序; {& ^8 }. S- t; v, S( N
1.11队列实现8 Q6 {: M: ^& A. d+ s: x' ~, Y
#include "sy_fifo.h"; ~, f; b) M, x0 L2 o8 B0 F
#include <stdio.h>
% F6 b' D$ ?* q#include <stdlib.h>
4 f7 Z) L: r/ I4 e$ f4 C1 M#include <string.h>
0 R0 S% D3 a; ]$ [//创建队列初始化2 R- O7 H* O, {) E+ p
void sy_obj_fifo_create(obj_fifo_typ_t *pfifo)
5 P( v1 W# M1 C{# o  r3 H- O6 b' y, q
          pfifo->_head = 0;1 _' f/ j7 H0 h+ ?
          pfifo->_tail = 0;6 f7 A$ F, e: L+ L' l: p; i- W
      pfifo->cmd_pos = 0;4 z# g; p3 Y; ?# F5 S+ }! N+ |; H
          pfifo->cmd_state = 0;8 V# B# y0 V1 ]& n3 S! j2 O5 o- _; {
}
5 B! [  B1 q" G' x' g//队列数据压栈
; d# ]# G- {9 R: Punsigned int sy_obj_fifo_push(obj_fifo_typ_t *pfifo, const unsigned char data)
1 ^( `9 k2 N# @- ]  G" Y{
: y1 W4 Q4 T9 n5 Q# V& a    unsigned int pos = 0;7 G8 Z% Q/ g) [4 E
        pos = (pfifo->_head+1)%QUEUE_MAX_SIZE;
. }% Y+ v1 @8 U; R; Y, t7 C" U1 R" G1 Z    if (pfifo==NULL)
; O  R: e' O! V) g5 ^    {
. K/ {5 |: S8 d+ \( H% b        return 0;9 C6 I" k9 ~- T$ t8 W/ [, A
    }4 U; D, N: D2 h6 }/ p* r; t
    if(pos!=pfifo->_tail)  //非满状态  }% I/ V7 l# J$ X0 f
    {
+ ~: ^3 `# _2 n2 C2 u, B                 pfifo->_data[pfifo->_head] = data;
. Q3 [% O; n/ J& J         pfifo->_head = pos;
5 ~2 c- f# D% H. i9 N! [5 S               
$ v0 `0 W# w$ ~+ ?& `                return 1;
2 M. _6 {4 W/ Q. o) A' D    }  t- V& W! o1 @5 f6 S3 h
   return 0;* k* S+ q: `9 V; c. F
}( t. U( b( q3 g3 W- t
//数据占用大小5 D6 \; o$ V3 V0 G2 d
unsigned int sy_obj_fifo_get_occupy_size(obj_fifo_typ_t *pfifo)6 C: ?5 @, w/ y( ]$ J& a8 o! W* t2 E
{& c; k$ J8 E4 {( Z$ }% i. s+ R6 q
    if (pfifo==NULL) return 0;
0 @, V- i$ O9 M& g3 {3 G' ?. _   return (((pfifo->_head+QUEUE_MAX_SIZE-pfifo->_tail)%QUEUE_MAX_SIZE)*CMD_MAX_SIZE);+ _: q- {2 Z6 `! M$ Y5 c) ~
}
! h, q, e. k' _6 j) a% c8 m7 A//从队列中提取指定长度数据 ,这里只是提示一个例子,具体根据自己实际项目实现0 C. M; U: a7 O. ]6 r3 i3 V+ j
unsigned int sy_obj_fifo_read(obj_fifo_typ_t *pfifo, unsigned char *buf,const unsigned int size)
# P" n0 Z/ I9 e4 _* ], R; S# s# S{
9 `6 B  y+ K6 x- G$ @
3 L' n  D; ?5 `1 o& ^        unsigned int i= 0;
+ B/ F) Z4 u# \1 H- Z6 X0 c0 q        unsigned int data_len = 0;: }' @* J2 q. b, |
, r9 q: M- _7 Y* t: I  Q2 V
    if ((size==0) || (pfifo==NULL) || (buf==NULL))" m+ v* @" d8 m. E( Q! o" i
    {
; q3 L$ ]$ h; h/ e  J+ \* i           return 0;
6 V. ]. R9 N: H* |    }( ?4 f" B% O& W* O/ K/ U

/ z, b4 {, V( A+ U% }4 h7 X$ m. h        if(sy_obj_fifo_get_occupy_size(pfifo)<size) return 0; //数据长度不足,退出& A! U% x, ?0 L3 d8 K% D0 C) W

+ W8 _4 ?1 r- D8 U  b% J  for(i= 0;i<size;i++){
# k4 d3 ?5 X3 ]! @- m
; H2 O' o! P5 @" z  X% a    if( pfifo->_tail!= pfifo->_head)                                          //非空状态
; _" D5 k! H/ n    {7 n5 o' x# n5 F9 K
         V* Q9 @# L( q% d& F2 m
          *buf =  pfifo->_data[ pfifo->_tail];
5 J1 X7 T% }; Q; i                  buf++;" Q. M/ I7 g2 z1 h: A
          pfifo->_tail = (pfifo->_tail+1)%QUEUE_MAX_SIZE;  U/ q' I1 X* Y1 K5 n8 n
          data_len++;0 r; q% y0 v" v* `$ q0 H
    }  ' }( X7 G0 Z8 I" t5 S4 `
  }+ a8 s$ f+ M- Z! w* \& Z6 ^
    return data_len;, q- @3 x( k! R2 k% n. q5 n5 I
}
' C! E) o! ~- B4 u6 u1.12 头文件实现
/ {5 l8 F( Y: ^$ s9 q  u: t! B5 r1 W3 Y6 u! Q* f8 z
#ifndef __SY_FIFO_H5 _$ K* Y6 C4 K  w
#define __SY_FIFO_H
6 _" C0 q& z2 S! p#define QUEUE_MAX_SIZE 1000# U6 G) O) S, w! L3 I
typedef struct
5 S* l% u1 O3 e/ K4 P+ Z" q+ Q{
( Z) r% M6 [6 T        unsigned int cmd_state;, f% u1 m2 ]: ]2 b2 n2 K
        unsigned int cmd_pos;
6 V1 H9 K+ G! A    unsigned int _head;                                                       //队列头: {. K! X/ D) b* r9 ]) w
    unsigned int _tail;                                                       //队列尾
) `  A" d1 U  A! \, g  h    unsigned char _data[QUEUE_MAX_SIZE];
  z$ W# d- ?" B) w}obj_fifo_typ_t;( C7 s4 A! ?* H0 P! s& j
void sy_obj_fifo_create(obj_fifo_typ_t *pfifo);/ ~2 o% _0 F3 }. _( C/ r/ B
unsigned int sy_obj_fifo_push(obj_fifo_typ_t *pfifo, const unsigned char data);7 F4 C, F& H) ?8 z1 M- J& ?# o6 m
unsigned int sy_obj_fifo_read(obj_fifo_typ_t *pfifo, unsigned char *buf,const unsigned int size);# `) ]/ F8 t# n% @# g
unsigned int sy_obj_fifo_get_occupy_size(obj_fifo_typ_t *pfifo);
: n8 p* [  u4 o$ k9 c8 ]5 ^9 r2 [0 S/ G' D  R8 q: Q
#endif5 D) l: r* q& b, G. y
1.13 demo
! e5 f. m- z  H7 w. |3 g5 Q.......................................
" ~2 X* U, W8 [6 a( Z; e7 S2 E( E, ^obj_fifo_typ_t  obj_usart_buff; //定义一个实例) V, E5 a5 b) ]' z1 c& n5 I
void main(void){
$ u  }% Q* u! i$ j2 y  ~unsigned int data_size = 0;
. K' s" q' {; U: ~' lunsigned  char buff[20] = {0};. t1 h0 g. I' s; _4 _) z" u
..............//user handle% C! O& |& k: o$ z; ]: m# V
sy_obj_fifo_create(&obj_usart_buff); //创建一个环形队列实例
4 {4 K6 `; E& l( R* Y  c        while(1){
8 [8 |% p3 S( M2 J/ _& q/ {% _, B3 t. B        data_size = sy_obj_fifo_read(&obj_usart_buff,buff,10);//取10个数据. \+ |/ @8 F4 s; g8 q7 F, A
        if(data_size == 10)
( O; O: z; v$ i        // user handle
0 H) W3 o& e) a        }3 q! A1 D1 m5 I1 [. M2 M
}/ Z$ i, n+ n" f8 p+ R

9 b4 N( u  l( A* O5 ~9 J//串口为例将串口接收到的数据压入队列中0 [7 D' Y- H4 ]; i
void UART0_IRQHandler(void)
! L8 E6 T2 I! u{
5 G! A6 W# j+ _! D7 E$ X5 w        unsigned char data = 0;
8 W8 V+ a% D& @7 \5 C    if (UART_GetITIdentity(UART0) == UART_IT_RX); ^; X( w5 |! ?. X2 c
    {
* S  O& q6 i9 {4 a2 I1 x                 data = UART_ReceiveData(UART0);( L/ M% z: m- l) \/ A  d
                sy_obj_fifo_push(&obj_usart_buff, data); //将数据存到队列中% l8 M+ ]+ v+ z; n/ g: F( X; K
    }/ l, E0 ^. {0 ^1 O5 G/ ?
    else if (UART_GetITIdentity(UART0) == UART_IT_TX)6 w& H" }; e- `) W, a
    {( `) w' ?0 D* Y& D  U% X, s3 }; ~
        UART_ClearTxITPendingBit(UART0);
% I/ l( y$ k: t    }6 c* D/ O# E5 ~7 A5 j6 d8 j

该用户从未签到

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

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-10-30 17:13 , Processed in 0.156250 second(s), 23 queries , Gzip On.

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

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

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