一、STM32CubeMX开发
) J( X8 E' F. ^4 H2 Q. o5 h5 F$ V1.1 新建工程
9 `' Q0 |& l( I, z# efile -> new project
D3 ?8 |& P0 P* I. c( ]
$ T" o" T6 A; e& X- U. v* q0 K选择芯片-> stm32 core内核
' ^/ w' u% s/ O9 \) p& G4 G& ] s1 T$ S- h; m/ v" h! a
stm32 series 系列7 v2 F7 h7 r8 U+ v
5 T& ?2 w8 h( Y4 U1 z8 @
stm32 line& H& J9 z1 E5 `7 v8 P
& W* @2 O3 L7 N# e# z1 [; M stm32 package
6 }4 Z+ s' s1 d/ W' g9 b% e' }# P$ K
选择芯片根据自身需求去选择,目前该项目是stm32f0系列 I( w0 B4 R/ i# Y
& E. h: b+ v& B/ ~/ `' `1 h! a1 u/ ^# M stm32 core内核 M0
$ ?6 m! L) ]/ c; b
4 ]+ ~! A) @# q1 g stm32 series 系列 F0
" Y3 d1 D& V# Q2 r' O
: Z# }* }" h; m+ F% ~4 M stm32 line F0X1
0 P7 F) p" ]% d# K1 f. P
/ @) i6 d) H1 S0 D8 _! A x stm32 package TSSOP 20' n, g4 @2 S8 K' r: I! T$ {' ~/ E
, T4 g P: q; p6 p5 O: Q5 U' o4 z* Q0 T 1.2 配置 USART1& E; m+ J$ z' o' b7 ^: b
配置 USART1 的模式为 Asynchronous,即异步串口模式
% g* @3 a- @0 ?: b+ s: v4 U9 F. I' Z5 T# i) b
d( W' r' ^" H2 o6 L6 N8 Y( v9 n8 x2 W- [( U
1.3 配置串口参数
% y: Z7 t0 L4 T6 X* Q- T- L4 c 根据需要设置波特率和数据宽度等参数,在此使用 9600,8,N,1, K( y; {0 A! i' b4 @
8 P$ J$ L0 f4 P% f" C8 Z" N5 q/ k1 V2 X9 Z
+ w- L& M+ W5 C c' h$ B
1.4 设置DMA
$ `/ I. }5 E5 [& A( X; i; B5 i/ L) a6 E+ _* M
1 ^4 v/ d4 d% | h( I9 c: @
/ J: |+ l3 s3 X0 d& A 1.5 添加串口中断
. g Y i2 r5 u
4 Y& Q" p! W' q4 M. l7 h& ^- G7 j: o. B2 p+ P* Q$ g9 {+ W
1 [9 M2 x7 ]/ A* |) f X j A- O/ c
1.6 生成源代码。
/ R: j& A( j1 q i: n在界面中输入工程名,保存路径,工程 IDE 类型,点 GENERATE CODE 即可。
- v9 t. J$ w$ Y2 s( c
, t( U6 c$ {9 Y& K/ y+ c. V2 C6 c1 F' U* ^% T a' W- n0 |
& |9 ]1 F+ Z$ R4 L2 a; Y x0 V9 _生成代码完成后可选择打开工程。 $ O5 }: S2 F; e* c h$ C
. {/ T1 j9 B5 t' I: `' B/ [ ^
+ N$ P/ R' ~( l+ }" r! l* o! P
5 ~, } A+ ]9 N3 j: Q二、代码部分7 r1 v- g( V' D# ^( U+ Y
2.1 接收中断处理
$ L0 a, ^/ F, R( }& H x2.1.1 接收固定长度:(舍弃)
/ m! b8 ?/ x& {' A0 L只有接收缓存到固定长度才会触发中断/ T* y3 x5 Q; }/ l: V A
串口接收回调函数. Z( f* c$ T1 z9 z; R% E0 M
. B( w) [. g, C' K
- uint8_t aRxBuffer[RXBUFFERSIZE];
! b) o* I3 n: w& t I7 _. J - /* Size of Reception buffer */
2 n6 n i8 i6 C4 E- p - #define RXBUFFERSIZE 10" K. ?+ j F. ]% _4 i
! O/ N6 r2 c+ v1 b. X/ H* a3 k- # N, m2 m& S# t! \, `( n( r
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
4 R5 E% ~7 u8 T! F5 Q - {- t6 ~8 R3 e" I7 O, W
- /* Set transmission flag: trasfer complete*/
- M4 N; s" t, C8 K( T - UartrxReady = SET;9 K. n: V3 s* h! |% e9 ]+ M
- HAL_UART_Transmit(&huart1, aRxBuffer, 10, 0x200);
4 M. e1 K3 K6 J1 q' w0 e" n# k - HAL_UART_Receive_DMA(&huart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);
/ |3 X, M# d$ T# G* Y - HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer,1);
, s( Y& K0 ]% o$ Z7 B4 y
0 E% ^7 `1 o: I( Z% K- |) J- }
# g7 A8 K- f, M
% G) d. ?$ ]4 }6 l! ?3 M- A- void USART1_IRQHandler(void); ]6 j5 _& Z* R5 Y3 k2 V+ l/ Q, D5 }
- {+ P( Y6 q) ^8 A* M! b9 w
- HAL_UART_IRQHandler(&huart1);; C' W) F1 x' c+ q
- }
0 ]- m8 t, ]' e
6 k8 A4 D& T9 _/ Q+ V5 A1 s1 G- T3 D. ]$ ~4 h) M: Q
- static void MX_USART1_UART_Init(void)$ u/ E p% p% x- ^: O- P
- {
b, V- M) _* [1 O
( _7 M3 v* ]2 @" V/ f+ r- huart1.Instance = USART1;
z, Y& j' p0 h c2 T - huart1.Init.BaudRate = 9600;
5 M9 ^" G# F( f c- d3 V - huart1.Init.WordLength = UART_WORDLENGTH_8B;
* x" R. u6 ^/ ^& G9 w% d - huart1.Init.StopBits = UART_STOPBITS_1;3 P5 ]; o) y+ U3 }. C8 k
- huart1.Init.Parity = UART_PARITY_NONE;
9 ^9 W, _) R$ u" l D, u& C% s - huart1.Init.Mode = UART_MODE_TX_RX;
9 Q5 J2 K7 c* J5 K - huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
" e+ f# t6 H& {: D - huart1.Init.OverSampling = UART_OVERSAMPLING_16;0 u y* S6 \# F* D b8 n7 j
- huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;2 Q& d8 {2 p8 y# t6 |
- huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;: W# Q& M$ A0 J- m* H# u
- if(HAL_UART_DeInit(&huart1) != HAL_OK)- Q! F9 P. ?9 Y
- { i4 m# [/ r+ t& B8 _9 w7 ?9 D
- Error_Handler();
$ p: D' ?( Q+ g W3 m - } : u; e! u2 y/ v a. L3 e
- & D( d# M0 M% h
- if (HAL_UART_Init(&huart1) != HAL_OK)
* F+ G+ k9 W' M$ Q& i - {, T) Y( j& [, l$ A3 w
- Error_Handler();$ k& M0 |6 S. B6 A5 c& V o( O
- }* Z: h8 r8 [( v9 g/ q" G5 Z- [
-
: V5 o8 [, \5 n$ t+ d1 }0 ^ - UartrxReady=RESET;
' p4 G; A3 Z) q8 M3 ] K2 } - /* USER CODE BEGIN USART1_Init 2 */, e" f2 _- Z. P7 @' r' j
- if(HAL_UART_Receive_DMA(&huart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK): J/ j* h( v' b( ^6 J% \8 A
- {
5 ^* l3 S3 z# x6 A8 \) x( S3 F - Error_Handler();
/ ?- v, b* N/ Z) z - }
; @7 c' }# E C8 _) Y( V -
$ q: b O" K6 v3 W% d$ P5 [9 _0 n - /* USER CODE END USART1_Init 2 */, j7 o R( d0 x1 b
- }
复制代码 ; `: [& d9 { |6 m% G, ?5 B
从串口调试助手可以看只有接收的长度 RXBUFFERSIZE为10时,才触发接收回调函数。
) x, b! u' ~/ f
, y1 {8 D3 |* P F
/ j! f' j2 P4 r7 T; \7 V
5 M9 p Z0 P# o3 N( U2.1.2 编写空闲中断函数接收不定长
# T( J( z( N; W# JUSART1初始化:* a' ?; {1 [( o- K4 m9 ]0 I3 W
- static void MX_USART1_UART_Init(void)" ^( _5 E( _( ?% J9 b, l2 R3 h' l
- {8 B( Y) B2 |. C" n! L
- huart1.Instance = USART1;- [) P) C$ r' E' l
- huart1.Init.BaudRate = 9600;, J. a- [ N& [# I2 ?
- huart1.Init.WordLength = UART_WORDLENGTH_8B;( `* r: }' E! T+ y2 S8 V
- huart1.Init.StopBits = UART_STOPBITS_1;6 z- d% i$ a/ A4 N! W
- huart1.Init.Parity = UART_PARITY_NONE;0 n/ h0 _8 l; }* b+ {2 I' |
- huart1.Init.Mode = UART_MODE_TX_RX;. n- O% }" @; J: u# e, }
- huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
Y7 @& s$ p. N2 A/ `: n0 L- f7 Q, a* ~- j - huart1.Init.OverSampling = UART_OVERSAMPLING_16;
% \! ]( X, V( _4 p2 j9 S7 K a% } - huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
' Y2 M7 o- N, l) Q% ^, W# Z - huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;# a+ a/ q# I& k$ R) b" L" h7 n% ^' S
- if(HAL_UART_DeInit(&huart1) != HAL_OK)
7 S2 [. B" u, O: J' l/ K - {$ k! R( a- F8 z0 a
- Error_Handler();
3 ?7 K. C" ?( g% ?+ T - } ! Y! o9 B* S7 O+ A
-
) V2 m2 {# u" v - if (HAL_UART_Init(&huart1) != HAL_OK)- N: b5 R8 H/ _, w% d2 U* b
- {
0 f6 f k* J+ \5 a- u4 F1 B" | - Error_Handler();! P$ |, p; n& b6 _2 g
- }
* W) G2 K4 ^- } - + Z, I; P; t/ P$ }( x' F! r
- __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); 5 F: a5 Q. @& C& y
- /* USER CODE BEGIN USART1_Init 2 */. r: ?) c! _# d o6 S+ O+ [' v8 w
- if(HAL_UART_Receive_DMA(&huart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)1 t* y7 P' |* E$ h
- {
0 ?; d4 D5 ]/ | K* P, u" E- I( G! l - Error_Handler();4 f% T1 V; u B, ?' d5 g+ m) h
- }( s5 E4 K X, _0 B8 d/ A% @
- : R3 A1 I; ~6 _+ h$ w
- }
复制代码
+ a; Q* z% ]3 A1 q空闲中断函数: + f6 i" v. ], a. {
- #define TXBUFFERSIZE 30; O; D: k) p3 v& r. a
- /* Size of Reception buffer */6 Z/ n9 l$ @0 a/ ]
- #define RXBUFFERSIZE 30
! ~/ O) A6 b1 C+ C% z s' j z4 I
6 ]# T' @' B, t& V1 J5 Y; c- void USAR_UART_IDLECallback(UART_HandleTypeDef *huart)7 ~1 s9 h* H" v% X6 C3 ]0 X# W
- {& C% a2 T U1 ~7 E# a
- HAL_UART_DMAStop(&huart1);
. E2 p4 | \, K: K3 n
; g# p7 |5 ~! Q% J* p. ~- uint8_t data_length = RXBUFFERSIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
* v6 Q7 j* h# U2 E. J4 Y; X! I - / ~' ]$ E. B7 O0 q; x2 g0 L
- ' P9 U. V/ @# i+ Z
- HAL_UART_Transmit(&huart1,aRxBuffer,data_length,0x200);, b# d& R2 |8 c6 Y" M" h! F
$ J3 I2 ~9 C/ \0 J, x) i- memset(aRxBuffer,0x00,data_length);
4 v" k- y! U& ?$ w j Z) Q - data_length = 0;
9 B$ k" E T9 g# E7 t$ T - HAL_UART_Receive_DMA(&huart1, (uint8_t*)aRxBuffer, RXBUFFERSIZE);
: @; u; h4 d* _1 i, _2 e ~ - }3 a# x2 C" c1 q8 [
; Q$ V, U( w& w" @! I- void USER_UART_IRQHandler(UART_HandleTypeDef *huart)1 B* l) o/ Z# D8 C9 O6 F0 W# @; j8 J( m
- {( O0 W( e! ~5 b. b3 r
- if(USART1 == huart1.Instance)
- f" t3 v3 f, _2 X5 s3 f* c - {
7 f3 e5 G K, W' O. _! r - if(RESET != __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))
; J; p. D' Y; i - {
& B, s4 T) n) z" O: J, T - __HAL_UART_CLEAR_IDLEFLAG(&huart1);4 o" i g3 G6 F! K C
- USAR_UART_IDLECallback(huart);
! w: y: N- {3 A* W$ R0 A - }! M7 Y" x$ h& ~4 }: `
- }
# z8 w# C9 X; ? V1 T& J7 ] - }) ~( {) u! X1 Q, N: |
/ L) }7 R. @; k* a( x6 [) K5 z" c- /**9 o! n, y6 i8 d( Z% m+ C% `
- * @brief This function handles USART1 global interrupt / USART1 wake-up interrupt through EXTI line 25.
9 X, n3 Z- a' D- h$ ^, h: M2 y0 K" H - */' ]3 n L5 G, ~+ f
- void USART1_IRQHandler(void)
5 a7 {, T1 J) @* V, r - {4 l' R% j# @% d5 u( y5 y
- HAL_UART_IRQHandler(&huart1);5 f: h$ o; `+ }9 d4 }
- USER_UART_IRQHandler(&huart1);
7 c1 b; r' i9 X) e/ U - }
复制代码 ; ]0 H$ Y6 w7 f( ~' X9 `
可实现不定长的接收! ) A1 @" J3 h* i' l
T6 o1 k% X, W0 e* v1 a6 E% y0 _; d4 J, N6 }& J1 k6 M
) d4 }1 b; E) R9 q" C2 N
注意:- f3 I4 T) |4 m& ^( t8 |
在中断中,尽量处理简单,不要做过多的处理,如发射,可以在函数外执行。8 T: R$ ~! k$ M" h7 W! N% M
7 k+ d4 F. T Y- K" A' }; R
三、使用ringbuffer实现任意数据类型的FIFO处理接收数据/ A0 @8 s1 W2 p" p# `* z# ~' | Y
使用原因:
/ [0 F4 k6 q* `
7 v5 h" ~ E1 u/ I1 `1 R8 ~ 虽然将数据保存在DMA接收缓存中,但在处理接收数据时,可能存在接收新的数据在调用数据完覆盖了接收缓存,导致调用数据时候会出现与原计划的处理不同的问题。
2 F5 }* v' P) R, z2 b# ?; D" W. A9 w, K
因此,使用ringbuffer将DMA接收缓存,以防数据的被覆盖
9 A4 a# W) B4 C; `4 |* _/ `* B/ ]; q2 |+ r
① fifo头文件:; C4 V- |- Z4 Z5 R; K, |8 D
- #ifndef __FIFO_H_/ s) M% P: [9 ]8 z5 E% B1 J' f
- #define __FIFO_H_
! P3 C. n7 E+ Z" E
/ x) j2 S0 g+ [( E( m9 x8 X- #pragma pack(4)
7 E% ]1 u6 n" U" i" K( v4 t - typedef struct FIFO_Type_STRU
) {+ e8 y0 f; \" t& X - {
# w9 v6 x, P S+ c5 T( j - unsigned int Depth; // Fifo深度$ X8 \4 T' g& x3 ^3 D
- volatile unsigned int Head; // Head为起始元素
4 L+ w( A2 E3 q" N+ f - volatile unsigned int Tail; // Tail-1为最后一个元素6 A7 v5 f6 d$ [. P
- volatile unsigned int Counter; // 元素个数3 W1 S% P* ^* ]5 d
- unsigned int ElementBytes; // 每个元素的字节数element6 m; G( J; f& M4 {; z
- void *Buff; // 缓存区. z. O: s) f) f
- }FIFO_Type;
* V5 z, K) I1 n* ~- h8 Q - #pragma pack()
, h/ z* E( I: M - 7 D" a4 c* `, D1 p) H$ c9 \
- /********************************************************************//**
9 a" r- D: W1 a1 e- m - * @brief FIFO初始化9 |( S) V$ V0 S# a9 l# m. w# t+ u
- * @param[in] pFIFO: FIFO指针% z F( `) x+ y9 u/ ]/ I* K
- * @param[in] pBuff: FIFO中缓存0 H" H/ q! k7 u
- * @param[in] elementBytes:FIFO每个元素的字节数3 D- z# V) d1 T- ], `. n
- * @param[in] depth: FIFO深度+ E% D) ?7 U; E) w9 G3 a
- * @return None
/ n" j) Z' Q) [5 b. x" N - *********************************************************************/# J( K$ z: p% j% } y
- void FIFO_Init(FIFO_Type *pFIFO, void *pBuff, unsigned int elementBytes, unsigned int depth);
% R0 U2 A" O/ Q; a0 L Q - 8 D- V6 x/ d& V; p- A
- /********************************************************************//**! D- \; R! U9 p2 `
- * @brief 向FIFO添加一个元素
% L9 h9 [. W1 X( Y5 f1 T9 c - * @param[in] pFIFO: FIFO指针( A, l( z) b; |- j. e
- * @param[in] pValue: 要添加的元素! V$ z) a: q# y; l+ V( r
- * @return 1-TRUE or 0-FALSE: N5 A) O6 h% V, O) X
- *********************************************************************/' e( ] l* k- O" @2 J+ s: \
- unsigned char FIFO_AddOne(FIFO_Type *pFIFO, void *pValue);1 v+ x' _% y2 ~* L
) C, D3 C* {* J; |) `8 d( Q- /********************************************************************//**0 C8 D8 J! O7 p* b
- * @brief 向FIFO添加多个元素
7 I2 d3 b% x- b, h# h. Y - * @param[in] pFIFO: FIFO指针
1 ?9 }' y; S. R2 i2 w2 _ - * @param[in] pValues: 要添加的元素指针
R6 z3 E; ?! m- V1 E2 N' W7 { - * @param[in] bytesToAdd: 要添加元素的长度
6 y( n7 ]3 N0 d7 Q: S: ~- \ - * @return 实际添加的元素个数! j, V6 ], r$ N8 h9 H
- *********************************************************************// @: l7 |% V, {
- unsigned int FIFO_Add(FIFO_Type *pFIFO, void *pValues, unsigned int bytesToAdd);4 b5 D; A! l' H" J/ W) ^, D/ O
- & B2 W5 m0 u1 B+ c3 b- C
- /********************************************************************//**
/ N2 f% |! x0 B) a - * @brief 从FIFO读取一个元素
' I5 Y% s/ m+ _: U9 F - * @param[in] pFIFO: FIFO指针
A/ h$ X! |. b- c$ u7 {0 u$ o - * @param[in] pValue: 存放要读取的元素指针7 c& [; {- c _6 A& W
- * @return 1-TRUE or 0-FALSE
5 Q% ^" S% ~0 @& Y% @& V$ a - *********************************************************************/
, b" N3 o; B1 z$ W, W0 X. a; J - unsigned char FIFO_GetOne(FIFO_Type *pFIFO, void *pValue);7 s+ [4 R4 t2 P& o5 |' }
- 1 `' z/ W5 V2 T Y @
- /********************************************************************//**+ [+ M& `3 S1 Q. D+ Y. u
- * @brief 从FIFO读取多个元素8 l! a! p/ t$ B
- * @param[in] pFIFO: FIFO指针
7 Z! v/ L7 E% T+ ^+ D - * @param[out] pValues: 存放要读取的元素指针% _, I4 |# `+ ]9 _
- * @param[in] bytesToRead: 要读取的元素长度
$ o9 q1 O* A a# X9 S4 U5 O - * @return 实际读取的元素个数
8 q; {% V* n$ O - *********************************************************************/
0 ?! p* P% O4 j - unsigned int FIFO_Get(FIFO_Type *pFIFO, void *pValues, unsigned int bytesToRead);1 ?# M# g& \5 C$ ]/ U! `! i' `3 N
1 n1 g) V8 ^! j$ j4 U) n* U- & k- [' e: h3 W6 t$ `/ p% R3 \4 G+ F" O
- /********************************************************************//**
* X) G6 n$ ]# z# M" L1 R' z) Y! U - * @brief 清空FIFO* _3 @ p# Y. _ e$ r' H, [
- * @param[in] pFIFO: FIFO指针
7 e/ e2 o' g& O o6 f- D - * @return None) _ O1 W5 P* s$ V
- *********************************************************************/* G( K Q; n6 v, G9 l/ _6 Y7 v
- void FIFO_Clear(FIFO_Type *pFIFO);
) Q+ q* `: t y; c- u9 K
' a% _5 s) \! ]# U8 g- . R& \& Y. n E/ c/ W0 J9 O, i
- unsigned char FIFO_IsEmpty(FIFO_Type *pFIFO);
# t; z! A6 w# k4 N5 V/ P - 2 i5 \" ]- `) m# f% \
- #endif
复制代码 * t. p& }; K8 M# R. n, e1 ^5 Y
② fifo.c程序主体
' n: {/ Y: i, t9 j
2 p E, ?8 n# u; c$ b, B- #include <string.h>6 n% W, k4 T5 D1 @! D' c d: Z
- #include "fifo.h"
; t3 I2 K$ C# z* T- A( v I' F; N - * m' L7 k% E1 J; o5 `; {
4 c+ @1 L/ z$ h" ?, w- /********************************************************************//** Q, N6 a/ z- t8 ?
- * @brief FIFO初始化$ M+ f8 I2 m4 D! M: G+ Y6 p; U s
- * @param[in] pFIFO: FIFO指针
6 z/ ~# d# D3 D, u - * @param[in] pBuff: FIFO中缓存, _# a3 p7 d* j
- * @param[in] elementBytes:FIFO每个元素的字节数& l. g$ H) w( T8 P/ l: ~6 d7 z
- * @param[in] depth: FIFO深度
1 `: d" }3 r! g/ O1 n - * @return None
. ?4 v4 K# r& S2 d6 N5 _6 A' L - *********************************************************************/$ [7 p3 q7 _3 F' {0 C
- void FIFO_Init(FIFO_Type *pFIFO, void *pBuff, unsigned int elementBytes, unsigned int depth)7 e$ {5 [+ C( a7 i; p8 @* j- l% n
- {
: X: A5 ]4 z4 s) B. s - pFIFO->Buff = pBuff;8 J4 {& L0 \4 F. |1 A4 L
- pFIFO->ElementBytes = elementBytes;
: M: j% Q9 Z8 Q- v5 [ - pFIFO->Depth = depth;
@; J9 d- v( R7 l' i) n+ ~ - pFIFO->Head = 0;
9 }) @9 y4 o8 b. w9 w$ A$ P - pFIFO->Tail = 0;$ q- Q' P; O& |4 x% D8 |
- pFIFO->Counter = 0;& x+ y0 `' D3 T% I3 Y
- }
0 K* _1 E2 T! M% z. a$ n
" y3 u8 A! j& Y9 f& a- /********************************************************************//**0 }$ O2 _2 b" D- w6 t4 X
- * @brief 判断FIFO是否为空+ G& Q, y* p* Q; V1 N5 x: H
- * @param[in] pFIFO: FIFO指针2 Z7 G1 M( t4 M8 `5 v9 {9 O, e: b+ ?
- * @return 1-TRUE or 0-FALSE5 A; q" i; J) q% Z( U [+ I3 G
- *********************************************************************/
4 G" N/ m8 T; p' o% @6 k1 Q6 E - unsigned char FIFO_IsEmpty(FIFO_Type *pFIFO)3 Q' w' w8 }3 ~
- {
8 p7 l2 _( K( x+ i. b8 N: Z9 z - return (pFIFO->Counter == 0);, C3 l1 ?$ a( ]: i4 Q
- }
: y& |3 Z6 z' s! H# w9 d4 N - " ?3 O) n" ^$ y3 E: p3 t
- /********************************************************************//**+ N) z: q1 n. F. M% }4 I
- * @brief 判断FIFO是否已满/ t6 g/ e2 y3 _) u0 U
- * @param[in] pFIFO: FIFO指针
1 \; ^* }& B( ~* _* r - * @return TRUE or FALSE
" s) d9 L& U" E' I" } - *********************************************************************/
. S$ p+ A$ o) |& D \* l - unsigned char FIFO_IsFull(FIFO_Type *pFIFO)2 `" s6 _6 P1 N5 G% I
- {
- G3 t2 x4 E7 [& I# j4 K: M& e - return (pFIFO->Counter == pFIFO->Depth);
9 s+ f9 g3 S0 C! ?9 Q2 M - }
! M8 l+ H% M8 E7 p+ D" |: R4 @
! W7 i7 M( [2 e- C3 g- /********************************************************************//**
7 D( r# J+ K' p, q" K' R - * @brief 向FIFO添加一个元素& L9 C# r( V1 b) p
- * @param[in] pFIFO: FIFO指针/ B) R- D5 X+ H9 z& _
- * @param[in] pValue: 要添加的元素& w2 p0 w9 z( X" h8 v
- * @return 1-TRUE or 0-FALSE! H+ X( f' z; t6 [( Q5 c! B$ t: V
- *********************************************************************/
& D. R$ ?8 |( K9 I - unsigned char FIFO_AddOne(FIFO_Type *pFIFO, void *pValue)
5 C9 z! d! k: o4 }1 c4 B - {
- X) }0 V& `- J3 b! v3 n - unsigned char *p;: f1 f1 }+ u- q5 S7 F
/ y. t* Z4 p% A; C4 e- if (FIFO_IsFull(pFIFO))+ ?: v$ j2 D9 h7 d8 a$ p) f
- {
* `4 f1 g2 \& ]" m& [& E9 a# H( x8 ]# h - return 0;
5 J/ }; s$ I: w ?2 R% k+ z - }' A3 d" d+ k- w0 }7 o3 N& D
% u# |; x; m3 `- p = (unsigned char *)pFIFO->Buff;1 s4 l( q3 L! E1 n- C9 _9 ?! @
- memcpy(p + pFIFO->Tail * pFIFO->ElementBytes, (unsigned char *)pValue, pFIFO->ElementBytes);7 [, ^! v1 K c' {$ U( c# `
- 2 Z1 U, J/ v1 S; B# o6 S
- pFIFO->Tail ++;
7 S0 W$ U I0 @% ]5 ~ q - if (pFIFO->Tail >= pFIFO->Depth)
3 G: _6 R$ F# S9 L2 s: E- I+ v. ~ - {; n/ {9 H9 {5 H
- pFIFO->Tail = 0;
& H4 D+ F! p+ z. ]7 W5 J4 } - }
6 @! F7 _' y; E: D- o% l4 {- i - pFIFO->Counter ++;
' F% K- E7 r- T4 J - return 1;# Y7 V- D9 x% T* O- ]
- }
( l" \- \5 v5 Q7 o0 S- u - & | ~ L: }+ M/ ]- v0 D4 K
- /********************************************************************//**. S% X: m" Q- J! V, E
- * @brief 向FIFO添加多个元素! F" X6 q" ]8 I7 T# S7 X
- * @param[in] pFIFO: FIFO指针
/ z3 z. ?4 I# }8 W& y) [ - * @param[in] pValues: 要添加的元素指针
) [( _: x9 e) p& x2 f" N - * @param[in] bytesToAdd: 要添加元素的长度* U6 I+ G( g0 R' R3 E* F3 m
- * @return 实际添加的元素个数
* k: r+ s" c7 z) E3 H3 y - *********************************************************************/3 u# c% h8 C5 h( ^7 P8 t% y$ L
- unsigned int FIFO_Add(FIFO_Type *pFIFO, void *pValues, unsigned int bytesToAdd)
$ h- `, h8 |/ t: r& W, V/ [& b - {
; I' m9 ~9 d0 `; R2 f9 s" q - unsigned char *p;
* f z M# Y3 J. _; M - unsigned int cnt = 0;$ @7 y1 Y4 |7 {* u/ Y. r
- / M4 b! _2 o+ |5 P& K
- p = (unsigned char *)pValues;6 B2 a2 W5 o6 M
- while(bytesToAdd --)
4 k0 E/ c- h$ E$ p% r! L V% r: c- Q5 v - {7 ?. W* q) m; ]8 l
- if (FIFO_AddOne(pFIFO, p))' n" }& v2 w) a; b7 x# ~
- {2 y" i$ C9 \/ |" j, B- h8 X
- p += pFIFO->ElementBytes;% V, v! f* v/ m
- cnt++;7 U6 L3 a4 ~3 m2 \: ~+ m! _3 G' `
- }- G6 |( j B7 j; `0 f. y9 @) U
- else) B9 R( u' j% C
- {
$ J! l7 T1 s+ k: n - break;6 U: Y! F% ^, K, L
- }7 `$ W# o2 n8 [( r
- }! W2 |9 Y! K. Q- }0 P+ F
& h4 V- N/ F0 h& R0 J7 L( p- return cnt;
& m; \" P+ p, |( ?% D: i - }
* @9 D: `9 Z n( O, D4 @ - & _* ?: G4 B2 C8 [4 z$ Q
- /********************************************************************//**
2 E" ?- H3 Z* g" m - * @brief 从FIFO读取一个元素$ b- |, Z& X9 d# ~, S0 _
- * @param[in] pFIFO: FIFO指针8 ]6 V+ ~, ?( @* u8 z) @! c( I
- * @param[in] pValue: 存放要读取的元素指针4 Z& F2 E+ g+ M( T* h
- * @return 1-TRUE or 0-FALSE
! ]1 n0 ?4 l# F. ~# |) g; t# {$ L - *********************************************************************/
3 w" X- c( s R, c - unsigned char FIFO_GetOne(FIFO_Type *pFIFO, void *pValue)( X$ @9 } F+ J7 i8 z
- {
8 T. W: L" q+ h3 E - unsigned char *p;
3 ?5 {$ b1 Y2 Q+ B - if (FIFO_IsEmpty(pFIFO))
' M2 O3 e* W# C& i, N9 ]8 N% } - {
9 y3 M& V4 g1 ] - return 0; g/ J) o3 X) b; i
- }$ g7 Q H4 h: I8 ]5 P8 A; _
- l% U" I- y5 [* y% H- p = (unsigned char *)pFIFO->Buff;; S! Q* m4 ?- F/ d. C' g% p6 R
- memcpy(pValue, p + pFIFO->Head * pFIFO->ElementBytes, pFIFO->ElementBytes);7 X9 ~. o; D* @" b [- e
& s9 X$ {8 v' _( K7 O6 y j2 Q- pFIFO->Head ++;
# N- Z2 W, G L - if (pFIFO->Head >= pFIFO->Depth)
5 a r5 z3 j/ Y0 J" P - {! Z. a: @. l2 _, \
- pFIFO->Head = 0;
, c3 j p- ^" Y) B9 C4 J - }0 x. h! |$ \' p+ G; c
- pFIFO->Counter --;
3 N k& y" |* k6 H6 b; ]4 o* H/ X
; {% y7 v* r1 B6 Q+ n- return 1;
! @ Y" w8 ]4 n0 R/ o2 T2 W& ^ - }
F8 @6 i) L4 Z) f/ i8 z6 L
; R( ^; l3 P! N1 ?7 k" O- /********************************************************************//**
* l( |7 H( ]" C9 y6 e - * @brief 从FIFO读取多个元素% L. @0 m% E1 O$ F4 t
- * @param[in] pFIFO: FIFO指针
2 C0 O3 p, p B: R. a - * @param[out] pValues: 存放要读取的元素指针% C% |0 t' w' Q. ~8 p
- * @param[in] bytesToRead: 要读取的元素长度5 _5 Q' o$ A, O
- * @return 实际读取的元素个数2 E; k) T: q: Q; i) T
- *********************************************************************/
7 t" e; S4 o7 @! @ - unsigned int FIFO_Get(FIFO_Type *pFIFO, void *pValues, unsigned int bytesToRead)* y0 U/ \. j% v3 e" i
- {
# m& f4 d! ~6 b' Z$ _0 ] - unsigned int cnt = 0;! L: C7 {4 Z- n* t, i9 }
- unsigned char *p;6 P( @4 h- F2 H- Q! d7 ]5 `5 G
3 i8 i5 U6 q! D" o- p = pValues;; L& ]) R' h! L
- while(bytesToRead--)
: Y8 c: s# k% C* f - {6 Q: K6 P+ W/ ^3 y* o
- if (FIFO_GetOne(pFIFO, p))% p7 F3 V2 \& ]6 b- O
- {
, S4 t6 |4 J u, C/ q6 _ - p += pFIFO->ElementBytes;
" H* M/ h' j( o m6 j/ B - cnt++;* I2 x3 A! u; l0 |# z; b
- }
* e, @9 l6 n7 ^/ u# J3 A' }! ? - else
3 m$ g) A' c% I8 N! T8 V - {
" B( o [$ }+ d$ N( a - break;
; m+ R5 H A& {1 n& i# f - }5 F- p" e/ A H2 c# \6 I
- }
; Z2 ~2 a7 `" |9 l7 \9 Z7 { - 5 y- C5 g( G9 w1 O4 Z' j
- return cnt;
% ]- z& |2 C3 ^ - }' M( M3 ~2 _) h6 l" J/ Z
- $ j' f$ X" f, R. ~0 A, n
- /********************************************************************//**
- x% i8 |0 N0 I2 D - * @brief 清空FIFO+ t4 N* _/ Z% O2 D
- * @param[in] pFIFO: FIFO指针8 o2 d0 }8 Y5 |; M ^
- * @return None
5 D2 P5 E7 F$ N- Y4 o - *********************************************************************/# H8 [; M6 e7 Q/ K& o* `* u
- void FIFO_Clear(FIFO_Type *pFIFO)
9 j5 n( S- k3 y) G$ \ - {
* H6 F+ I7 |, k4 ?3 c1 c2 ~ - pFIFO->Counter = 0;
- U/ v& g1 D( P \. E% G - pFIFO->Head = 0;
0 Z& y* ]% b, m2 O - pFIFO->Tail = 0;
' ^6 x. Z, ?) k! `2 m2 f! {) L - }
复制代码 6 f4 H+ J7 |+ K
③ 串口初始化2 B+ ^8 z/ P0 S. g, P) h
- static void MX_USART1_UART_Init(void)
) C0 M! I/ V# p3 o0 f5 A2 q+ f, K! D. d - {
9 O7 `$ J* ` v$ K/ p) r" v - huart1.Instance = USART1;2 F( E6 l4 G( V" q$ M s( E) B
- huart1.Init.BaudRate = 9600;
! s/ x* x/ { m, R V, u% i" }* m+ u* x - huart1.Init.WordLength = UART_WORDLENGTH_8B;# H) S c7 B1 u- V( `/ y: _
- huart1.Init.StopBits = UART_STOPBITS_1;# h3 e5 Q1 O7 @
- huart1.Init.Parity = UART_PARITY_NONE;
' U6 ~. k& U2 I# X$ z0 q - huart1.Init.Mode = UART_MODE_TX_RX;
+ ~$ m1 h% s5 T N$ d0 E* d( \8 ? - huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
3 T& N% f( f$ y8 g) q' ~$ Q" C - huart1.Init.OverSampling = UART_OVERSAMPLING_16;' [! E) H! e( C! }5 Q
- huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
3 T& n2 D4 e; Y+ [: K - huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
$ Y5 B) \! ^( a( R5 a, t6 p, S; ] - if(HAL_UART_DeInit(&huart1) != HAL_OK)
P' X7 a* C! `9 ^7 Y - {8 {5 s( M& P8 m+ K
- Error_Handler();* v4 z4 S& W& g Y! Q& T- _
- }
# ~+ d6 _3 O% |, R" j - $ L b/ b( q( Q9 l
- if (HAL_UART_Init(&huart1) != HAL_OK)
9 ^$ F* j( _7 R+ n) u - {* s- t4 m- |" z
- Error_Handler();' n# S# H8 ^: m' H2 r( ^! a7 H
- } t# l/ ^" A, T
- 8 x) X* q" u' v6 c/ v3 D
- __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); - s/ _& S. a$ R, Z. Y7 t1 u0 x
- /* USER CODE BEGIN USART1_Init 2 */
- k; p/ Z, V. Q1 a - if(HAL_UART_Receive_DMA(&huart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)" Q3 s& O+ E3 B* J: D; E5 S& E# f
- {
- J" b: n: k5 S- F - Error_Handler();
1 _# c4 i. @$ r - }
4 n0 V' C; k/ k. _6 g3 W) I - ; T! X9 g' Z# h+ ^% }
- }
复制代码 v0 i8 w) l$ y! p/ V) e* L
④ 接收空闲中断4 t+ J7 Z6 K/ }0 {$ {) h/ [
- void USAR_UART_IDLECallback(UART_HandleTypeDef *huart)& |8 z6 |# p1 c6 V, l
- {8 ^: ]5 p$ |% v
- HAL_UART_DMAStop(&huart1);. P' g' X! t: o7 O( ~$ G
- & i4 f7 {% `" E! x. ?( o A1 e) ]/ |
- uint8_t data_length = RXBUFFERSIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
* a% L1 F# @0 J3 e) Q7 H - R! o5 D k, O+ Q2 T% B8 N
- FIFO_Add(pfifo, aRxBuffer, data_length);
7 q9 x, W: l' M' z% A. d - data_length = 0;
$ L9 E* `; o8 S- p8 f - HAL_UART_Receive_DMA(&huart1, (uint8_t*)aRxBuffer, RXBUFFERSIZE);" Y, _4 t- R$ L( d* B" I3 ]
- }
8 h8 s6 b Z9 p+ r - 1 ^5 ^0 {9 x# n, d4 v- U. \% t1 }% J
- void USER_UART_IRQHandler(UART_HandleTypeDef *huart)
9 o7 x1 n' j# V8 B - {- j; z( O1 ?! ]
- if(USART1 == huart1.Instance)
+ i: L2 P6 r+ \" g" L% s. Y% |" ? - {
: f$ U" Y5 S2 q - if(RESET != __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)): X, f2 J3 h2 p6 }2 L
- {
& H/ {) z6 k$ J E! q - __HAL_UART_CLEAR_IDLEFLAG(&huart1);
; u2 E% i0 h$ m8 m" P - USAR_UART_IDLECallback(huart);0 {: I/ B7 y) G0 J) j* y5 Q5 x
- }
7 e0 k4 i( i. I0 k1 t% Q4 V - }
( I- _4 `# n: u - }, H5 B/ d- P0 w
- 1 \ R0 {: O1 c( ^9 m3 |6 ~5 X% J6 b
- /**
1 Q) d5 a9 @) o - * @brief This function handles USART1 global interrupt / USART1 wake-up interrupt through EXTI line 25.
# A9 [1 K9 [/ k. n! J9 p# x - */( t- C v' G% c: D( h/ X g
- void USART1_IRQHandler(void)
+ x- k1 G6 T9 F6 M0 E - {
: x* f) c' A1 @' W8 B - HAL_UART_IRQHandler(&huart1);
1 u8 P- U7 A" E - USER_UART_IRQHandler(&huart1);
& z) x% u* n* H5 p: ? - }
复制代码
3 k d, F7 m% ]* T5 v⑤ 主函数调用:. M6 A+ G1 ^& z+ t) Q; B
- #define TXBUFFERSIZE 302 V4 o% Y: ]4 X4 X% O8 T ?7 {+ Z
- /* Size of Reception buffer */9 r1 b6 ], u! K" H
- #define RXBUFFERSIZE TXBUFFERSIZE
, Y) I0 e( f0 \' r - #define RXFIFOBUFFERSIZE TXBUFFERSIZE * 5
2 j6 ^8 Z5 T& P - # _9 j: x: V( t# a1 l
- ) ?( v4 I& X: }. `8 ~3 _% n
- uint8_t aTxBuffer[] = " ****UART_TwoBoards communication based on DMA****";
0 _$ `+ z7 p! Y r% z - 6 X4 C& S; d% w$ t
- /* Buffer used for reception */
; O$ H+ A, d+ j9 P0 x* V - uint8_t aRxBuffer[RXBUFFERSIZE];
8 x2 J A! ^) V" |
: J1 } f. w% D; K, H7 o- uint8_t aRxFIFOBuffer[RXFIFOBUFFERSIZE];
* V, S! [+ \2 L# \& B! ?# R) r - FIFO_Type fifo;% u8 U8 w, e& b! n# a: y
- FIFO_Type *pfifo;
, G1 x- I% b! `
) V* ]5 g/ k5 q+ u4 r% e# u) d" @- int main(void)8 J: a1 [0 K" u) u4 Y( L) w
- {& T7 `# f: {" a- c0 }% h: y
- /*此处省略硬件初始化*/
6 U: z8 c S G. ~ - if(HAL_UART_Transmit(&huart1, (uint8_t*)aTxBuffer, TXBUFFERSIZE, 200)!= HAL_OK)
v) U1 e0 D' {# a" ~, V# l - {, r) ~( x/ e0 p
- Error_Handler();
- b b8 U1 B4 U' a - }8 ?! }( e# |2 s2 ^3 x
- / h" q8 z3 ]( V' h+ v
- pfifo = &fifo;
& e1 X, x3 t$ G+ H& ]+ F
" X- V3 _4 \6 p- FIFO_Init(pfifo, aRxFIFOBuffer, sizeof(uint8_t), RXFIFOBUFFERSIZE);: s Z2 M) V; _$ G
- / Q0 {3 A+ H; P" d9 Q2 w, g
- while (1)7 f" Y. P) l2 `; n/ M3 [; I& b
- {
3 ?7 z( u! `0 @8 [- @, n - /*一次接收的缓存,重新发送*/' Y9 I4 ~* D; {+ L/ |, P$ P
- if(!FIFO_IsEmpty(pfifo))7 G! r% ?3 c7 l( e
- { m. n4 J/ W) @- v- t8 A
- uint8_t a[100]; //存放读取fifobuffer的数据& |9 X% ^$ ^. [9 O1 ?
- int i = pfifo->Counter;//先保存接收缓存的数据个数
2 K. ?9 s2 A4 B* Y) Y, G5 F - FIFO_Get(pfifo, &a, pfifo->Counter);3 c7 i1 B8 J0 E6 }+ b8 ^
- HAL_UART_Transmit(&huart1, a, i, 200); //将接收的缓存数据再次发送,判断有无误码率
, z0 _# v# M& [' w( G - }6 d# ^( h2 M1 F D
- }
: Y5 e: [0 ?4 o x - }
复制代码
L+ p3 L* J3 d% `) E% l测试成功!可以在主函数对数据进行处理,不用担心缓存的覆盖!
w) \/ e( U7 X9 c! Y6 w6 M* [) K Y4 M# ^
: r; M% E) j) K3 i; ]
" \* R! D0 S( b; G& s
问:关于 stm32 HardFault_Handler问题处理?5 {2 B' n" O& C) V
! R$ L9 H3 E7 N5 ?- w
ANS:. Q5 b7 I6 b4 p, N# f* c
0 ~- X0 M" |- l: N 在代码调试是,发现在执行fifo_init初始化,会进入HardFault_Handler,
6 @7 W+ a+ T! q' i" a7 v1 K/ r
8 O2 a# C) b6 [; a( M% d. Y8 Y' Z. v- o, p" ^: i
: Q v! U$ y; ?; h( R1 g6 h
) ?( j7 E: ~5 x5 J: n
& `4 {# M: U6 e 最后,发现是在fifo_init 调用的指针,未赋地址。添加之后,解决了!9 }* O$ q/ V4 n( j
+ j$ b8 X8 ?1 G s- a' y% E2 _' `' m1 y3 k) I
! x* F, j# z6 x, r1 X' R
3 h( E5 z. M) c' u( G |