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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
前言1 g' [. ]9 Q# l3 D- _
单片机开发过程中,如串口通讯中,大家往往会遇到数据传输有时候并发量很大,处理不过来导致数据丢失。实际如何确保数据不丢失?估计有点经验的朋友都会想到缓冲存储。对的,先将数据存储起来,再慢慢对数据做处理。
& Z- b1 p) P; I: Y9 m& A& t* Y" W- d( k) |' R9 H
1 环形缓冲队列0 b( B+ R& f6 b& H6 }
环形缓冲队列,如下图,再初始化时队列头尾相等,表示没有数据缓冲,当接收到一个数据时,队列头加1,并把这个数据存在移动到的位置下,实现数据保存。当头尾队列不相等时,尾队列指针追头队列移动,这时就可以将数据提取出来。
# I! H; c: T$ E8 k& r! ^# i3 ]! z1 Q' s4 S8 w
3 w% R- u+ w! p2 }/ u1 D0 `
1.1程序
; g- ^( A4 E4 e- |. V% b& s& M+ K1.11队列实现
; q) F% r/ V2 X( L#include "sy_fifo.h"
* J% W2 p- b5 l; h1 Y& w#include <stdio.h>1 N* j6 g- _3 H# b; M
#include <stdlib.h>
! E: `& m+ f; }#include <string.h>
! \1 [* ?% O2 n0 a$ J//创建队列初始化% Z, R) b" ?* J% Q2 ]7 D, o
void sy_obj_fifo_create(obj_fifo_typ_t *pfifo); R5 I5 v+ \, P. ~7 f9 q
{
% ^& ]5 R5 o" K# `9 \          pfifo->_head = 0;9 |( \" z$ p" }2 F3 V* U+ ]2 Y
          pfifo->_tail = 0;
8 V1 D7 F  x# E3 T6 X; @      pfifo->cmd_pos = 0;/ I6 K5 y; E, o( R; [
          pfifo->cmd_state = 0;
) H; {5 s, }. E}
& b4 h  R" E5 l* w0 n# E6 J//队列数据压栈! ?/ z8 P" X/ Q( H
unsigned int sy_obj_fifo_push(obj_fifo_typ_t *pfifo, const unsigned char data)
& i+ L( @: |+ B0 F{
; V6 r+ ]2 Q- q- s& _- f    unsigned int pos = 0;4 u. }, x& x% G
        pos = (pfifo->_head+1)%QUEUE_MAX_SIZE;/ q, K7 F' t# E  `
    if (pfifo==NULL)% ^: U: S) C3 l, \0 f) |8 o
    {% M$ C$ T2 o: s
        return 0;
  @* M2 d6 M; `# l  T- h& `    }
/ F- u, i+ t' A& ^7 {    if(pos!=pfifo->_tail)  //非满状态/ a! S$ ^3 C( t$ s  y- ~
    {
3 O' K; \- Q4 t' {9 M  A                 pfifo->_data[pfifo->_head] = data;( i1 T* M: }/ J+ r
         pfifo->_head = pos;4 k, N9 h6 g& i- P: D4 q
               
( G# a; i& ~; \* F) `. y1 h+ D                return 1;( p+ `4 q/ g8 n; u4 p, U" w
    }
( O- f6 ]" f/ G; p* M' f. C   return 0;
! W5 o# r0 }. j* m, l1 A}
5 |8 f! K5 g8 t' P8 M//数据占用大小
) E' H0 M3 t* O4 ^9 ]# \. Lunsigned int sy_obj_fifo_get_occupy_size(obj_fifo_typ_t *pfifo)/ u8 d) l5 R* }4 d% Z9 `
{
3 B% c& _  F2 h! V    if (pfifo==NULL) return 0;2 {  F) Q9 w) h1 `) [5 |6 L! y" h; I4 W
   return (((pfifo->_head+QUEUE_MAX_SIZE-pfifo->_tail)%QUEUE_MAX_SIZE)*CMD_MAX_SIZE);5 J" m9 D& i. n3 r, O+ @5 P/ a
}
( ^7 y4 B; h6 O) s# y( F( T8 Q/ e//从队列中提取指定长度数据 ,这里只是提示一个例子,具体根据自己实际项目实现7 y- |, y4 ?6 x& b
unsigned int sy_obj_fifo_read(obj_fifo_typ_t *pfifo, unsigned char *buf,const unsigned int size)
3 C) w) Z" A0 {7 e6 W{4 V# p( k& m. p  M0 Q0 O7 i
' B$ f& U5 l  Q5 I
        unsigned int i= 0;
  |" r* ~; {! F/ [4 L" k8 v# a% r        unsigned int data_len = 0;9 P7 p1 {  e) b! v( b5 t7 ^+ e  Q
9 k' a0 M" N3 [5 f% N1 @7 Q
    if ((size==0) || (pfifo==NULL) || (buf==NULL)), F% W% J* b* U4 s' v' F: F
    {
! S/ D6 h; i* e, G( L+ [0 V           return 0;
# B4 C' ?$ [9 x3 [    }% d+ m+ O! r) d/ p2 }, G( d
, t3 v) D0 q- S" ^3 @, C% X1 f6 [) \
        if(sy_obj_fifo_get_occupy_size(pfifo)<size) return 0; //数据长度不足,退出$ @1 t5 O4 ]! E
0 e$ q# _$ i& V% c0 E
  for(i= 0;i<size;i++){
- x% k. {, {! i) H* O  W9 Z- {$ F' M% Q; ?+ n
    if( pfifo->_tail!= pfifo->_head)                                          //非空状态8 s* y' b; k2 C1 z
    {
; g* `; j& I) ~% ^7 s1 ^       ) ?! g! `+ f0 ?- d: B; B" i
          *buf =  pfifo->_data[ pfifo->_tail];/ u4 V4 h; c  [' x7 B  o/ N
                  buf++;" Y! B7 A1 _' X# c
          pfifo->_tail = (pfifo->_tail+1)%QUEUE_MAX_SIZE;3 |! h6 B8 L# n( f( R* X
          data_len++;/ @% B# C' e# ~' ~; e5 s1 s& J
    }  ' _" c  I1 w" d1 J1 ?$ B  u
  }
# M3 f) k( E2 f* P: @, j+ \5 g    return data_len;# y# N3 y& K0 u6 o5 q6 K8 @
}
4 V, d) [8 H- E9 I$ z1 J1.12 头文件实现  N. m: g: s9 I/ p% A0 N8 G7 R8 j
& K7 l# F+ c3 i# w5 k8 H1 ?' W& q
#ifndef __SY_FIFO_H
$ C; y! Z, `; X3 d4 Y$ j#define __SY_FIFO_H
1 A) P% y6 ^) ~, I. G/ s! v# i#define QUEUE_MAX_SIZE 10005 U3 I0 e. `1 T+ f$ Y% P, n/ X* q
typedef struct. Q4 G# e) d9 y3 [  O- O
{3 t4 d5 i  M9 F2 |
        unsigned int cmd_state;$ ?9 B7 o6 A- }% c
        unsigned int cmd_pos;( m% ?5 Y. B! @, ~& T# P! f. l2 @* r
    unsigned int _head;                                                       //队列头3 m9 g* c' i1 r/ ~- U& Z
    unsigned int _tail;                                                       //队列尾, k4 B" g: l8 A
    unsigned char _data[QUEUE_MAX_SIZE];
6 [$ A, j+ u+ @, e1 U1 \9 K}obj_fifo_typ_t;
1 T- S3 Z! L' `- M4 ]. r$ kvoid sy_obj_fifo_create(obj_fifo_typ_t *pfifo);5 d% C' n% @+ t$ P  P
unsigned int sy_obj_fifo_push(obj_fifo_typ_t *pfifo, const unsigned char data);
3 [' P- a* l7 C+ N: ^9 E$ Ounsigned int sy_obj_fifo_read(obj_fifo_typ_t *pfifo, unsigned char *buf,const unsigned int size);" u% e) ?0 L5 d: r
unsigned int sy_obj_fifo_get_occupy_size(obj_fifo_typ_t *pfifo);
  L0 Z; b& M' Q" C* U- U- A* q( Q, R) ?: T5 h$ l
#endif9 j/ X3 }" Q# H) d
1.13 demo
# S# U" t( @: U* P: K7 ?.......................................$ `- x$ J$ p$ \2 ^2 v6 n
obj_fifo_typ_t  obj_usart_buff; //定义一个实例& s' ^  F$ ~% c' K3 W2 W% b1 ]$ R
void main(void){
* P8 \- ]; x$ X% i4 o2 ~7 `3 J, Iunsigned int data_size = 0;8 f# Z; F1 n/ q3 Y# s4 `5 g1 `
unsigned  char buff[20] = {0};! }$ ]/ M9 [/ e" b( P. |
..............//user handle9 m$ H) H" U7 e% p, d& G
sy_obj_fifo_create(&obj_usart_buff); //创建一个环形队列实例
, y( D# Q, F/ Q: J. u        while(1){7 F! \- y; I# v; F% x0 W2 K
        data_size = sy_obj_fifo_read(&obj_usart_buff,buff,10);//取10个数据4 c7 y) Z/ |# W/ ~/ `) k; I7 l! M* L
        if(data_size == 10)1 o8 ?% c2 e: V  ~7 i
        // user handle1 n, r( P7 f1 {
        }) s; J/ Z* |/ z% b! N- f* q
}
0 X/ W' F$ D8 H* d. d$ {- c0 A( ?2 z) H: N3 f
//串口为例将串口接收到的数据压入队列中
+ B' H2 X) a% B7 M6 l: x( Zvoid UART0_IRQHandler(void)
/ g' T0 {# }. U3 ^6 {7 i# P{
2 [2 y7 S, }: v  x        unsigned char data = 0;
; y* B  o1 t9 w) Q! v; H    if (UART_GetITIdentity(UART0) == UART_IT_RX); T  g3 w; B) U8 b
    {
; Q5 G7 J" S/ m                 data = UART_ReceiveData(UART0);& b  ~3 z, l! }6 h9 [
                sy_obj_fifo_push(&obj_usart_buff, data); //将数据存到队列中, r& f: [' e, b
    }
) g' }$ m3 ?! D# N    else if (UART_GetITIdentity(UART0) == UART_IT_TX): M7 C+ r1 X' j  f* r0 K
    {. m! I# ]2 m0 i6 W% J
        UART_ClearTxITPendingBit(UART0);9 ]1 C5 ^  ]( g4 q9 s2 C# ?
    }6 s% n' o; h& P

该用户从未签到

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

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-8-12 12:32 , Processed in 0.109375 second(s), 23 queries , Gzip On.

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

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

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