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

【实测教程】STM32CubeMX-STM32L4之研究串口通信(DMA)

[复制链接]
STMCU小助手 发布时间:2023-1-15 00:07
一、开发板平台简介:7 s# q- n; J' C% \( y( x/ n
1、开发板资源简介
& C7 Z/ w, `  z" t7 i: Q, ~
(1)开发板主芯片型号:STM32L431RCT6
! ?6 n9 D2 B0 [& K+ R: F' a7 Y(2)开发板主芯片封装:LQFP-64_10x10x05P0 r0 S5 U6 I7 j( v+ b8 A
(3)开发板主芯片内核:ARM® Cortex®-M4
! y" ^* G6 n7 z& P: r1 N$ a9 h(4)开发板主芯片主频:80MHz
# n( I5 d0 n3 s3 L- p* U4 t(5)开发板主芯片Flash大小:256KB
$ X' O  O$ U8 G- h% r, C(6)开发板主芯片RAM大小:64KB$ C$ d. ^% r0 c7 d8 h% Q
(7)其他外设:请参考芯片手册
$ k2 v* I# C/ S& N( K
6 `. ~4 |4 k3 D
bb91345227434ee7a43a34bf3fe366e6.png 4 a& ]4 m5 @8 B7 D

' m( B% a5 ~4 x6 b
929c0cce04aa4115a8623703982bf3e1.png
" V& }) P4 s. y1 `6 d1 ]. v) Y. z3 @+ j1 r% ?/ L
2、串口简介
/ J2 C) V3 K. ~7 O4 n
         串口全称为串行通讯接口,即数据在通信线上一次传输一位,按先后一定顺序传输。我们通常所说的单片机串口准确来说应该是串行异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART),使用TTL电平,串口需要RXD、TXD、GND三根线进行通信。
/ Y2 U1 g/ s5 h" b+ |7 m. s5 a, V) K! y5 c" q2 F
        (1)我们选用的STM32L431RCT6开发板串口1已通过USB转TLL串口芯片CH340G引出,使用时,只需要用公对公USB线连接电脑即可(注意也得需要安装CH340G驱动),后期验证试验也使用该串口1进行。
  W6 \+ U4 T! ~% J7 }( [5 h; K  _: n
; X' P1 O! x& b; @        (2)开发板上的其他串口已通过排针引出,为TTL电平,通信的时候需要注意选择对应的电平模块,如USB转TTL串口模块等。
; V0 p  i8 {+ Y5 c2 V/ q8 E% ~0 Z
1 |! B, H* s$ k$ E, Y
  二、新建工程
: D# Q5 K, x7 g( y% }: A% [1、新建STM32CubeMX基础工程

6 i/ ]% W: S+ y5 g8 x! f(1)打开STM32CubeMX,点击“File”-->"New Project"
& Y- A+ q. U0 @" i3 V
5 p0 Y* _$ i6 k
2399170347904e959c855fefd5877f84.png % E$ E* d% ^' @: L% _; s/ T4 r& b

7 L# N- N3 G1 m5 u4 t, R(2)等待打开主芯片选项界面(大约1分钟时间)。' M- e# Q' n8 d8 L3 R% A1 T6 C. n9 c( ^

8 o* T2 F) }7 C# U$ j7 ^3 E/ ~
d74d2fdc60c9440483e2b7cf8d928e7f.png & N- W0 y# Q6 Z' R- P
- }7 _" \  ]# D2 P3 p: @

3 B! E- {7 V8 Q(3)昨天搜索框中输入(或选择)所需的主芯片型号(因为我们用的是STM32L431RCT6开发板,所以此处现在STM32L431RC),然后在右下角选择STM32L431RCTx(因为开发板主芯片是STM32L431RCT6),左键双击即可打开新建的项目。2 h! E* `1 {+ b' |0 ~% A4 d

3 j* \0 N1 A# p8 X( N. Y$ _
7b80345238d74bea82ce70e1a348f7b4.png 6 U+ B/ [+ T; q) m
" J4 `3 C7 ^! Q$ m" Q3 P, x
(4)选择时钟源。
1 ^0 x1 K8 J2 d9 }; b! N2 M(1)因为开发板上有8M外部时钟,此处选择外部高速时钟(HSE)。
/ B, Q7 Z. h- m9 b6 ]( {0 u(2)因为我们没有用到外部低速时钟(LSE),此处不做处理。
! e$ m4 T/ L6 A- M: `% M& T( h( L3 l- i3 Z# U1 E& {
72119b971f62410fa8344f7f9fb9f389.png : S8 m- s8 h9 m% r/ L

) ~& ^* l0 a$ K: p0 p0 F2、配置GPIO控制LED
; o( P- O) q4 }1 t5 r4 @+ }
备注:LED灯用来指示系统是否正常工作。" j- V$ e1 H! v
(1)查STM32L431RCT6开发板原理图得LED1控制引脚为PC0,则配置GPIO的引脚PC0。
: h2 {0 e/ r! Y' ~! b2 l. v% W+ i$ x  i鼠标左键点击PC0,选择“GPIO_Output”,表示设置该引脚为输出模式。
% F( A) o% T* Q! J
* }' y9 y# e- T% t' V
492907c1e71149819adbaee4516a2af4.png
9 |! a$ k6 a) x' F# Y6 f( h5 S' J0 J3 s3 z8 s
(2)根据自己的需求配置GPIO的参数,如输出方式、输出频率、上拉下拉等。因为GPIO控制LED的要求比较低,此处采用默认参数即可,不用修改。
( k2 y3 Z( b1 u3 i, d0 j1 M$ i0 c  p' G1 X* k1 s: `& i
38ff4b80e1c5495ba3076a5158fd91fa.png   |+ _9 f- u4 ~4 `- |  s
3 o# s4 r! K, q1 u: z
3、设置串口1参数8 j) T: p$ K( x
1、查原理图得知,串口0使用STM32L431RCT6引脚为PA9-USART1_TX,PA10-USART1_RX,引脚设置如下:
' ?. Q+ h# n) ~0 e6 L8 M3 ^/ z- M- C$ z
497b8ee0243e446784e64a3c31e8a26f.png , A. g- p/ T$ f5 u
9 a9 w$ D# I7 m0 S9 m! [8 r
(1)序号1用来设置串口收发引脚的选择。( l: q# p; M" C1 R& F6 E& n3 d+ @% P

2 a  I. Y1 b7 s) B3 W* I; c(2)序号2-3-4-5-6设置串口参数,如波特率115200、8位、NONE无奇偶校验等。% k: d0 O/ v0 L/ W9 _) f' b

. h: u5 ^- ~7 u0 `- u2、设置NVIC settings 使能接收中断
: }+ z, W4 `* j
3 k. ^! H1 E$ u( r  s7 H5 G
f9d7783b08304465815834f4d2095571.png
/ N3 x. g. i3 B5 Z+ |$ j2 t; v1 E/ G/ U
4、串口DMA设置

' k) f# ?5 m( U& E3 r+ F# S* L) a' C8 y8 @% M, Q
6d26b13dd9d34039a2b426ca47680f8c.png ! I% m4 A2 f, K' ~3 G. h/ F

# T, [/ a* ~; N& d% ^. H (1)根据DMA1通道预览可以得出,我们用的串口1的TX、RX分别为通道4、通道5:% Z3 i2 A! C% g% l/ q3 L
点击DMASettings 点击 Add 添加通道
* p% }8 `1 m& Q" a5 H选择USART_RX USART_TX 传输速率设置为中速& k9 S/ g, B6 h3 @
DMA传输模式为正常模式,即发送一次就结束。3 H8 ?2 h9 H0 k' ?" r
DMA内存地址自增,每次增加一个Byte(字节), ]- F* w8 \  F/ T: A: _

$ d- G5 B' u% X$ L* y/ S
976712e0494a4482bf65c69fc09fcabd.png 0 I& E% x! U3 A9 q6 X3 a+ y5 x% E  A

7 p6 q0 h0 H5 q9 s& f% F: l
: X* o8 b" o+ {8 J/ |! z
(2)DMA相关参数解析( U5 h0 o' @. m  I$ j9 y# m
2 n% \, U# b5 ?( K' Z
Dirction : DMA传输方向有四类
. E. B" W1 G" S  H$ i7 d" F外设到内存 Peripheral To Memory! n9 R" I  _: l3 w. L' c
内存到外设 Memory To Peripheral! ?% G& @0 v9 y: ]/ g
内存到内存 Memory To Memory
3 G1 r/ E2 f% M6 q外设到外设 Peripheral To Peripheral" Q9 B7 g+ j3 p, I5 C
Priority: DMA通信传输速度有四类
+ v7 m% U, ~! X( q, [) k" l- C最高优先级 Very Hight  R- F$ {5 K' r7 U% e9 u3 x
高优先级 Hight
' y# C/ e+ `+ O+ `+ K中等优先级 Medium* u/ ]: M2 \# g2 t4 O1 m- F
低优先级;Low4 a) \: O( Z& l6 u  `: a- f

7 T+ Z+ D$ W7 H1 C
Mode:DMA传输模式有两类0 s; [8 N- g# G  y- i6 u( l3 s

' j3 c# V' ^" L2 E7 }- ~
9021c11fed3e4c1885477e062b846258.png * j; c8 W3 z8 b6 F1 u+ b

: S  v' @* f) D# W6 i6 ]8 k* l

+ M$ ?& {. p: YNormal正常模式:当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次。
& _* `3 k7 {4 g: Z, cCircle循环模式:传输完成后又重新开始继续传输,不断循环永不停止。
) v5 ]' ^+ U$ m' }5 g9 G6 B8 p" r
0 J' c) z; q4 C; R4 }, w
Increment Address-DMA指针递增设置:  t' ~! c1 q& S3 F4 Z0 U$ ^% z

. K* P) |! A* }: w: t0 M9 P- r6 E+ @
2b1a952d6514444e9dbb019a9ae88c42.png
( Y/ u, H. O# |0 C( ~" A  d+ O: M' P% X+ `* I+ ]& o

9 b' ]  g5 n, o% `6 t# Y% q 5、配置项目工程参数/ ~0 z5 M& r! ]& v: j
(1)配置时钟树,用于系统内部时钟,以及各个外设时钟等。此处选择外部8M晶振作为主时钟频率,内部最大倍频80MHz。9 P: V0 f! e$ w+ u

, r" B  L3 w5 O9 L
2ce1933c10484d819234682f4abc0228.png - k# ^' \1 l) t
7 F$ A8 [% @& }  ]9 W$ j
(2)完成配置工程。/ T. v; O4 q: x
备注:需要注意代码生成过程中的继承关系,如图所示:需要保留开发者自己编写的代码时,请根据配置设置,不然生成代码后会删除自己编写的代码(从这个方面也可以看出开发者备份自己的代码是多么的重要。)$ K1 I0 [" q! ?# W: e
6 K. `- v+ r, [3 j/ [- j
efdb616174f54925b6eac31109f227b5.png
0 z* P: r' u) g4 t( S5 b% y" q' _& q
41c3f2716e4e4eda8f62fa3a1d871322.png
: t0 v1 c) v( A' q3 p2 M' u9 e- I  K* @6 ~6 a
(3)生成代码。7 n" Y% N. w, d3 l
& z/ }0 Y3 Y& ~2 G2 \
8eaa7d0babea40ee93f158481a6ee471.png
* s( b: g+ l+ l+ w
" N, e$ a, J0 k8 N4 L 三、在KEIL 5中编写代码
% I" I0 S/ g( y2 Z" W4 k/ E; Y& z2 S1、使用KEIL 5(MDK)打开项目工程文件

' T% }; W6 i' W# m( n(1)找到刚才新建工程的存储路径,安装项目名称,打开项目工程。* f$ Q/ ]1 E, K* ]4 H

& n; H/ z0 I& C8 B+ A: F. a1 S
9837b01954cc4d3ba3e25073f31b30b5.png
. I: t* q! }& b8 F/ `
1 N& H9 j6 a9 z+ j3 |5 B1 C2、添加LED指示灯作为系统提示
/ M) |3 o4 F# y- G添加每隔500ms,LED1闪烁一次的系统提示,用于提示程序运行正常。
- b( E$ z9 T! l/ t
" p0 d+ E  [( Y2 ^- `
6ab72ceaeb7a41af833842fe5ba6f34d.png
# i$ M" w7 @( k" o/ `" b& A" z9 @/ h% Y7 M" t7 o7 S
3、添加HAL库UART  DMA 发送函数代码
+ C- t8 J/ y- q3 P$ i(1)STM32 HAL函数库的串口DMA相关函数如下:5 E# A; J1 l  R, ?
  1. HAL_UART_Transmit();串口发送数据,使用超时管理机制
    2 Y& v2 K1 |; v0 ?, f9 V, z8 z# R
  2. HAL_UART_Receive();串口接收数据,使用超时管理机制- |/ d" g# ^3 D
  3. HAL_UART_Transmit_IT();串口中断模式发送
    $ R' D% i, w6 M% N+ F4 ~/ I
  4. HAL_UART_Receive_IT();串口中断模式接收4 ?3 K/ }# J. ]" Q/ J! R
  5. HAL_UART_Transmit_DMA();串口DMA模式发送7 ~' t$ }) m" \0 a! C- _7 }  C8 y/ `
  6. HAL_UART_Transmit_DMA();串口DMA模式接收3 V5 P( p% o  m9 v1 j
  7. HAL_UART_DMAPause() 暂停串口DMA
    # V% u8 X! t+ N4 l/ S8 H! W$ @& V
  8. HAL_UART_DMAResume(); 恢复串口DMA0 W9 I. U/ n5 N$ f- O
  9. HAL_UART_DMAStop(); 结束串口DMA
复制代码

/ e9 u# Z  ~5 |(2)添加串口DMA发送log代码:- H  z8 e( z7 x5 Q: V& H5 Z9 ]
  1. /* USER CODE BEGIN WHILE */) C: z: t; F2 v5 k5 G# d; l# o5 ]
  2.   while (1)
    0 }/ t1 {* d& J* W( w; z' w
  3.   {
    # s3 W8 R: z( U
  4.     /* USER CODE END WHILE */
    ; F$ @9 Q. G0 y9 \

  5. . s& r2 i# K4 R# q. _
  6.     /* USER CODE BEGIN 3 */
    ' B8 W( s3 L3 z7 Y
  7.             HAL_Delay(500);
    , M* k8 G- ?9 g* Z7 Q
  8.                 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);//控制LED1闪烁  y8 M% f! F5 L% S* G0 ~& T7 p* r
  9.                 HAL_UART_Transmit_DMA(&huart1, (uint8_t *)"hello world,this is usart dma send and receive...\r\n", sizeof("hello world,this is usart dma send and receive...\r\n"));//发送提示  
    ; v1 x" z- ^0 h. h0 Y1 d. r/ i
  10.         }4 a9 ]  T3 X" v5 S6 z
  11.   /* USER CODE END 3 */
复制代码

5 q: N" L) t' P3 `/ V4、添加HAL库UART  DMA 接收函数代码

& ^4 D; B* d7 O+ u(1)DMA接收设置前铺垫知识点:
. O3 i+ X, `! _+ k; ~2 g0 U        STM32的IDLE的中断产生条件:在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断停止。; M" X+ S7 o" y' G2 \

" ?* B% E2 c& L3 d# c& p(2)初始化中断接收配置:, m% |: R0 r2 L( }
uart.c添加代码如下:
, R: h  H9 v0 Y% B: Y7 ~1 z
  1. & I( z5 Q3 W$ K( i& Z
  2. /* USER CODE BEGIN 0 */
    4 H% Y$ k. v! T+ E( L: ^- A$ `" d

  3. + D, b3 Q& I( Q* S6 d$ [
  4. volatile uint8_t rx_len=0;                        //接收一帧数据的长度
    ( z) G5 C* C6 R, ?9 I% M5 |6 V
  5. volatile uint8_t recv_end_flag;            //接收一帧数据结束的标志位; L9 _5 G: P- g0 n
  6. uint8_t rx_buffer[100]={0};                        //接收一帧数据的数组大小
    9 ]! {+ M  ?) U' o! v
  7. /* USER CODE END 0 */
复制代码
  1. /* USART1 init function */2 y* C1 w; D0 o. J/ M, E2 ~  I% c' R
  2. " }, P( P% d. W0 ?1 G$ H' \2 L1 i
  3. void MX_USART1_UART_Init(void)
    # O% T! l: j7 n# F  ~
  4. {
    ( [) g. f. Z* \/ c: ]

  5. % `6 j* n7 e' h6 X: D2 C- ^
  6.   huart1.Instance = USART1;
    : D2 S+ F2 U. X: c9 C4 x
  7.   huart1.Init.BaudRate = 115200;
    ; H! M5 k1 O( d0 i9 ]# A6 W
  8.   huart1.Init.WordLength = UART_WORDLENGTH_8B;7 @9 C: P7 D* ?9 T+ I, j. Q
  9.   huart1.Init.StopBits = UART_STOPBITS_1;
    # q) _9 j6 M4 f
  10.   huart1.Init.Parity = UART_PARITY_NONE;  t' G" n, K! @* V
  11.   huart1.Init.Mode = UART_MODE_TX_RX;
    5 N0 o- [8 \1 |
  12.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    3 l1 i: W+ b: Q" c
  13.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    2 j) p! g( s, V
  14.   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    ) i: m5 I% S* \8 J/ c/ p
  15.   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;/ @1 U8 ?* e; a$ o8 M
  16.   if (HAL_UART_Init(&huart1) != HAL_OK)
    / S2 W3 o$ L6 Q0 h
  17.   {/ r& l; Y2 l! e3 n3 c+ M7 ~  N$ ?9 R
  18.     Error_Handler();
    3 o2 G( u) w, s# p  [
  19.   }. {% {6 ^% B+ Q8 j+ E/ x* U- d! B
  20.         /* USER CODE BEGIN 2 */" _7 H2 g. x5 p! Y, ]
  21.         ( ]* ^6 g. E( `- T
  22.                 __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);                     //使能IDLE中断3 F# ^# _6 s) h2 e+ V
  23.                 HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);            //DMA接收函数
    , K  u6 H* o* o) Z1 I
  24. & B5 `9 m! E# I% `/ s4 u+ t
  25.         /* USER CODE END 2 */
    . `: k! ~$ b# C4 u
  26.        
    5 x8 C' q( z" O

  27. 2 d1 G- C5 c) I8 f
  28. }
复制代码
/ {) g4 j' {' O. @' x
uart.h添加代码如下:
3 R, A: t' Z, x% {
  1. /* USER CODE BEGIN Private defines */0 E, g. g: W, I: T+ o/ J9 F
  2. extern UART_HandleTypeDef huart1;, n, d9 A( Z* X- Z* T8 N5 o
  3. extern DMA_HandleTypeDef hdma_usart1_rx;% O: z4 d& c" C  g: K
  4. extern DMA_HandleTypeDef hdma_usart1_tx;
    3 F6 |, [- A& ]1 [

  5. ) G/ u9 u& N: s! m+ a
  6. #define BUFFER_SIZE  100  
    4 v$ Z6 |3 h5 [
  7. extern  volatile uint8_t rx_len ;                                  //接收数据的长度! g+ I9 Z' t8 b
  8. extern volatile uint8_t recv_end_flag;                     //接收数据完成标志位" l7 q& m5 X0 [5 C# y! L  [* G
  9. extern uint8_t rx_buffer[100];                                  //接收数据存放数组
    6 V" e  ^6 g5 g& E8 D
  10. $ h$ U7 k; _1 N& j* k) d
  11. /* USER CODE END Private defines */
复制代码
* m, i; h3 y! R2 r
main.c添加代码如下:
  r6 a' e: T- L; G7 {
  1. /* Private includes ----------------------------------------------------------*/
      v& c6 H' O0 c# x$ @6 ~
  2. /* USER CODE BEGIN Includes */+ @( _4 G  Q; F8 w! b/ h) ?
  3. #include<string.h>                        //添加字符串头文件$ A8 f9 b2 V- f& f8 K0 v9 D
  4. /* USER CODE END Includes */9 C- b5 O2 }' j, k9 Y/ z$ n
  5. /* USER CODE BEGIN 0 */
    # _6 S4 |+ s& {& G) l+ t' {* ~
  6. /*******************************************
    , n( h& ]" D( x7 G; A/ Y9 ~* E+ F4 Z/ F
  7. *函数名:DMA_Usart_Send
    - t0 M8 H- O7 _  E
  8. *功能说明: 串口发送功能函数
    ' ~+ X* P3 @% Q, |
  9. *形  参: buf,len+ _" l' W$ ?! c6 l/ t) X2 x
  10. *返 回 值: 无
    7 y; b7 V3 W9 P* h& q- w& R% I
  11. ********************************************/$ A% B# S$ C+ q+ ?
  12. void DMA_Usart_Send(uint8_t *buf,uint8_t len)        / K2 T( n- ]% r8 N
  13. {
    + ?3 V! V* i1 I; _* D
  14. if(HAL_UART_Transmit_DMA(&huart1, buf,len)!= HAL_OK) //判断是否发送正常,如果出现异常则进入异常中断函数: [) w" ~" M1 a, U# l& t6 C
  15.   {" T0 t& o  N( q  d) d
  16.                         Error_Handler();                                                                                                                                //异常提醒8 ?' B6 j' }; r% ?! m9 ^, k/ a$ z: C
  17.   }; J, U( y* [4 f9 x; v% W2 ?# Z
  18. }- Y: s9 D/ a, e& E5 ?5 r) \" n
  19. /*******************************************
    " |& l. C! Q2 z; ^5 w' l+ x( `
  20. * 函 数 名: DMA_Usart1_Read
    ) s$ }  t; P/ L- G+ t0 a
  21. * 功能说明: 串口接收功能函数
    5 k9 H% S- a+ e$ d
  22. * 形  参: Data,len
    7 U* @; M6 U4 K- v; s  a
  23. * 返 回 值: 无
    8 y2 T1 z4 ~" i7 C
  24. ********************************************/
    ; z, ]. J) r' s
  25. void DMA_Usart1_Read(uint8_t *Data,uint8_t len)
    / q2 [, @! X# {  w
  26. {
    ( m3 ^1 t9 \. _  i0 ^+ ^! s) r9 ~
  27.                 HAL_UART_Receive_DMA(&huart1,Data,len);                                 //重新打开DMA接收: L$ f8 f) I) D  N) _
  28. }7 l7 v' s) }9 t) k- T( I+ N! X, ^
  29. /* USER CODE END 0 */
复制代码

3 |: v: w. }7 L% B  Ymain.c  while(1)循环中添加代码如下:
! `+ \! g$ s, b# r# D9 w2 b  h
  1. /* Infinite loop */
    2 t/ N* }1 f3 \' e
  2.   /* USER CODE BEGIN WHILE */
    # k9 @% k9 ]2 Y- s
  3.   while (1)4 m" T+ }# }7 X
  4.   {
    : b3 g: e. z- X2 M2 E; r6 u
  5.     /* USER CODE END WHILE */, b/ p, U3 H7 U0 f3 H1 _
  6. 2 c, G' z  Y- g5 @# |- u
  7.     /* USER CODE BEGIN 3 */2 w, K$ U6 \- x) S
  8.                        
    & R1 G8 q. S) P" t4 f
  9.         if(recv_end_flag == 1)                          //接收完成标志,如果串口有数据接收,则执行该部分& w- D/ U' y4 B6 c! p  j4 a
  10.         {, k5 U3 n7 g- c( s
  11.                 DMA_Usart_Send(rx_buffer, rx_len);& {" m1 k+ H* K! b0 F# ?* g: S: G( t
  12.                 HAL_Delay(200);
    $ Y& y8 A3 f5 l7 ?6 g5 N' S
  13.                 DMA_Usart_Send((uint8_t *)"\r\n", sizeof((uint8_t *)"\r\n"));       
    8 f7 E6 F5 U& w3 }5 t
  14.                 rx_len = 0;                                                 //清除计数
    4 U, K: r+ |6 ^* U8 h6 [
  15.                 recv_end_flag = 0;                                //清除接收结束标志位
    0 ?- z4 @1 H! E& H
  16.                 memset(rx_buffer,0,rx_len);( H, \$ x) }# t5 m. O
  17.         }
    + j1 ^7 b' i+ l# T$ v/ X- D1 i9 a
  18.         else                                                                //如果外部没有数据,则执行该部分) t8 z- d6 z) h" Y, u7 V" }( w. u
  19.         {0 f8 u3 x, ^& t: ^
  20.                 HAL_UART_Transmit_DMA(&huart1, (uint8_t *)"hello world,this is usart dma send and receive...\r\n", sizeof("hello world,this is usart dma send and receive...\r\n"));
    4 R3 b: a. I/ K3 _, }1 R
  21.                 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);                //控制LED1闪烁2 o" R2 t8 o+ a2 a2 ]* U
  22.                 HAL_Delay(500);) C% _: @0 j5 L; ^2 j; p4 M
  23.         }9 V2 O; ?' J( t
  24.         HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);       //重新打开DMA接收                                ) v( ]4 V& }2 Y# H2 I
  25.   }
      m4 d  w- \6 e" A- T( C/ E
  26.   /* USER CODE END 3 */
复制代码
4 U5 u% E0 P1 t. U8 H8 ^3 Z
stm32f1xx_it.c中添加代码如下:
: d% w% H8 I' F" y; @' e) F
  1. /* Private typedef -----------------------------------------------------------*/
    ; V; a8 `6 i  F- f
  2. /* USER CODE BEGIN TD */
    ) O+ c" G  C/ s2 \
  3. #include "usart.h"
    % W7 F5 |, a1 V9 i% k2 c
  4. /* USER CODE END TD */: }. V- T/ Z4 f
  5. & ?0 Z# j4 D. S( o: V- h
  6. /**! N3 t, e3 t+ b# k( ~! _5 s; A! [
  7.   * @brief This function handles USART1 global interrupt.- m" \+ [  w5 N$ Q* o+ o9 n
  8.   */
    0 i! j1 g0 W; T5 |
  9. void USART1_IRQHandler(void)! }. H4 `7 q% i) Q* u
  10. {
    7 H+ z  e8 w8 z% }6 i
  11.   /* USER CODE BEGIN USART1_IRQn 0 */
    2 Q/ l* w& G6 N) Z
  12.         uint32_t tmp_flag = 0;
    , ]: Q2 K6 N# `8 K' g' l% C7 |
  13.         uint32_t temp;
    & T# x3 W6 L$ N5 N3 P
  14.         tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位
    7 x. v3 A: d4 Y# m' t
  15.         if((tmp_flag != RESET))                                //idle标志被置位
    9 P: j  ?( Q. k5 d
  16.         { 1 J+ D1 T; ?6 E8 b- J; d" U9 k& f
  17.                 __HAL_UART_CLEAR_IDLEFLAG(&huart1);                //清除标志位
    2 o) S1 ~3 ~$ R& n+ c4 }
  18.                 HAL_UART_DMAStop(&huart1);     
    - N6 C8 T( a' r' U( _
  19.                 temp  =  __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);   // 获取DMA中未传输的数据个数   9 s5 A; h6 b! X  K% q' q- n( @7 m
  20.                 rx_len =  BUFFER_SIZE - temp;    //总计数减去未传输的数据个数,得到已经接收的数据个数
    ; D0 l0 K% _% ~' o
  21.                 recv_end_flag = 1;                                       // 接受完成标志位置1       
    $ Z7 w2 s7 P. a. u
  22.          }+ X4 B1 |4 o8 z# W
  23.   /* USER CODE END USART1_IRQn 0 */
    1 N2 B6 a: H. c: `5 c5 D. N5 F% j) m
  24.   HAL_UART_IRQHandler(&huart1);
    9 C$ W9 q8 c3 O" p$ z+ o
  25.   /* USER CODE BEGIN USART1_IRQn 1 */
    4 `' w, x* e- E3 U
  26. % m7 r, g. y3 d: Y% l
  27.   /* USER CODE END USART1_IRQn 1 */) @( u0 g2 h$ {- j+ N( W2 z  z
  28. }
复制代码

* z( _. V0 @6 L(3)至此,串口DMA收发数据需要添加的代码已经完成。
" \$ C3 M! ?' D5 }5 a9 S7 D
0 l, g1 V+ {  S# A" W5 }
5、设置编程仿真下载模式
! o5 u) W  C7 K* R8 O(1)选择Options for target ...>>Debug>>J-Link/J-JTRACE Cortex,点击Settings>>选择Port(SW),可以看到搜索成功SW Device,表示芯片可用,可以下载。* W% f" j, J* g
. Z% g9 @8 }) j7 x2 e, ~+ r
edefb6b9a2a14be3b1221ad6d5c7a8a2.png 7 w( }2 d/ F" N9 ?5 U5 [
3 {4 z; D; |0 J4 g' q' v/ Y
(2)点击编译,完成后提示“0 error(s),0 warning(s)”。8 f- I( N. I9 P/ k, f- v; m( \$ p2 b

& q7 J( q" f. j# S) c
f0ed816a3ed14487bf9e857c317fc99b.png - o" |" n" |2 T' [6 n

* y3 V' y0 m# E% I3 P5 y  m(3)点击Download(或者快捷键F8),即可下载程序。8 H- M" M6 t/ R! ^/ p& R
* W1 ^7 Z. P' k1 T2 a: u% V* r$ i
ba221842d5db40808aa129dd83c593d0.png # W$ m2 ~- @6 X* m

6 j6 I; k% ]+ h(3) 如果下载程序后,没有看到LED1灯闪烁,可以按下述方式设置一下(Reset and run表示下载后自动复位和重启运行)。或者重新彻底断电再次上电(或按开发板的Reset按键复位MCU即可)。
3 p1 j2 a. m- s  F! W! G2 H
9 a. ]5 B; h1 Z- D
9f8aa1a4e8f04041bcf5cb183facd100.png
) }+ n+ `% k, d3 a2 B' Y8 X* y( p% s& I' }4 _7 Q. I
4、查看串口发送函数打印log效果, A) y& a" W$ o$ d
(1)设置串口助手参数为:115200、NONE、8、 1(和代码中串口初始化参数一致)。
! f  e. f2 ~) K
, P: ]2 u  a4 p6 h: i4 R+ }(2)设置成功后,就可以看到串口打印的效果。如果串口助手没有发送给MCU的数据,则MCU每隔500ms闪烁LED1指示灯一次,且串口输出一个log。
/ N6 }5 J2 r# H0 e( v/ z4 n8 u$ v5 ~9 o& w7 ?' B% K
(3)如果串口助手往MCU发送数据,MCU把接收到的数据发送到串口助手进行打印显示。
/ B9 d5 v) r3 g7 S) A* J( R& p4 Z/ n6 m+ s8 U! e
16cd1063057845399adc6f45e25a20c7.png " m' s8 @' {, l, }

/ K2 k6 W/ u7 C0 H  e————————————————, w- D; C  V8 G; i# x
版权声明:智能小屋ZYXC
0 U+ h. ]: A2 s8 s7 u
. T% B+ E' d! Z5 m, `/ ^; h' n: X8 V' ^" i2 S# l) x; o$ F
收藏 评论0 发布时间:2023-1-15 00:07

举报

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