背景
( D! r5 W! x$ `9 F8 e1、单片机串口接收数据处理,这个代码已经过很多项目验证,没有问题。用这个代码帮了好几个同事解决数据接收久了就异常。3 V" L: ^# h Y6 E; } q) |' [9 v9 ~
2、这个代码做到接收和处理分开。避免不必要的处理逻辑问题。8 @5 v# s2 N% j$ q" N0 k% o! i5 h
3、也可用于网口tcp,udp,spi,iic等方式。1 R# X$ r, L9 [ k8 x
' R; h2 D% D5 G/ s9 }
4 z2 U# c- e, W$ |缺陷 :9 R' d$ a8 N6 G: ]+ B9 P, t; @
1、接收和处理两个缓存区,比较吃内存,不过现在单片机内存大,不是问题。
$ d7 `$ G& ], Q7 c+ l' F! L. A& E2、接收和处理分开,响应没那么及时。现在芯片主频都高,可以忽略。4 m7 U0 \. t& v* }5 E5 y; y
" V7 w7 `" M# n/ h0 V$ v7 J. O2 v& u/ [$ n( j s* v: N0 G
实现
/ q( e Z% s. ]- <font face="微软雅黑" size="3">//缓存区根据实际情况修改
' I5 B% g5 j5 c' ^, j - #define UART_RX_BUFSIZE 16 // receive
' N \" M# _2 |# z" Q, J4 t8 M. z - volatile uint8_t UART_RXBuffer[UART_RX_BUFSIZE]; // receive: i+ L* O! S! V: J4 ]
- volatile uint8_t UART_RXReadIndex = 0, UART_RXWriteIndex = 0; // receive buffer indexes :
b1 _; ~5 R3 o/ w& d3 t% y9 I - volatile uint8_t UART_RXCharCount = 0; // count of received bytes:! L4 x+ I! }/ I8 B/ w# k8 x' S
7 c; p% f/ s! G: z. Q* C- //根据实际情况修改
5 V+ h5 a2 J# N7 V: j - typedef struct _REC_TYPE3 {, z+ I8 E7 F7 t
- { `& D8 J e% x* @' D
- uint8_t Head;
" e6 w$ V+ i. ? q - //uint8_t OptCode;& ?+ T1 n8 _* D0 b0 M8 _
- //uint16_t DataLen;5 }6 U5 {. O% ?7 r
- uint8_t DataBuf[5];
2 f( h' H+ a" Z
; c- y' J) {1 {2 p0 O! i5 {- uint8_t Tail;
@: C* i' R7 i8 D! {: l
0 W) O; t) S7 l& w* J8 L: a- } REC_TYPE;
c' ? g9 F3 V+ |; U, q. x# _ - ) V$ H. ^: S7 X4 d$ Y
- typedef union REC_DATA_TYPE
6 ]! q; A9 g2 z' V - {
1 A9 x( F7 S" z2 E1 a& P - REC_TYPE data_type;( Q. l% I" A1 h: ]6 P! v
-
3 R s4 `1 j* ] - //根据实际情况修改 X3 J" z+ i2 c9 u* F& \
- uint8_t data_arry[16];: u6 q0 i4 k5 Q" |* I# @6 ?3 I
- # a( X. n1 `* m$ L" v1 f
- } REC_DATA;
' `7 X: j# {$ Z7 C
- @& @) R1 c$ q$ G- REC_DATA uart_rec_buffer;//16byte0 ^3 d' d$ `. {2 R y+ v
. T" {) r2 L& M, c- uint8_t uart_rec_count = 0;
% k8 H" W/ r) U t; s+ I9 y: H - uint16_t uart_timeout_count = 0;- H( z/ u1 r& ~) X* C
- ' ~; ?5 t5 ^6 z1 n; R2 h
( C0 u5 I4 C) j8 S( y+ S4 D- //中断接收,根据实际芯片修改
" }/ w4 U9 ]7 k! Y- ~# a/ M - void USART1_IRQHandler(void)! Q9 a/ j+ p* O& z$ l; |8 } p
- {7 S k5 X7 X% \
- if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) s j) C3 U# B6 z- E& p- l
- {: I5 y+ ^+ u7 ]$ h0 k
- USART_ClearITPendingBit(USART1,USART_IT_RXNE); & ?9 t6 z9 v7 X* M9 m
- * {" W, H' `" n- ]
- UART_RXBuffer[UART_RXWriteIndex++] =USART_ReceiveData(USART1);
! U5 ]# Y6 ]4 q9 B! O4 D* I# d0 A0 c - UART_RXWriteIndex &= UART_RX_BUFSIZE - 1;& E, c) |% ~& h! P5 ?9 k$ K$ H9 Y M
- UART_RXCharCount++;0 v, F& S$ c/ r; e
- }6 y- o, f+ W; D/ E
- }
+ T7 F! N! t: F" T- s8 m( ] - //读取缓存数据
1 o- x$ N6 M# N# S - uint8_t UART_Ci_ReadChar ( void )
, ~' v* _* W% x2 `) f) ^" f9 k - {& A8 }9 ?. T9 b4 N
- register uint8_t Byte;( R. H/ e4 J3 d" r* j# D. g9 v8 _; s
- + n" i$ I9 v) _) I$ f; F
- if ( UART_RXCharCount )
( r- h: Z6 Q6 |. ?9 { - {4 W9 c# V9 Q* u3 P
- Byte = UART_RXBuffer[UART_RXReadIndex++];3 s6 |$ W% S% ?
- UART_RXReadIndex &= UART_RX_BUFSIZE - 1;/ X L" [$ A: f9 K6 G* {8 u
-
w0 E$ }) l3 e" S - UART_RXCharCount--;' p" B5 c* g4 V: h# X& [+ \
-
- ], B+ i1 X+ K) n - return Byte ;
5 S1 w/ I) U1 k: U! | - }
7 ~, r2 ]% u9 @- e$ s - return 0;& M% ^$ P% k" z/ P: d6 ~
- }1 ~2 b+ G; u5 d( t3 L1 D
. h6 D* N: \! }8 t- void Uart_process_rec_data(void)9 Q+ k3 l4 V9 f3 z6 F* W; \
- {
1 @2 O4 E' n6 b/ a% J - 8 N; v: j- V4 J4 B7 l$ q" W
- uint16_t m_ui16Data;
) Y+ Z" q3 ]2 L# v - 1 x! r( z$ c/ X
- if ( UART_RXCharCount )* G' f8 C4 q; x: A' R
- {( m6 V8 d2 @6 K8 |8 K( @, [
- //设置超时初值$ I$ F4 s8 n& V
- uart_timeout_count = 50000;
2 N& n H k/ r& K9 ` - uart_rec_buffer.data_arry[uart_rec_count] = UART_Ci_ReadChar();2 A& n v7 ^! K, ^. I
- uart_rec_count++;
! a* Y7 s9 ?& Z/ Y - }
' Q+ D! |1 G6 ?- B5 B# N - //添加超时处理2 k2 o7 r) {6 Q
- if ( uart_timeout_count>0 )
6 w9 D3 o# b6 M1 C' c: i; G1 j - {
% Y2 l$ C7 u9 M# `! t# U" E - uart_timeout_count--;# i5 w) {( b6 G" B: A+ Z
- }
3 ?6 z3 |: a9 K9 q- ~, V - else8 ~' x: _6 s$ V- y$ l9 r. b. O' W
- {* Y/ B" R: l) @- D) A/ R" V
- uart_rec_count = 0;
/ W8 l1 J* K7 G; }/ L - }
2 D/ {% W7 r5 i4 m, d - if ( uart_rec_count > 0 && uart_rec_buffer.data_type.Head == 0xff )
( b# C% h6 N; m( y - {
: k* O: E: H! o. [3 W* h" |7 p# I3 m - //这里添加类型处理
7 T6 e; p3 |6 f5 _ - - `8 i% T$ F l( D, a
- //7是帧长度,根据实际情况修改
" ^ A& e( d1 M/ c0 v8 X - if(uart_rec_count>=7)- D& G' l' F- k+ M
- {
- j0 _' G8 ^: s- S - //记得清01 I, l9 t2 R5 W
- uart_rec_count = 0;
* E2 s% Y5 p; F2 ] - if(uart_rec_buffer.data_type.Tail==0x00)1 a; s1 h. F4 H: v) s9 i2 U- N
- {7 u4 ~1 N- v# b. p/ r: e7 `) J( `5 Z
- //数据处理
! K* n" [0 b% r! s; i0 Y1 \8 z - }
0 q" |2 z5 _" v$ w - 4 f/ ]+ P) P* q0 U
- }8 ?+ x( ~8 s' |7 ]
- }% k" F- [5 ]: T/ T+ Y
- else9 V# E# l9 h) R* w. a
- {
) f! u) {, M; p% ] - uart_rec_count = 0;
% X# [ j# P: P& |3 a, i. z4 }- e+ R - }* U; @5 @$ A4 S( k4 `
- }
0 N9 P% |/ y8 d7 p! P4 _+ o0 v% k - </font>
复制代码 6 O# c! \7 S( @' B
' _7 f6 V0 }" n+ [' s" `4 Z. `
|