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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
前言  `& k; m# s4 V6 t4 w0 k9 y
单片机开发过程中,如串口通讯中,大家往往会遇到数据传输有时候并发量很大,处理不过来导致数据丢失。实际如何确保数据不丢失?估计有点经验的朋友都会想到缓冲存储。对的,先将数据存储起来,再慢慢对数据做处理。
& j0 w9 r" W/ V) g
1 N; f; s5 y( o* W1 环形缓冲队列
+ Q4 }* z: I4 ?0 a5 f4 M环形缓冲队列,如下图,再初始化时队列头尾相等,表示没有数据缓冲,当接收到一个数据时,队列头加1,并把这个数据存在移动到的位置下,实现数据保存。当头尾队列不相等时,尾队列指针追头队列移动,这时就可以将数据提取出来。
& S& `5 _; q3 ]' P) Z
  W7 E; j' y7 M6 ?* H  Z
. h. J; Q' F! `+ |  [: L1.1程序
$ @: e  S/ s2 z  L1.11队列实现! x' ^3 O9 i" J6 b. M9 w
#include "sy_fifo.h"  j: f9 I  p9 I' P% e7 Y1 S
#include <stdio.h>) _8 `2 _2 a1 X" x) a
#include <stdlib.h>4 k- V+ w* g: V; z# K
#include <string.h>4 \7 H8 q5 G( @) N$ \9 m
//创建队列初始化
$ ?3 P# m6 Z, s8 C& Cvoid sy_obj_fifo_create(obj_fifo_typ_t *pfifo)
6 F- X% r, D$ A: B, R5 x{5 u- c& ]# K3 w
          pfifo->_head = 0;
- e& ]0 c6 R, T: Z% s          pfifo->_tail = 0;
- n8 s0 w* k1 C; ^9 W  y- T      pfifo->cmd_pos = 0;
0 m7 ]0 S7 P' B# D. s. x) @1 Q          pfifo->cmd_state = 0;
& L* z' z1 t) b4 ^2 l0 O. y3 C- @% L}1 e1 \: \1 v1 {' D. s
//队列数据压栈! i' |' ]" f0 I3 G5 r/ K
unsigned int sy_obj_fifo_push(obj_fifo_typ_t *pfifo, const unsigned char data)
. w6 L# ^1 W) E" K$ c{- C- x4 `- x  \6 Z! v
    unsigned int pos = 0;5 N, z% y, F$ F5 B
        pos = (pfifo->_head+1)%QUEUE_MAX_SIZE;
# y. V# Y) g3 y! J9 J, Z* }$ S; `; C    if (pfifo==NULL)
) f' J5 R# u- G5 a9 ?) ~    {) }8 \* ], c$ y9 I
        return 0;; ^' |7 F9 ~! \4 o1 D
    }
  X; Y" f7 a/ B! ~    if(pos!=pfifo->_tail)  //非满状态
/ z" A/ N" K, |" w9 z# K- A    {+ ~- ~8 ~: F: w
                 pfifo->_data[pfifo->_head] = data;" r, l9 \7 z9 i5 j" S
         pfifo->_head = pos;
- c9 S8 \/ r# L7 r' R& H$ \) t               % G* s! y4 C- [! O7 y/ H( U  D
                return 1;! I9 P2 K/ n! N6 V
    }( u0 y2 U1 g* T7 m5 J4 H! D
   return 0;' @7 ]5 R4 G8 Z4 v3 q; d0 x( \& I& u
}
! S, k; \0 F% L  G0 n: W//数据占用大小
2 k+ q( N5 e" D& |4 p' Yunsigned int sy_obj_fifo_get_occupy_size(obj_fifo_typ_t *pfifo)1 {3 F' c$ D* h& ?& z3 c
{8 i0 k7 r) U2 _* g! u. p" n
    if (pfifo==NULL) return 0;. x6 s9 o" O* B7 S- y
   return (((pfifo->_head+QUEUE_MAX_SIZE-pfifo->_tail)%QUEUE_MAX_SIZE)*CMD_MAX_SIZE);6 |( o; }; |4 ], F- M
}
* X3 i8 @6 f% I//从队列中提取指定长度数据 ,这里只是提示一个例子,具体根据自己实际项目实现+ z0 i) ?6 Y$ M7 @! p! i0 H
unsigned int sy_obj_fifo_read(obj_fifo_typ_t *pfifo, unsigned char *buf,const unsigned int size)
& B  r& e: X1 r- \{7 Q: `; m+ k2 ?5 A6 y/ n

: k7 ?& K* i! P$ e+ A/ r        unsigned int i= 0;
" p) d/ R' M: A/ C7 [) e& ^        unsigned int data_len = 0;
1 @8 k* o* E. V# \+ W- g. @3 Y9 K! U. K$ x* G# T( I; F
    if ((size==0) || (pfifo==NULL) || (buf==NULL))- E* \& V: E5 r- i/ ]
    {
8 W' n) k; z( z! i! K; W4 ]           return 0;
, a2 E$ B' Z8 C+ b/ L) j1 w    }
1 n' v5 ^8 j7 s  v4 k0 q) z$ ^/ u" J8 A
        if(sy_obj_fifo_get_occupy_size(pfifo)<size) return 0; //数据长度不足,退出
. Y+ L( Y: P8 K4 p: o. C- n
1 l, G4 {  K7 N1 M- ~" d& `# ]  for(i= 0;i<size;i++){4 G2 K) M: u- {9 ~3 j4 g
. H" L# i6 m* d+ n6 `
    if( pfifo->_tail!= pfifo->_head)                                          //非空状态- w& a$ G4 d1 A& V9 o6 w1 j
    {: q% c6 \/ b% f0 [# v9 ^
       ) L" n: K- }. c. Z( t: a
          *buf =  pfifo->_data[ pfifo->_tail];/ c! q& x; ^+ Z  Z, q* ^
                  buf++;9 P6 `- t, O4 o8 O) u* s
          pfifo->_tail = (pfifo->_tail+1)%QUEUE_MAX_SIZE;
, c2 q0 h4 J, _. U+ C0 Z* {/ P- ^          data_len++;! o" z9 f* Z2 t  f! M! O) C
    }  
- n# u$ M$ F4 h- A0 [/ X/ B0 r, y  }% l, ?3 N9 }4 w" Z1 i0 Y( C6 n1 ^
    return data_len;; V- n+ G0 }; N
}
" Z! E! j  G# O$ G9 Z! k1.12 头文件实现
& g- r$ S/ O' J$ S8 j2 p
9 B- W3 z5 h, |: N% N' ?5 Y#ifndef __SY_FIFO_H  x/ [; e7 E' J) G' h
#define __SY_FIFO_H
* Z2 e. o5 J  Z7 G" O* z' H#define QUEUE_MAX_SIZE 1000
0 ], t' L" g! \" u" w0 e# n5 g; Btypedef struct. Q1 ?( ^" U- }7 I. q+ H6 Y
{
+ B4 P' H3 p. k$ T; a        unsigned int cmd_state;
1 l! w8 @& w7 j7 l        unsigned int cmd_pos;4 ?$ N# {) j3 b+ I$ e" W$ n
    unsigned int _head;                                                       //队列头; {- T& G2 E3 j2 }- ^0 l# \
    unsigned int _tail;                                                       //队列尾( o# q$ N) M: V8 f
    unsigned char _data[QUEUE_MAX_SIZE];! {0 Q, Y# T  K7 D1 o% ^
}obj_fifo_typ_t;
# X+ U, v9 R  x6 ^$ Fvoid sy_obj_fifo_create(obj_fifo_typ_t *pfifo);  b( {8 D: \4 @$ v+ B
unsigned int sy_obj_fifo_push(obj_fifo_typ_t *pfifo, const unsigned char data);/ }3 x9 R4 f( W6 I, z8 V
unsigned int sy_obj_fifo_read(obj_fifo_typ_t *pfifo, unsigned char *buf,const unsigned int size);
& r9 v/ I3 C& S4 o% R( A# hunsigned int sy_obj_fifo_get_occupy_size(obj_fifo_typ_t *pfifo);
6 S; p# Y, i6 K2 @
! K* y+ X9 z' e: v1 n/ `#endif2 H& z: e, Z. J( w. ~
1.13 demo, O9 n4 c; f4 S. m
.......................................6 j# A* X& s5 q, K6 n& m
obj_fifo_typ_t  obj_usart_buff; //定义一个实例" J* R% z  a3 @. T& c1 _
void main(void){
: n& H6 \& a. a( K4 {, vunsigned int data_size = 0;/ l" H" Y' e# I6 ~4 g/ {1 |
unsigned  char buff[20] = {0};7 A- u3 s& I) i0 d
..............//user handle8 F% K  e9 c- ]- q) M; ?
sy_obj_fifo_create(&obj_usart_buff); //创建一个环形队列实例  K" K; U' S3 J  K
        while(1){
2 @$ o* Z6 P- w7 {& D        data_size = sy_obj_fifo_read(&obj_usart_buff,buff,10);//取10个数据
! h# k+ F' l/ _+ s5 }4 V        if(data_size == 10)
) C. q* C* Y# n. D( s        // user handle
: o* {& t1 u  U        }% f- d) z& v! _( W
}
0 H% l5 M8 n. {* o6 a7 s% i2 H1 z& x( j  \+ ?6 D
//串口为例将串口接收到的数据压入队列中
# E, f( s5 T! X9 H; l$ Svoid UART0_IRQHandler(void)
2 Q* F6 C6 Z' a$ U, f& w3 s- K{7 R- ~4 x4 c! F0 L8 j' D0 N1 f* T
        unsigned char data = 0;
2 K' L. t* Z: C6 J% z4 H4 x3 G    if (UART_GetITIdentity(UART0) == UART_IT_RX)0 t$ [( m6 j" K; z3 t
    {
5 y. V! w1 g. K1 F, n; h                 data = UART_ReceiveData(UART0);
  [' y+ w+ C2 H7 R7 Z) {0 P" P% r                sy_obj_fifo_push(&obj_usart_buff, data); //将数据存到队列中
3 c5 D5 e% ?4 z- |& |$ A7 d    }: q+ D7 }0 B! F0 ^
    else if (UART_GetITIdentity(UART0) == UART_IT_TX)
" L% [, Z+ Y( `8 o1 m3 g. M    {# S2 B4 [& r/ h" v" |& b
        UART_ClearTxITPendingBit(UART0);
' E7 V" M6 `+ R9 c3 V    }
/ e: z6 b& Z: e" B7 E

该用户从未签到

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

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-9-8 02:41 , Processed in 0.109375 second(s), 23 queries , Gzip On.

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

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

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