你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】stm32f0串口 DMA 空闲中断接收——基于HAL库(代码篇)

[复制链接]
STMCU小助手 发布时间:2021-11-25 15:00
一、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
20210827163252369.png

" ?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
20210827163448427.png
: 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
20210827164240955.png

( 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 ~
20210827164323729.png

- 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
20210827164544427.png
& 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
20210827164829635.png
$ 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
  1. uint8_t aRxBuffer[RXBUFFERSIZE];- ~) _) c6 q1 A* a4 m2 G
  2. /* Size of Reception buffer */- @! W" E9 w9 ^: I
  3. #define RXBUFFERSIZE                    10
    : R9 v* J' E: e$ h2 ~

  4. 3 f! y4 f) i' @7 K$ T
  5. 3 E4 U7 F9 p# g( T# c. n
  6. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)2 _4 F- j% _* q/ `, t
  7. {
    4 ]+ ~2 N  ~, q1 t: u+ F
  8.   /* Set transmission flag: trasfer complete*/
    " }) k3 e% w  R3 q: J
  9.   UartrxReady = SET;
    : V9 z& G! W( J( V. d# W) B- s
  10.         HAL_UART_Transmit(&huart1, aRxBuffer, 10, 0x200);
    2 N3 W. W& }) B* Z6 q4 [
  11.         HAL_UART_Receive_DMA(&huart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);1 l# g5 P; K0 a  f6 {3 r
  12.   HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer,1);
    : A4 f; I4 c4 U' ^$ |1 w  w1 B

  13. % g8 O0 }( z9 D+ b1 N7 a/ o+ g
  14. }. V; `9 Q6 j" \& D! y8 l
  15. ' o: u& p4 J, S3 K( C# M0 m
  16. void USART1_IRQHandler(void)
    4 t: U. X& v* l) }  [+ a" o
  17. {/ P! n- I% R! t+ s9 _5 b
  18.   HAL_UART_IRQHandler(&huart1);
    ! _0 v, f5 j* k  D7 L& c7 ]4 L
  19. }& g5 G+ G$ B) v# t- K
  20. 6 }' W! `7 ]+ j8 A
  21. 3 C! o! g" E9 a5 _7 w  P
  22. static void MX_USART1_UART_Init(void)
    , J; e' x( u1 T6 ]: t7 V& k
  23. {
    & I) g5 A/ Q. v; s! M
  24. 5 ~- u/ N& [; [" m+ L8 \% A  B
  25.   huart1.Instance = USART1;
    5 Q7 s9 `0 u# C/ _0 }8 A  m
  26.   huart1.Init.BaudRate = 9600;
    8 H3 y4 b; m% U, x2 M# U9 @
  27.   huart1.Init.WordLength = UART_WORDLENGTH_8B;
    6 d" F' @% U- g; j( F5 z
  28.   huart1.Init.StopBits = UART_STOPBITS_1;& Z  D9 z- k3 d- V0 d
  29.   huart1.Init.Parity = UART_PARITY_NONE;
    1 M) ]* e0 A: U7 U) C/ e6 j5 Z
  30.   huart1.Init.Mode = UART_MODE_TX_RX;8 x' F. V& s0 q6 U8 u
  31.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;2 W* R+ N# H) o; J' R6 U
  32.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;6 T# R" h0 y/ K: |& j
  33.   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    % g$ U# [+ a/ m0 @* }. n' q$ j
  34.   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    1 E/ c6 }- C6 c! H9 J! _
  35.   if(HAL_UART_DeInit(&huart1) != HAL_OK)
    ; Z, r1 C* N2 E. {0 s+ I% X& `# d
  36.   {
    2 {# \3 u, B2 ?$ j  ?1 a
  37.     Error_Handler();6 v0 F6 q0 ]4 y2 Z
  38.   }  1 M% s4 H- N7 D8 j. c
  39.         ! D+ u$ y! I. @( @: u
  40.         if (HAL_UART_Init(&huart1) != HAL_OK)
    4 X! B$ J2 R8 `  _  c" U
  41.   {% ~7 b- g4 k0 r8 I3 {
  42.     Error_Handler();! c' G0 _3 s, j& r9 h% `8 p1 \& c
  43.   }
    # R( W3 g( c9 i% o0 ]+ Z' d. b
  44.         
    ' X! M9 J, c+ p  F
  45.         UartrxReady=RESET;
      j  [% a" |  J9 g7 [4 o
  46.   /* USER CODE BEGIN USART1_Init 2 *// d% M8 ^- n# j" z
  47.         if(HAL_UART_Receive_DMA(&huart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)1 {; e% j, [. [' c0 M) _
  48.   {+ Q' m, C1 H' m/ O1 c# S0 b- r
  49.     Error_Handler();- }7 S0 i7 |+ ]2 w2 l: J
  50.   }- d, L" h! f" e! @* W) z/ k1 a
  51.         " m0 T. s8 P, ^$ r7 b; v
  52.   /* USER CODE END USART1_Init 2 */! O2 G! F7 R' F: E
  53. }
复制代码
( Y# y) L+ D1 ~& m5 N
从串口调试助手可以看只有接收的长度 RXBUFFERSIZE为10时,才触发接收回调函数。
5 `; n: i% A$ o! }( ~; h. E
" U6 x8 H6 g, h9 f/ z) M' z
20210902164819116.png

" 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
  1. static void MX_USART1_UART_Init(void)
    ; Y& b% x4 f% q& i
  2. {% ~  r& \& T6 s+ |
  3.   huart1.Instance = USART1;  z  r% Q; f# a+ x% M+ A
  4.   huart1.Init.BaudRate = 9600;+ F0 y) F( s2 F# E9 h3 a
  5.   huart1.Init.WordLength = UART_WORDLENGTH_8B;5 j  N7 w" Y, o
  6.   huart1.Init.StopBits = UART_STOPBITS_1;: g2 V; E7 c! m7 n% h+ S/ A
  7.   huart1.Init.Parity = UART_PARITY_NONE;$ l+ z7 |1 B( V8 e
  8.   huart1.Init.Mode = UART_MODE_TX_RX;
    " u# ^( q% ~8 f5 e. K! E+ D& j/ Y
  9.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    8 X( h8 x# B' P( P$ G# E
  10.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;# h9 ]5 `9 A. v9 b8 k0 ?$ @
  11.   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;* k- j9 d1 G4 h' ]6 M! R" R  e. k
  12.   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;8 b/ b1 r; B7 j
  13.   if(HAL_UART_DeInit(&huart1) != HAL_OK)
    % P7 ~$ I" t8 ~; [
  14.   {, U) ?% u' D; r/ i
  15.     Error_Handler();
    " D. i& X) a1 ~3 q
  16.   }  + T" }: d, J/ O8 o' a& }8 W3 t! g" \
  17.         4 v/ ~# W% }2 X( e$ k/ j3 n
  18.         if (HAL_UART_Init(&huart1) != HAL_OK)
    / N$ P! W3 W# l& b
  19.   {
    ' W% X% I7 @5 V+ g/ w* ]! A6 \
  20.     Error_Handler();6 r7 w5 D9 ^4 j+ C3 g  \
  21.   }7 L+ n! X8 y9 u
  22. 7 e7 u' p5 \" b, k  o6 a5 {" R0 c
  23.         __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
    0 u7 ~3 h$ o7 o4 k
  24.   /* USER CODE BEGIN USART1_Init 2 */) O: p4 K1 j/ i5 x5 L, V
  25.         if(HAL_UART_Receive_DMA(&huart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)" W  [) V7 K7 P
  26.   {
    * {. J1 U& u, \1 A4 e$ @4 B
  27.     Error_Handler();5 h1 Y1 k9 v6 u
  28.   }
      g! S0 F! b5 S
  29.         
    7 l' q% S: t( n+ M
  30. }
复制代码
3 G9 f9 [( D/ ]: K
空闲中断函数: 2 r; E7 _  g' H
  1. #define TXBUFFERSIZE                    30/ q9 b; m$ M/ y) Y' Z
  2. /* Size of Reception buffer */9 ?* M7 t6 w8 W& g  d
  3. #define RXBUFFERSIZE                    306 d8 V; q6 N( e1 M) r
  4. 0 d  G$ k. ]. ?! A$ \! }
  5. void USAR_UART_IDLECallback(UART_HandleTypeDef *huart)$ K" D8 g/ B, Z% @, y& n' h! E
  6. {
    % J1 E; I5 i$ y' k  J9 h
  7.     HAL_UART_DMAStop(&huart1);
    7 T8 f: {0 [/ P
  8. - Z3 k2 Z+ h& h( l4 |
  9.     uint8_t data_length  = RXBUFFERSIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
    : k7 b5 A5 P( P- H

  10. " q/ J. W  y* W. f3 E

  11. 4 V$ {/ l( ^0 d
  12.     HAL_UART_Transmit(&huart1,aRxBuffer,data_length,0x200);
    3 D% ?3 o# E' }% J& C. L; ^5 `
  13. # K: @3 d' t7 `* S
  14.     memset(aRxBuffer,0x00,data_length);6 Z: Q+ {" J9 N. ~
  15.     data_length = 0;' q$ f% R- ]/ v! ]
  16.     HAL_UART_Receive_DMA(&huart1, (uint8_t*)aRxBuffer, RXBUFFERSIZE);9 r3 G& t, _9 N* o+ f6 ?
  17. }/ ?$ d$ ]/ J" I: ~& @. ^

  18. 1 m3 w+ i: B* N' S- d
  19. void USER_UART_IRQHandler(UART_HandleTypeDef *huart)+ _6 e7 H* s7 O
  20. {: l% J5 \+ Z8 }$ v" M0 a$ f
  21.     if(USART1 == huart1.Instance)
    3 y  w- i' T" x. B- c) d( R7 @# C
  22.     {* @) q9 L3 l& V1 a+ |, N
  23.         if(RESET != __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))# I7 D; Q5 K4 ?* M$ C
  24.         {- Q) {* {) _7 D5 L# [
  25.             __HAL_UART_CLEAR_IDLEFLAG(&huart1);
    " p3 V. J. q8 ~  _& k" t
  26.             USAR_UART_IDLECallback(huart);5 X( g3 t' A5 t5 y" G2 v
  27.         }) ^1 R9 x8 N$ c
  28.     }; }) {& i7 h) |2 T
  29. }# P/ o8 e& q7 H% Q+ \& P

  30. $ V" a- t- j. _# k
  31. /**
    + R! V! b4 F; t0 _: M% W9 I6 ~
  32.   * @brief This function handles USART1 global interrupt / USART1 wake-up interrupt through EXTI line 25.
    3 B& ~$ ^2 E! ~# O
  33.   */
    4 N* m$ L, X8 E$ B
  34. void USART1_IRQHandler(void)
    ' R8 s% e' k# J. o! V
  35. {- p. E# N- `  `, v9 \$ Q
  36.     HAL_UART_IRQHandler(&huart1);
    0 T6 K; A2 \+ D! i
  37.     USER_UART_IRQHandler(&huart1);* y2 [$ E7 n9 N) P/ }6 P
  38. }
复制代码

  |5 X# D" t2 r5 {) [可实现不定长的接收!
; B! V4 @# N9 i9 o, w9 P8 C' l( |
20210902171851390.png

( 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 \
  1. #ifndef        __FIFO_H_
    , x8 Y! E# D/ E& o) {2 j
  2. #define        __FIFO_H_/ b. p4 ]" X, X* E. C
  3. % [* x2 r# ?1 i, _
  4. #pragma pack(4)0 c$ a  V) `+ ~5 ]
  5. typedef struct FIFO_Type_STRU
    / [  U" k0 G- P, k: ]; R* _
  6. {6 q1 N# ?! s+ V2 N
  7.         unsigned int                        Depth;                        // Fifo深度5 ]- }9 W, ~/ _) ~
  8.         volatile unsigned int        Head;                        // Head为起始元素5 c: H: L$ o) b, p( n5 L
  9.         volatile unsigned int        Tail;                        // Tail-1为最后一个元素% v, g& s, Z* e. K
  10.         volatile unsigned int        Counter;                // 元素个数+ _% c# n, N( B. [0 q
  11.         unsigned int                        ElementBytes;        // 每个元素的字节数element8 o0 L& u7 e# T) |4 S6 j, A  ~
  12.         void                                        *Buff;                        // 缓存区
    / k$ }5 y- i, k! \) ]/ p% ]. ?+ m* M* ~
  13. }FIFO_Type;" F: T) T, u$ G3 {
  14. #pragma pack()
    ( }- M+ o2 t5 T- X
  15. # W& T# m, W+ @- h6 S5 r7 l, R
  16. /********************************************************************//**
    3 A: o/ w. u( V: M4 Z1 g" @
  17. * @brief       FIFO初始化
    % @, P2 Y: ]  y- x& N/ {! D
  18. * @param[in]   pFIFO: FIFO指针
    , o* Y1 Q! O# j. N' x
  19. * @param[in]        pBuff: FIFO中缓存! a  e/ D  D" j  B% k2 {
  20. * @param[in]        elementBytes:FIFO每个元素的字节数
    , G+ M* l. ?0 V' ^; ]( K
  21. * @param[in]        depth: FIFO深度4 m4 h- {6 f2 E8 i% J9 z; [& g/ i
  22. * @return      None
    ! Q! R; m" H& k1 H# v. S
  23. *********************************************************************/
    ' E5 j, E/ @* R8 ^0 n& W
  24. void FIFO_Init(FIFO_Type *pFIFO, void *pBuff, unsigned int elementBytes, unsigned int depth);
    # o4 S- h; x9 C$ r5 x2 v* D

  25. ' v. I# u6 x: x# j. M
  26. /********************************************************************//**
    $ w' L; }* i/ z7 p& [
  27. * @brief       向FIFO添加一个元素3 h* t  s7 {$ ?' o5 ?( p
  28. * @param[in]   pFIFO: FIFO指针
    0 O8 k) g+ K! J  j& ^) ]' d
  29. * @param[in]        pValue: 要添加的元素2 B% b, p3 l; G
  30. * @return      1-TRUE or 0-FALSE
    4 ?! ?4 c* W$ b, P; y- W
  31. *********************************************************************/, D0 K; G+ f( w# [! Y/ C& Q% n
  32. unsigned char FIFO_AddOne(FIFO_Type *pFIFO, void *pValue);# s7 X; `- \' ]) N5 t( |) \, k

  33. 5 u+ W9 }6 [% ~) j$ Z! T
  34. /********************************************************************//**5 l4 V1 I% i6 m3 m" H* t
  35. * @brief       向FIFO添加多个元素
    6 e- s+ F: P" r/ r9 `5 R; n
  36. * @param[in]   pFIFO: FIFO指针/ @  S# y, c! f  O# R- ]. w
  37. * @param[in]        pValues: 要添加的元素指针
    ) `' @3 U  j1 N, A" Y7 W4 c
  38. * @param[in]        bytesToAdd: 要添加元素的长度
    & E( ~8 p7 M: |. ]! X* h
  39. * @return      实际添加的元素个数
    6 E5 m/ n9 p/ ~2 E! _
  40. *********************************************************************/
    1 ~" P: ?  c4 P) a0 r0 F" t2 W
  41. unsigned int FIFO_Add(FIFO_Type *pFIFO, void *pValues, unsigned int bytesToAdd);  O& {0 u, C, s6 v: @( V
  42. + D5 C, F  J( p7 ?$ |: p, k- m
  43. /********************************************************************//**/ b5 g4 V, G/ w+ \: |) t# m
  44. * @brief       从FIFO读取一个元素: L* I; i- G+ k3 _7 J7 k3 z9 q# z
  45. * @param[in]   pFIFO: FIFO指针: o% W8 ^* y( M
  46. * @param[in]        pValue: 存放要读取的元素指针
    ( G, d/ W5 o& a3 ~
  47. * @return      1-TRUE or 0-FALSE
    , q/ m$ r) p6 }
  48. *********************************************************************/
    0 _6 Z6 q4 B% X: A9 v% ~# c
  49. unsigned char FIFO_GetOne(FIFO_Type *pFIFO, void *pValue);
    ! i0 M  Z4 D$ g* ~: e7 S! f+ p

  50. 4 q2 u$ z( y+ F
  51. /********************************************************************//**
    8 F/ a) \8 c: K. |4 h4 q4 ~
  52. * @brief       从FIFO读取多个元素0 D0 E- T) h+ T! o# S1 h
  53. * @param[in]   pFIFO: FIFO指针7 }3 m# \  A2 Z8 w
  54. * @param[out]        pValues: 存放要读取的元素指针. \$ g* t9 U2 |6 ?. `
  55. * @param[in]        bytesToRead: 要读取的元素长度) |2 Z- `; u3 r2 o6 D
  56. * @return      实际读取的元素个数. }5 e( i3 y8 y" x3 r
  57. *********************************************************************/) w4 }- x' _) g, K9 p/ T1 f0 ?
  58. unsigned int FIFO_Get(FIFO_Type *pFIFO, void *pValues, unsigned int bytesToRead);. L4 I# u4 r, j. j4 i& f2 {' p
  59. 5 {/ O7 [3 f$ e' h2 s9 b" r7 i

  60. & G! z$ G! |* M2 E! F- O3 i
  61. /********************************************************************//**/ o& u7 E  `4 G% c" L
  62. * @brief       清空FIFO$ w) M4 Y% s/ l8 B* [
  63. * @param[in]   pFIFO: FIFO指针+ l1 J) I& F! ~7 [7 Q$ V
  64. * @return      None! S2 R* Y/ ]& [: J# f; D
  65. *********************************************************************/
    5 |" V! A0 w7 z0 V
  66. void FIFO_Clear(FIFO_Type *pFIFO);
    4 y0 ?; e+ {% M* T5 ?
  67. & I0 n& F! Z* }7 G" o
  68. # }+ {1 c% x# m% k; W
  69. unsigned char FIFO_IsEmpty(FIFO_Type *pFIFO);1 }5 {; B5 s, E) p+ q# A" N( U3 |- q
  70. . j4 `) q$ a* c/ G5 O, Z
  71. #endif
复制代码
$ o6 F; h6 A2 T) n# n9 ~
② fifo.c程序主体
* Y1 W. x* H% e% z( g
' b) U# J$ V) W$ V3 |
  1. #include <string.h>
    , g& S9 I$ H. ?: G' K! R
  2. #include "fifo.h"$ Q" a% K2 {8 L
  3. # [" }, K2 _2 @; T6 K& w

  4. ) Q! S2 N  E- I# E5 f0 }$ \
  5. /********************************************************************//**. Z+ f) L! G% x" M+ `/ L2 d
  6. * @brief       FIFO初始化" j4 }- S# b$ }% H
  7. * @param[in]   pFIFO: FIFO指针
    0 N; N+ \* f. t; ^6 X; U
  8. * @param[in]        pBuff: FIFO中缓存% }3 u3 [# E1 E3 w: E& t) M- q1 H
  9. * @param[in]        elementBytes:FIFO每个元素的字节数
    / d( Y7 m# O1 a
  10. * @param[in]        depth: FIFO深度
    - U) D) P& s( j3 h# D0 e
  11. * @return      None
    / m1 T+ F% @# A, N5 @0 u3 `
  12. *********************************************************************/
      I- X+ S7 b% D" {& t+ i7 n
  13. 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
  14. {
    / M; X/ N" S3 P" ]; P
  15.         pFIFO->Buff = pBuff;2 c$ q# e' j# s% k& ?! j
  16.         pFIFO->ElementBytes = elementBytes;9 I: ^5 _4 E  c/ p& r3 e
  17.         pFIFO->Depth = depth;8 }* [9 ^6 B! O% |  h/ c' [- G
  18.         pFIFO->Head = 0;
    / `. a: ]* T8 j$ o, D# r. u
  19.         pFIFO->Tail = 0;
    0 Q+ e" S! b) g
  20.         pFIFO->Counter = 0;
    0 C) a7 W& z( u- ]* q
  21. }
    . G4 ^" g1 ~4 A, ?0 o
  22. 2 I6 z- P! o& f6 a: g6 R) Z
  23. /********************************************************************//**% l* P& G+ _' ^# D4 V0 ^
  24. * @brief       判断FIFO是否为空
    " B7 [; [# A. S7 X6 J
  25. * @param[in]   pFIFO: FIFO指针
    * ^% K" H: ?- C- P6 N9 N7 r
  26. * @return      1-TRUE or 0-FALSE
    : g$ O8 w( E- {5 F$ i
  27. *********************************************************************/
    1 I% N5 @* l0 y4 U
  28. unsigned char FIFO_IsEmpty(FIFO_Type *pFIFO)
    & e* ]$ @/ l# e2 c6 c$ m- o# x  y
  29. {
    ; N* n! b7 T' i  |
  30.         return (pFIFO->Counter == 0);
    ( n. g1 l7 p9 J+ }: _- L
  31. }
    / c8 \5 H0 t0 B/ g; @
  32.   ^9 K3 n- K+ D2 p% ^6 l
  33. /********************************************************************//**
    / U( u- D3 C5 Z: |2 @( ~6 \+ d
  34. * @brief       判断FIFO是否已满# Q& H2 @- [/ d- i) o7 r
  35. * @param[in]   pFIFO: FIFO指针
    " e4 W4 [6 f4 z& O9 D
  36. * @return      TRUE or FALSE
    : t0 s3 v' B% E  Q. R: l" z4 k
  37. *********************************************************************/9 E2 {% ?' P( j& v
  38. unsigned char FIFO_IsFull(FIFO_Type *pFIFO)/ D. _: {: v) W+ ?
  39. {/ _/ F' m3 X7 _" ]. ^, e# `
  40.         return (pFIFO->Counter == pFIFO->Depth);1 @9 ]' S3 M+ v$ @
  41. }
    * o/ [, ^8 J4 f& P* x/ ~

  42. " ^( N* E  |. S) l1 n
  43. /********************************************************************//**
    # v# T: ^9 b. x% D+ ]) T, a/ ]
  44. * @brief       向FIFO添加一个元素
    2 [( [" e+ ?: k- g; E$ Y; {. d
  45. * @param[in]   pFIFO: FIFO指针( R$ u3 p3 ~( Y5 W
  46. * @param[in]        pValue: 要添加的元素
    & E$ `! Q2 ^9 y8 Y# d" f  C
  47. * @return      1-TRUE or 0-FALSE
    & [9 t9 X  p  ]( _' w  b% X
  48. *********************************************************************/  Z; p) S% j. v  ]. H
  49. unsigned char FIFO_AddOne(FIFO_Type *pFIFO, void *pValue), ~7 k) D6 w0 U+ N* B) f  T
  50. {
    2 O6 e& ~9 ^8 c, t4 V
  51.         unsigned char *p;  t2 A! I- s: t
  52. : E& ^: N7 G" R& J; _
  53.         if (FIFO_IsFull(pFIFO))
    ; N& j& }; i. {) v
  54.         {- k* v5 y5 C0 U
  55.                 return 0;
    " ^  z$ G  D% Q: C! s" U& A
  56.         }2 n/ X- n5 v% F3 b
  57. ( b2 v8 M( m0 G7 R7 ~
  58.         p = (unsigned char *)pFIFO->Buff;
    ! o" h0 B$ W7 q2 N: X& T+ o; \
  59.         memcpy(p + pFIFO->Tail * pFIFO->ElementBytes, (unsigned char *)pValue, pFIFO->ElementBytes);
      x4 `3 E9 L8 _& S" E" t
  60.         5 T8 F% M- |- L
  61.         pFIFO->Tail ++;
    - ^- D5 X' }3 x# C
  62.         if (pFIFO->Tail >= pFIFO->Depth)) F9 `/ x" o9 I) n9 S
  63.         {
    % Z2 M5 T+ C2 r  }2 r* R; }% m# Y  X
  64.                 pFIFO->Tail = 0;
    % @8 W$ f7 t# s+ Z
  65.         }3 O# n7 g$ f* ]4 |" W5 M& t  R: J
  66.         pFIFO->Counter ++;. S$ ~( p# E6 v5 _2 X
  67.         return 1;) V4 M9 j' i$ P* a3 g  n7 Z
  68. }
    # v7 Q2 }: O0 J. U2 _* K. c

  69. , |% @$ {# \0 C! r+ f  n* y$ {) G
  70. /********************************************************************//**3 m; x  H0 V7 |3 s% k8 C+ Y
  71. * @brief       向FIFO添加多个元素
    " Y7 U/ l; e; M  o
  72. * @param[in]   pFIFO: FIFO指针7 q/ O  W1 g7 ~
  73. * @param[in]        pValues: 要添加的元素指针
    ; L" L% N# c' z! K' ^: Z, {
  74. * @param[in]        bytesToAdd: 要添加元素的长度; `* z' t" E; ?" w
  75. * @return      实际添加的元素个数
    . m6 k5 r  y6 U
  76. *********************************************************************/
    ( O+ f* M& Y4 m% o
  77. unsigned int FIFO_Add(FIFO_Type *pFIFO, void *pValues, unsigned int bytesToAdd)
    : \1 c$ O. y: }- F) q, d8 m! W
  78. {" I; L$ m( r. A" @) r7 a
  79.         unsigned char *p;
    - w1 Z5 p# D  l, S4 I. O
  80.         unsigned int cnt = 0;8 L/ x+ Y0 h7 T: m
  81. 6 q2 W. n+ T, L  ^1 K
  82.         p = (unsigned char *)pValues;
    - P! ]9 f# d" X7 ?; y" X
  83.         while(bytesToAdd --)3 c. P3 s8 {8 j& }. C9 D
  84.         {" _4 e3 r! o# @5 \3 h6 |
  85.                 if (FIFO_AddOne(pFIFO, p))% v" B2 |5 j/ [: Z! h
  86.                 {5 f4 Z" k6 x+ F# K6 E+ Z' g
  87.                         p += pFIFO->ElementBytes;
    1 B2 J4 c2 ]- ]1 j3 l
  88.                         cnt++;* z  \4 D6 E7 q$ X, ]8 [( P; Z2 L
  89.                 }
    * z% A9 {3 w1 Y  [8 q8 |2 r6 I) L+ a
  90.                 else. T; r! ?) I: Y% w) @6 K% g
  91.                 {$ B% K; @: y; Z# d& x
  92.                         break;
    / p2 j" l& t! x) i
  93.                 }, u! b* |/ G1 z* g" W. |
  94.         }
    8 m/ b5 r1 N$ d" I% Q% H

  95. $ ~0 q$ e5 v) W1 i
  96.         return cnt;
    " i: e' n2 I" \/ ~" w8 J
  97. }
    , P% J1 T& r$ K- o2 i7 ]

  98. 7 b' K! c1 ^; D) u' ^/ ]# a: Z
  99. /********************************************************************//**, H! p  y* T9 G6 Z1 b8 o2 P& s9 a
  100. * @brief       从FIFO读取一个元素
    0 ^4 K" N) w, |7 v% z
  101. * @param[in]   pFIFO: FIFO指针
    " C( V3 E2 _# z
  102. * @param[in]        pValue: 存放要读取的元素指针
      K6 }9 Q; |! S& `
  103. * @return      1-TRUE or 0-FALSE
    " C# V$ {7 \; D3 \- C8 c  i
  104. *********************************************************************/: {! T! Q, ?1 \3 ~- i* i
  105. unsigned char FIFO_GetOne(FIFO_Type *pFIFO, void *pValue): c- g- M# ?+ q0 G8 ^# m
  106. {
    / N# N1 M3 g) ^
  107.         unsigned char *p;" ]9 O5 U5 z3 C- T7 v9 X' Q
  108.         if (FIFO_IsEmpty(pFIFO))
    ( [3 W4 ^: a& X, R, \$ l, m
  109.         {9 _, n9 {$ X1 E1 W  z# ^
  110.                 return 0;
    ; f: F' |  [+ I0 h) l  E
  111.         }
    - _& e) a  D+ l/ R

  112. $ b  Q) E  l4 p8 v3 x% P: h
  113.         p = (unsigned char *)pFIFO->Buff;
    + T" O) F& i1 |/ L3 W
  114.         memcpy(pValue, p + pFIFO->Head * pFIFO->ElementBytes, pFIFO->ElementBytes);2 j4 f/ f1 y2 K7 d

  115. $ O9 T9 v) m' e$ K3 u, X
  116.         pFIFO->Head ++;7 K! S2 P7 A" T+ t6 h
  117.         if (pFIFO->Head >= pFIFO->Depth)
    . Y3 n1 b. e' Q+ U1 T8 L
  118.         {- p$ P% I8 J% }7 H
  119.                 pFIFO->Head = 0;
    1 Z; M7 N% {1 j' [* u" ^' f$ Z
  120.         }- s$ U& ?. i, Z- v, }
  121.         pFIFO->Counter --;
    2 }8 p! U6 O2 E% g7 _4 a2 ~$ j
  122. ! j; f3 L  _# ]" u
  123.         return 1;" _! T. a; }0 o" E+ w( g9 N4 i
  124. }
    0 p" e  Z. L' `# {# u4 X, l

  125. 6 r& m2 B- C6 E( ^6 P1 {
  126. /********************************************************************//**
    + d3 Y9 A8 L: G7 }, \* m
  127. * @brief       从FIFO读取多个元素
    & u+ T0 _4 m6 h; C/ P
  128. * @param[in]   pFIFO: FIFO指针: s4 o9 s+ u: j0 w7 |
  129. * @param[out]        pValues: 存放要读取的元素指针) i6 M# m9 L6 H" G; {; a
  130. * @param[in]        bytesToRead: 要读取的元素长度+ A9 F3 G4 q* U- Q; J
  131. * @return      实际读取的元素个数
    1 ?: i  o! ~/ w$ U! j1 p
  132. *********************************************************************// z$ L8 v2 N! J( ?3 s3 T) _
  133. unsigned int FIFO_Get(FIFO_Type *pFIFO, void *pValues, unsigned int bytesToRead)
    . V: k6 `" [/ W5 ?, |$ H. W' y
  134. {
    , C: P* V! L( j* \/ w
  135.         unsigned int cnt = 0;
    2 j+ O& ~0 E; ]. O$ }* [
  136.         unsigned char *p;
    7 U* h# k7 Z5 F9 A

  137. 0 n. E8 ^5 Z/ p. p
  138.         p = pValues;
    6 G# N& \( @3 C4 L
  139.         while(bytesToRead--)$ s+ E, c8 t6 B! G3 L
  140.         {
    7 A6 J/ @0 |! B. O* x+ ~0 }
  141.                 if (FIFO_GetOne(pFIFO, p))- ]1 O9 J; }9 i2 L. l$ P" Y* i! K
  142.                 {2 B& Q: Y$ b6 ~
  143.                         p += pFIFO->ElementBytes;
    " v. o4 }' A) q& u# b, g2 v
  144.                         cnt++;
    + K& z' `' A) T, i0 P
  145.                 }
    ! }+ g% {) o. B9 C7 ]
  146.                 else
    / W% D; _4 B( ?4 z; P; z( L
  147.                 {$ ]8 I$ E0 G' p. o" T$ M, B
  148.                         break;
    8 N0 P/ P$ p' E- a) N2 V3 K9 V
  149.                 }* x) a1 o% Q% J, A( r
  150.         }/ r+ `4 E* ~1 h
  151. ' \6 O7 ^' ]; _: X
  152.         return cnt;: d) D+ k! Q5 D; L. K
  153. }6 d* H% p( p9 s5 K; z# ]
  154. 9 L8 z$ Q( z( L( s
  155. /********************************************************************//**
    , Y$ ~3 L5 Q% A% E5 O
  156. * @brief       清空FIFO% w' C; q. o+ l. n+ [! O% I& [
  157. * @param[in]   pFIFO: FIFO指针
    . m8 s# F1 ?% E) ~" ?. m
  158. * @return      None# o/ x6 S+ r' \% G/ T8 p
  159. *********************************************************************/4 J9 ^8 ?; k6 R
  160. void FIFO_Clear(FIFO_Type *pFIFO)8 a* _, i6 K. U( b: X# O' |2 i
  161. {
    + ~1 y' F7 o1 ^: F0 H% X  ]
  162.         pFIFO->Counter = 0;2 C+ F/ a  z3 N2 `  D
  163.         pFIFO->Head = 0;4 M2 o5 J* D7 I+ |" O) D3 P' j
  164.         pFIFO->Tail = 0;
    , v) @2 E5 M5 o) u
  165. }
复制代码

4 W! D5 ], ^3 y/ u7 Y6 x) d ③ 串口初始化
: L1 O8 Y3 m1 {9 x+ I* S
  1. static void MX_USART1_UART_Init(void)8 v0 x/ p& r! G2 j( u
  2. {$ s' r6 I0 r0 U/ Y2 h. v: X3 V
  3.   huart1.Instance = USART1;
    ) N% t. O. H* m" h' i/ q: D: C, U% o# `
  4.   huart1.Init.BaudRate = 9600;7 l3 O! U& k/ V5 V. h. X* k5 X
  5.   huart1.Init.WordLength = UART_WORDLENGTH_8B;
    ) t  W" r" C* l& E. A' L
  6.   huart1.Init.StopBits = UART_STOPBITS_1;6 h# s5 B* \- R' a4 G: {
  7.   huart1.Init.Parity = UART_PARITY_NONE;# K, L! c0 O: R$ \; i6 O
  8.   huart1.Init.Mode = UART_MODE_TX_RX;
    $ @3 z5 `, a/ I# `' W" i& R
  9.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    ( o/ k1 n$ k4 N
  10.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;4 g" O! D+ A$ V6 P
  11.   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;: X1 f% }6 W1 a, ^! j
  12.   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;) l. E/ n6 s8 l3 p9 B
  13.   if(HAL_UART_DeInit(&huart1) != HAL_OK)
    : w& C1 o0 H5 D* }
  14.   {
    8 k. q$ g1 L7 }- O- b6 V5 d
  15.     Error_Handler();
    9 X1 ~9 O2 e" \: O
  16.   }  ' |$ b. l8 V6 b; r7 R5 ]  p
  17.         
    0 L3 M/ v: V* M7 q) P. q
  18.         if (HAL_UART_Init(&huart1) != HAL_OK)
    + M1 ]/ N: @+ x, m. X' c# |
  19.   {1 q( r+ s4 U' y% A" b. V* M
  20.     Error_Handler();4 V$ J0 T7 j9 o9 ]0 V: F8 |3 R
  21.   }' B$ D% @/ R0 z$ C* s; B3 ^0 z
  22.         9 b8 o; c9 I# l$ K+ U/ j  L
  23.         __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); 2 `- U$ D. g/ J4 D4 l& U
  24.   /* USER CODE BEGIN USART1_Init 2 */
    9 d- D) z( M% @) p1 w  O
  25.         if(HAL_UART_Receive_DMA(&huart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)
    5 t. c" r/ O! G! w5 c0 t  U+ C
  26.   {$ h% w) b1 K0 W; ?) [/ A1 X+ ?
  27.     Error_Handler();
    - Q0 i( e9 ?4 r/ \8 X! M- G3 t
  28.   }4 P& ]) Z8 n+ }/ _7 F( f
  29.         / m1 J" v2 B# `7 x" W* Z, F- a
  30. }
复制代码

5 z: J5 r) `" q6 g% s ④ 接收空闲中断! Y4 V! h% j1 H: R6 `; q
  1. void USAR_UART_IDLECallback(UART_HandleTypeDef *huart)
    ; S# Q5 C: x7 U; N) T9 M8 J; Y/ @
  2. {
    " n- s" g# Q; W
  3.     HAL_UART_DMAStop(&huart1);; ~3 _& P' i$ H7 C
  4. 4 U3 l% ?0 d9 Z$ n  ]# _
  5.     uint8_t data_length  = RXBUFFERSIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
    / L: b- _9 N/ k; ~: J
  6.         " I" m$ |+ e2 V! M' K1 b( w
  7.         FIFO_Add(pfifo, aRxBuffer, data_length);! ^8 i% G8 s: [5 p8 v* q* v6 Q
  8.     data_length = 0;& q% |/ L& E0 }' C, Z+ J( Y7 {# _
  9.     HAL_UART_Receive_DMA(&huart1, (uint8_t*)aRxBuffer, RXBUFFERSIZE);
    ( |! O5 t6 r. ]" _
  10. }* {+ ^! g+ f; J4 D- f& w" Q9 \

  11. 3 F. n' o4 o0 C- C; {
  12. void USER_UART_IRQHandler(UART_HandleTypeDef *huart)& Y1 V2 H( g, ~3 M7 e$ y
  13. {
    8 o7 Z! R* C+ P+ x
  14.     if(USART1 == huart1.Instance)
    8 l6 D# M  F; A! [) b8 _( C3 u" J* k
  15.     {, c; _2 m5 P( w; J2 n
  16.         if(RESET != __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))( A3 L  k2 H2 f# q3 X, Y; C
  17.         {, N% L5 L' a' I8 D
  18.             __HAL_UART_CLEAR_IDLEFLAG(&huart1);
    2 k* G6 B/ n. N- ?  T6 H% i6 P4 ^
  19.             USAR_UART_IDLECallback(huart);
    2 W) r- i+ j8 I
  20.         }) a4 E6 ^8 q5 T( ?: Z. k
  21.     }' |3 L  q; M, C4 G) }
  22. }  z2 ?/ p- Y0 h5 p+ \; y$ H

  23. ) j" z' c+ c/ g. M; G
  24. /**
    - N' O3 T8 J8 f+ f
  25.   * @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
  26.   */3 n# Y/ M: b0 j" z6 t& Y1 Y
  27. void USART1_IRQHandler(void)
    . f1 B) V8 H( x" ]# Q' n- r; Y
  28. {
    $ W: W" X1 Y; _
  29.   HAL_UART_IRQHandler(&huart1);4 y, X8 }1 @9 ]
  30.   USER_UART_IRQHandler(&huart1);/ y' J" K: o3 ~
  31. }
复制代码

0 `: P: r( o. m; O1 G. {, m⑤ 主函数调用:6 x: B# T! m. O8 I2 {. B$ n( W$ f
  1. #define TXBUFFERSIZE                    30
    % E, |' U3 U: _% G1 o
  2. /* Size of Reception buffer */
    + ~$ E( m% o* q4 H9 i. V
  3. #define RXBUFFERSIZE                    TXBUFFERSIZE% S8 P7 D- r" l* k
  4. #define RXFIFOBUFFERSIZE                TXBUFFERSIZE * 5
    " H+ q4 U1 d1 }% M
  5. , Q( ^9 Z) `2 t0 v: u8 E
  6.   J' U  }+ U; P* I
  7. uint8_t aTxBuffer[] = " ****UART_TwoBoards communication based on DMA****";' n( [8 |: k6 D% }, {/ O
  8. 3 K# X# o" R. e, x( x( `* o
  9. /* Buffer used for reception *// l7 d' p2 g/ W  N4 G- R4 q
  10. uint8_t aRxBuffer[RXBUFFERSIZE];5 e+ b9 b1 N6 O" H- O
  11. ( d! u. T5 z" I$ [3 O
  12. uint8_t aRxFIFOBuffer[RXFIFOBUFFERSIZE];3 a& H: D$ b- @" N
  13. FIFO_Type        fifo;7 g. H2 }9 b1 Y$ p) ]
  14. FIFO_Type        *pfifo;% @( |* x8 ^4 \1 g

  15. * u6 i4 Z. p& o( H  B5 H
  16. int main(void)
    8 \$ S" O9 O6 W# g. Z- ^
  17. {2 b' T$ X, y( v
  18.   /*此处省略硬件初始化*/) z0 |  l& q& M/ n
  19.   if(HAL_UART_Transmit(&huart1, (uint8_t*)aTxBuffer, TXBUFFERSIZE, 200)!= HAL_OK), m8 W9 Q# l+ q, W: ?4 w
  20.   {
    # m. c) W: t7 l
  21.     Error_Handler();0 Z, b) y! h; }- t
  22.   }
    2 D1 ~' O7 I5 E4 m( n2 f
  23.         
    0 i+ c/ Y& p  C
  24.   pfifo = &fifo;" [& D. q0 O2 u3 g' Q+ U; ~

  25. % U' N7 c( }/ ]: }" \  X$ @! X
  26.   FIFO_Init(pfifo, aRxFIFOBuffer, sizeof(uint8_t), RXFIFOBUFFERSIZE);8 Q0 d+ g3 u) J! t0 H! ~: o6 X

  27. # [/ }7 ?2 u% m6 ^2 i; D" f1 ^
  28.   while (1)
    / [7 x/ G* C( k6 `/ n8 l- I+ M
  29.   {7 ]! A7 X8 n$ u0 e- D2 G2 `1 T0 ~
  30.         /*一次接收的缓存,重新发送*/$ H0 _; y0 p3 S! ~2 O% v
  31.                 if(!FIFO_IsEmpty(pfifo))
    8 Z- H5 }/ b# N$ ~
  32.                 {
    , M" f/ m: Q9 t
  33.                         uint8_t a[100]; //存放读取fifobuffer的数据
    7 N: i. [( S# T# B$ t/ j
  34.                         int i = pfifo->Counter;//先保存接收缓存的数据个数, N9 V  N/ Z0 q! h5 j7 @2 ~5 I
  35.                         FIFO_Get(pfifo, &a, pfifo->Counter);- a4 [6 f! Z4 s9 l3 P3 O
  36.                         HAL_UART_Transmit(&huart1, a, i, 200); //将接收的缓存数据再次发送,判断有无误码率
    7 ~1 L: Z& \/ V5 B/ @( H( `
  37.                 }* t! e0 k# W" ^& D" ]0 [, U
  38.   }
    4 q. f% P8 Y4 O1 x
  39. }
复制代码
: ~6 e0 b9 Y$ _; j
测试成功!可以在主函数对数据进行处理,不用担心缓存的覆盖!
4 h; f  y. U. [6 S' A; T6 _+ L) V. @2 T1 W
202109031459585.png

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
20210903150306628.png
+ d2 J+ N* ^4 a7 A) d% W
' E# {7 B1 J7 e. I2 r
20210903150316369.png
2 @# w+ h5 v- m$ g' [+ J5 t4 \  p

4 X6 D( [" Z0 V. D# ^ 最后,发现是在fifo_init 调用的指针,未赋地址。添加之后,解决了!
; N1 w, I. c2 z1 u/ c
  1. pfifo = &fifo;
复制代码
2 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
收藏 评论0 发布时间:2021-11-25 15:00

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版