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