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

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

[复制链接]
STMCU小助手 发布时间:2023-1-15 00:07
一、开发板平台简介:8 ]+ I$ B# \! Z! w2 z- X  {
1、开发板资源简介
7 K4 K- t& N2 g0 P- `8 A1 |/ I
(1)开发板主芯片型号:STM32L431RCT6; b6 `& ?9 J5 q' _% H
(2)开发板主芯片封装:LQFP-64_10x10x05P
' C# g! O) G( ^0 i4 L3 b) q! c9 a(3)开发板主芯片内核:ARM® Cortex®-M4
: _& S& v6 G$ x1 T% F5 o(4)开发板主芯片主频:80MHz4 ]& s" O: I' D' J
(5)开发板主芯片Flash大小:256KB/ T0 ~9 P# h* c, z" A! t0 l6 y/ K* q$ A
(6)开发板主芯片RAM大小:64KB% Y8 H' L: O; z) n
(7)其他外设:请参考芯片手册7 g- o/ g4 B3 _& D, h5 O
8 A+ i: O6 G8 a) W, r) z5 A! ?& Q
bb91345227434ee7a43a34bf3fe366e6.png
+ w- M- s; |4 m) j+ `2 s8 \
& F% f: l$ ?# h* _6 B+ M% V6 }! _/ W
929c0cce04aa4115a8623703982bf3e1.png ' Q/ @, ~* @3 Q0 o( K
7 @! r* Y: T/ l- v, x6 D0 F
2、串口简介

; K) b; h3 v* k; l% q& f         串口全称为串行通讯接口,即数据在通信线上一次传输一位,按先后一定顺序传输。我们通常所说的单片机串口准确来说应该是串行异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART),使用TTL电平,串口需要RXD、TXD、GND三根线进行通信。7 W! A" F! T* G% A& w

5 J* ^0 o6 U0 G        (1)我们选用的STM32L431RCT6开发板串口1已通过USB转TLL串口芯片CH340G引出,使用时,只需要用公对公USB线连接电脑即可(注意也得需要安装CH340G驱动),后期验证试验也使用该串口1进行。
5 W* g9 R- Y4 w' u4 [( e; |: K- {' G' U$ Q
        (2)开发板上的其他串口已通过排针引出,为TTL电平,通信的时候需要注意选择对应的电平模块,如USB转TTL串口模块等。% ?0 I8 L% D2 k. D
$ Y# p7 }  p: a' B

! F6 K. l! t- R5 w" e  二、新建工程
: u$ O% G" ?$ z9 u; e1、新建STM32CubeMX基础工程
+ h% _0 D: d5 u) D4 x. x
(1)打开STM32CubeMX,点击“File”-->"New Project"; n) H. i, {, C6 a0 c: K4 h9 l
6 Z, V. e# _0 m$ j
2399170347904e959c855fefd5877f84.png * Q" f+ B# M. A3 u! h6 r0 ]
( q5 ^/ Q8 b" X$ q1 H0 w- V- I
(2)等待打开主芯片选项界面(大约1分钟时间)。
# ]) ?0 j4 r- w. M5 s! i9 f+ V& Y6 o: ^7 L- l0 p( x
d74d2fdc60c9440483e2b7cf8d928e7f.png
/ L  C/ S8 `) r" f& L
3 w% k  D2 g8 s# u$ V, ~* ?

, u+ n! I1 E9 @(3)昨天搜索框中输入(或选择)所需的主芯片型号(因为我们用的是STM32L431RCT6开发板,所以此处现在STM32L431RC),然后在右下角选择STM32L431RCTx(因为开发板主芯片是STM32L431RCT6),左键双击即可打开新建的项目。% |$ k) z) x2 N9 o! y* w2 @! Y
3 }5 Z# o: v4 L9 L: u4 P
7b80345238d74bea82ce70e1a348f7b4.png
& C2 M1 X) Q# i, Z# x- X* F
' r& X2 N7 z& V, D# {(4)选择时钟源。
  [, v. Q  Y* a(1)因为开发板上有8M外部时钟,此处选择外部高速时钟(HSE)。6 A: P3 v0 Z3 u! x7 g! `) _
(2)因为我们没有用到外部低速时钟(LSE),此处不做处理。
! g, j' A, W! T: [0 ?5 O) p8 _) A# F
72119b971f62410fa8344f7f9fb9f389.png
# ~4 r: A, b9 D. h8 V3 ^: A/ y
8 Q" _) ~( N; f  A& z4 }
2、配置GPIO控制LED
5 e3 r" ^4 g, O
备注:LED灯用来指示系统是否正常工作。1 I5 k' K% u! U) s7 n3 R
(1)查STM32L431RCT6开发板原理图得LED1控制引脚为PC0,则配置GPIO的引脚PC0。: z* e. e9 ^6 v4 m% j3 R
鼠标左键点击PC0,选择“GPIO_Output”,表示设置该引脚为输出模式。
  X9 |' f' S: B4 `3 V" Q5 Q3 {3 S5 e7 J9 w+ j1 ^
492907c1e71149819adbaee4516a2af4.png
' c+ t9 R+ Z' U6 ~  I5 i: V
0 A" L" F- I$ [/ l% o* y; g(2)根据自己的需求配置GPIO的参数,如输出方式、输出频率、上拉下拉等。因为GPIO控制LED的要求比较低,此处采用默认参数即可,不用修改。; P# ?4 q1 G, z- D, R  ]1 @6 Z

% n, a3 W% E  ~4 H 38ff4b80e1c5495ba3076a5158fd91fa.png % Q& A( a1 |* L, J% Z
7 \% c; V! Q/ R" {$ A
3、设置串口1参数
, _) @' r$ t# E: B& Z6 }1、查原理图得知,串口0使用STM32L431RCT6引脚为PA9-USART1_TX,PA10-USART1_RX,引脚设置如下:$ A, f" d/ [9 w. o. F) k5 l

" l* I7 ^0 P6 C# Q2 N$ [) d
497b8ee0243e446784e64a3c31e8a26f.png
* R9 |3 ]) a& D' r9 y

! j; U+ _: {' Z  x (1)序号1用来设置串口收发引脚的选择。
6 o+ B+ I0 \! U( n2 D5 {, A
" |9 x5 ~. H, J. S- V/ H
(2)序号2-3-4-5-6设置串口参数,如波特率115200、8位、NONE无奇偶校验等。
- m1 O3 O( r# h  A6 {) `6 _

3 T/ q* A/ x1 g% n. M' K* T) d2、设置NVIC settings 使能接收中断
, f# m) i2 o9 P2 y+ E! t7 V
, `( N: y, i- x4 G; i
f9d7783b08304465815834f4d2095571.png
2 o9 k7 P& `5 x; U, X; l% }1 u  D
2 n$ d$ E" P" F& U& U4、串口DMA设置

6 M  K9 _4 r3 n5 c8 p$ X& x4 p; G% V4 H$ D9 A7 D2 U
6d26b13dd9d34039a2b426ca47680f8c.png
) \1 }' Y  p/ V, w5 N/ |
7 @3 }: v1 b+ }+ K8 ]8 n0 X (1)根据DMA1通道预览可以得出,我们用的串口1的TX、RX分别为通道4、通道5:. c7 Y) g; D9 q8 o# F/ ^0 y
点击DMASettings 点击 Add 添加通道1 k& O. j( b" L8 I) Y2 J( p
选择USART_RX USART_TX 传输速率设置为中速' H$ g8 n3 ~" \- J, \5 M
DMA传输模式为正常模式,即发送一次就结束。
( @/ ?2 W! l2 ?) a" d( ]; T* FDMA内存地址自增,每次增加一个Byte(字节)* K6 F* e2 A7 F2 Z9 q! f& h7 [

7 u0 `0 r' A) Y. n7 Y: i
976712e0494a4482bf65c69fc09fcabd.png
2 P2 F5 f( t7 f$ D. }/ {( {. v/ r' `$ n& y6 o3 K; @1 f

+ j6 }6 h# o0 E( R4 W! P4 j(2)DMA相关参数解析, U3 y; j: R8 E2 B( {( E

( o7 u/ Y( Y" d2 H! A8 ?; TDirction : DMA传输方向有四类3 w% z: O- N! [/ x! R; G
外设到内存 Peripheral To Memory
) C* x3 w# L$ f3 Z1 i( f6 `6 H内存到外设 Memory To Peripheral
# v3 a) ]: z1 T! o, x+ m内存到内存 Memory To Memory) k/ W6 N# q. w6 a' S  N
外设到外设 Peripheral To Peripheral6 _; V+ ?5 O/ @) B' i) ~
Priority: DMA通信传输速度有四类
) a1 j/ w" i0 n最高优先级 Very Hight
: U0 ?( g8 X9 _高优先级 Hight& d- |7 ?5 [( v' d# n- Y# ^! M9 B
中等优先级 Medium
7 G% W: |" T  `0 k# d& o+ c低优先级;Low& J6 I) {! V3 Z. y! _& f* [8 `

8 I" _( y5 E7 u% ^/ \
Mode:DMA传输模式有两类# Z. l, G; m! A) C, p3 }

& s- ?$ W7 R8 \( c9 ?! ?6 g
9021c11fed3e4c1885477e062b846258.png
0 z! h- J7 N- e0 F% Y- d, I- y! ^- e! V' P' Q4 C- `* L

+ Q9 r) c& ?) O/ RNormal正常模式:当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次。
1 D% b4 I5 T) G+ zCircle循环模式:传输完成后又重新开始继续传输,不断循环永不停止。9 N* h7 [' X; w6 y! o7 c

* }* W2 ~% Z+ y8 S! g# r8 M
Increment Address-DMA指针递增设置:
. S1 s3 C; l1 L+ [4 J3 o0 ^" O) I: D0 X2 E- {! Q7 X/ d
2b1a952d6514444e9dbb019a9ae88c42.png
7 p2 d8 ^2 c- h: H- C. \! K# r0 b" O5 U8 X& |/ _) n: J
* ^! R7 p. r. P2 o' T
5、配置项目工程参数
; b- P- Y+ h2 ^(1)配置时钟树,用于系统内部时钟,以及各个外设时钟等。此处选择外部8M晶振作为主时钟频率,内部最大倍频80MHz。& ~9 ]# n* b  |/ ~
8 m6 _# u3 P. N/ ~+ X2 M$ q: ]
2ce1933c10484d819234682f4abc0228.png # Z# L0 |" [9 u  ^& Y/ S

8 h$ ]& ?3 ?/ q( u  k( m1 w/ N(2)完成配置工程。( P& U+ n3 E$ M- p
备注:需要注意代码生成过程中的继承关系,如图所示:需要保留开发者自己编写的代码时,请根据配置设置,不然生成代码后会删除自己编写的代码(从这个方面也可以看出开发者备份自己的代码是多么的重要。)& m; W9 e3 h  W( v- o
* @8 i' H. N6 e* }. O! V: o  t
efdb616174f54925b6eac31109f227b5.png
  h& c; j) H2 T- s2 _6 H! w4 ]% l
- v2 ^8 @9 J- b1 t
41c3f2716e4e4eda8f62fa3a1d871322.png
; r6 B: e  [& V* |5 v1 e: k2 U0 b  j& a5 e$ p8 W  n' \
(3)生成代码。. v9 r% w* @* h' q/ T4 p% f  p0 B

1 U, e/ |& q% J; h; x
8eaa7d0babea40ee93f158481a6ee471.png
: z2 f' M) P- R6 w% k; _7 N. F4 Y/ H: n9 V5 l
三、在KEIL 5中编写代码+ ~$ ]/ P8 k, O( C7 x
1、使用KEIL 5(MDK)打开项目工程文件

3 _" `; ^" m. ^' d' c. ^9 k(1)找到刚才新建工程的存储路径,安装项目名称,打开项目工程。
0 k, P% I0 t. {$ B+ M& q) [5 J1 C0 _! d6 V: l$ _- }8 ?2 A
9837b01954cc4d3ba3e25073f31b30b5.png   h' ^0 l3 h- {$ A! h# v& F
8 w9 R0 V! g# |* ?
2、添加LED指示灯作为系统提示( B+ r6 k3 x# @& e+ O7 s: u" v
添加每隔500ms,LED1闪烁一次的系统提示,用于提示程序运行正常。
$ w$ o8 }" p9 i: W3 `+ n% M$ H* c. v1 H' z$ }( |
6ab72ceaeb7a41af833842fe5ba6f34d.png
+ y2 B) o' m) y% O- s$ V" A4 Z4 U6 ]0 p2 H4 s' a, I+ W# A
3、添加HAL库UART  DMA 发送函数代码1 f7 r$ P0 B  ^
(1)STM32 HAL函数库的串口DMA相关函数如下:
" w0 e5 V0 d5 ]7 r8 M
  1. HAL_UART_Transmit();串口发送数据,使用超时管理机制
      P+ F) T" c7 U  \# O* f: n8 i
  2. HAL_UART_Receive();串口接收数据,使用超时管理机制0 p# g8 }  ?' F1 H9 D
  3. HAL_UART_Transmit_IT();串口中断模式发送
      b2 m6 @0 h% p5 k. }
  4. HAL_UART_Receive_IT();串口中断模式接收0 L, O% N3 k+ a
  5. HAL_UART_Transmit_DMA();串口DMA模式发送
    8 C# T' _& P( F& x
  6. HAL_UART_Transmit_DMA();串口DMA模式接收
    3 s. e" u# E! a$ j8 }
  7. HAL_UART_DMAPause() 暂停串口DMA
    3 M2 |, b$ O9 g' b6 B- N
  8. HAL_UART_DMAResume(); 恢复串口DMA
    3 A7 Q8 R1 H- M7 r( I) n6 {
  9. HAL_UART_DMAStop(); 结束串口DMA
复制代码

0 ~9 E! T5 B3 z1 k  E(2)添加串口DMA发送log代码:1 M8 O$ x' \" S. @6 q: q7 H
  1. /* USER CODE BEGIN WHILE */
    % K/ s5 [! a. c1 X% E! H
  2.   while (1)
    , _4 O" k5 M1 W3 b3 t* R
  3.   {3 j' d8 V8 ?" e% t% l' n3 b) }) e
  4.     /* USER CODE END WHILE */3 x5 ^( T, R3 w2 E" c$ P

  5. 7 E0 Y  [0 N8 [+ l( t+ f4 v5 @
  6.     /* USER CODE BEGIN 3 */
    5 j- b1 ?( W0 Z" r  b
  7.             HAL_Delay(500);! O- a6 e9 I2 C
  8.                 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);//控制LED1闪烁6 \/ o& s/ c( Y1 O( J2 K0 t
  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"));//发送提示  
    2 ?! i8 z. W$ B( k. b6 U
  10.         }( w. b3 {, d4 c0 G# t- k9 T
  11.   /* USER CODE END 3 */
复制代码

# W. ?- C; E. I& N- S; ]6 M9 |" Y4、添加HAL库UART  DMA 接收函数代码

! _( V  c) n- N" M& e$ K, K  T(1)DMA接收设置前铺垫知识点:  I8 _( [' Q) V' ^8 i
        STM32的IDLE的中断产生条件:在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断停止。. ^; S" X2 B% h4 _

8 V7 I1 f/ s- G( f) G(2)初始化中断接收配置:
/ T; A3 V6 w1 _) P5 }# l# e/ q; `uart.c添加代码如下:" O4 {* I# |. [- A4 S! {
  1. 6 ~$ R0 k- m/ T# m$ Z
  2. /* USER CODE BEGIN 0 */
    * J- D" p, ^5 `2 _; v; d1 J
  3. 4 z, Q# o' X, ^. H" ~+ T! A
  4. volatile uint8_t rx_len=0;                        //接收一帧数据的长度& n. d6 K; H2 {% p- q
  5. volatile uint8_t recv_end_flag;            //接收一帧数据结束的标志位
    + ~/ ~, M- o& }* K5 O
  6. uint8_t rx_buffer[100]={0};                        //接收一帧数据的数组大小* h/ l7 t* I8 E# T* ?
  7. /* USER CODE END 0 */
复制代码
  1. /* USART1 init function */
    $ @" W* O) B/ l& M% M) ?
  2. 7 L- ~- s" ?% f3 w" q- U
  3. void MX_USART1_UART_Init(void)
    0 ]( A8 k% d1 @/ d0 o
  4. {
    , G0 c, B+ Y# _" {1 z
  5. $ l5 K9 s; |4 I3 C  z
  6.   huart1.Instance = USART1;' ]( e9 W& g$ ?2 ~
  7.   huart1.Init.BaudRate = 115200;0 a( ^! ~, r3 Y- ^0 c' Q! m
  8.   huart1.Init.WordLength = UART_WORDLENGTH_8B;
    0 K9 e/ o1 p. x* n' T
  9.   huart1.Init.StopBits = UART_STOPBITS_1;/ x1 k! _% I0 D- e* P
  10.   huart1.Init.Parity = UART_PARITY_NONE;3 M# |: e6 ?( v  }
  11.   huart1.Init.Mode = UART_MODE_TX_RX;: b; A2 M- Q2 Z( k- M7 I/ ^: \
  12.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    0 E3 G) q( p0 |; y: ?8 H0 f# A
  13.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    $ |( j) U, `1 ~- q/ Q
  14.   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;4 j6 t% ^1 @% y: f  w9 m9 N, w( e
  15.   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    4 J4 p( s' R5 j. e! j& l( ?
  16.   if (HAL_UART_Init(&huart1) != HAL_OK)7 I3 _$ z: h$ r; X
  17.   {
    ) {) Y( o( @/ p! k
  18.     Error_Handler();
    / Q* N+ D6 |! m5 p; P
  19.   }; S0 _" g* p% e4 o) N& s
  20.         /* USER CODE BEGIN 2 */
    ( {  B6 b9 W8 N% ?
  21.        
    - K+ A) ?/ ?9 [( A
  22.                 __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);                     //使能IDLE中断9 K1 ?  x8 B3 j
  23.                 HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);            //DMA接收函数3 O; D$ U! _; z

  24. ( A+ E7 d, I, s% d' R' D
  25.         /* USER CODE END 2 */# [3 A0 d, |1 i
  26.         3 G5 |( z, B. V, Q' r" R- _7 g

  27. ; c7 q" g" a9 Y
  28. }
复制代码

9 R; K$ m/ z1 q% uuart.h添加代码如下:
8 |  ^& r; E* X6 I3 V
  1. /* USER CODE BEGIN Private defines */
    + T  S  t  F/ c& z2 z
  2. extern UART_HandleTypeDef huart1;- Y5 ?, L# r, H, B! O4 d* b
  3. extern DMA_HandleTypeDef hdma_usart1_rx;
    8 X5 b. ], h- {- B
  4. extern DMA_HandleTypeDef hdma_usart1_tx;
    7 Q6 Y- `1 |$ i. @: x( l

  5. # v0 @6 ^- L. G0 ]* r9 ?
  6. #define BUFFER_SIZE  100  
    + [* j  F, Z# E2 F7 S: j% J8 d" c
  7. extern  volatile uint8_t rx_len ;                                  //接收数据的长度+ o" b; q; u( j# ]7 P$ _
  8. extern volatile uint8_t recv_end_flag;                     //接收数据完成标志位1 ?% [- X- `* i. c7 Z0 v2 q6 v. b
  9. extern uint8_t rx_buffer[100];                                  //接收数据存放数组
    / E& D5 E) U. G& m

  10. : [6 f8 J8 S4 a
  11. /* USER CODE END Private defines */
复制代码

7 N. S) E6 C8 {* L& r# P) W; Kmain.c添加代码如下:
' D' ]; S( G3 W
  1. /* Private includes ----------------------------------------------------------*/5 y8 s5 o) t9 m6 n3 K! H7 @
  2. /* USER CODE BEGIN Includes */7 R! a+ R  W# K
  3. #include<string.h>                        //添加字符串头文件
    7 D9 x) ~+ Z) M0 ]* J! ~. p. V
  4. /* USER CODE END Includes */" H7 z5 a$ ?# I4 [7 A
  5. /* USER CODE BEGIN 0 */
    $ E1 ]6 q5 c* [  v8 W* I1 b, J
  6. /*******************************************' a* l; i) X. |' g, L6 d- D
  7. *函数名:DMA_Usart_Send
    ) p$ A5 v3 ^( E; g
  8. *功能说明: 串口发送功能函数/ J4 B+ d/ ~) P8 P1 L
  9. *形  参: buf,len
    9 y9 {: _/ k0 s, Z- P; u
  10. *返 回 值: 无6 K, Q1 d" ~* ^. ^
  11. ********************************************/# Z) P  o: j: G& c! m
  12. void DMA_Usart_Send(uint8_t *buf,uint8_t len)        ; n6 I# p; ?# `
  13. {. g, f! }7 e" k* {
  14. if(HAL_UART_Transmit_DMA(&huart1, buf,len)!= HAL_OK) //判断是否发送正常,如果出现异常则进入异常中断函数
    ' U. P: N$ b4 Q: ^& ^3 N
  15.   {$ e- v3 ], k6 X  f& \: x/ j! g5 w
  16.                         Error_Handler();                                                                                                                                //异常提醒9 G( }% t$ h& u
  17.   }
    * ~) j8 \; `/ j% @
  18. }( P- H( z- V- J2 O2 V
  19. /*******************************************. n! c; j7 ^5 U7 d
  20. * 函 数 名: DMA_Usart1_Read
    7 o# u  z% _  D# W1 M
  21. * 功能说明: 串口接收功能函数; X2 n- `( B, j* M5 o! F
  22. * 形  参: Data,len6 N7 Y! j0 S$ r& N1 y3 W/ R
  23. * 返 回 值: 无
    , c0 k/ ^9 @8 m% E
  24. ********************************************/, c9 d0 M2 W( m5 L% l% ~
  25. void DMA_Usart1_Read(uint8_t *Data,uint8_t len)
    5 L( n' }3 V" H- |; w0 K. A
  26. {3 {2 }4 D. c0 z. D! S/ s, r
  27.                 HAL_UART_Receive_DMA(&huart1,Data,len);                                 //重新打开DMA接收
    4 H! e' H6 a# K
  28. }
    % L# O$ Y8 W- l; C& c
  29. /* USER CODE END 0 */
复制代码
' E, A/ R0 k; z
main.c  while(1)循环中添加代码如下:
; I6 {9 R' d) z2 q1 U- g; k$ Z
  1. /* Infinite loop */9 Y4 u$ ^, ~6 O0 T
  2.   /* USER CODE BEGIN WHILE */1 [' C. g2 c3 T, h+ c
  3.   while (1)) N* ^4 Z2 {' T5 m) I: C
  4.   {1 P) M. y0 Y2 M1 P0 A, F" v  q' C
  5.     /* USER CODE END WHILE */
    3 n+ F) L& O* x- h4 _4 I8 u
  6. 1 i1 w- a5 i1 i$ B7 y# |( [
  7.     /* USER CODE BEGIN 3 */' [( o" r6 o9 ]- N  t% i7 c
  8.                        
    ' T8 l( A5 Q7 l1 h5 O& R* A
  9.         if(recv_end_flag == 1)                          //接收完成标志,如果串口有数据接收,则执行该部分
    8 l/ X$ {! Q3 h. G9 z, @! b
  10.         {
    . P' c- ]% v: N8 n
  11.                 DMA_Usart_Send(rx_buffer, rx_len);/ R( D& a% l; O% ~+ _# i; P; L  Q
  12.                 HAL_Delay(200);( S7 N! Y1 ]% P$ {& _% S# S
  13.                 DMA_Usart_Send((uint8_t *)"\r\n", sizeof((uint8_t *)"\r\n"));        & }/ F" a/ \5 k8 p6 P
  14.                 rx_len = 0;                                                 //清除计数
    6 v6 K0 E. k5 f7 O( h
  15.                 recv_end_flag = 0;                                //清除接收结束标志位5 {/ F, _; n5 s4 t
  16.                 memset(rx_buffer,0,rx_len);
    / B' a1 {( L* h- G' m# @
  17.         }5 `0 f; Y. F" j- h2 ^2 ~% e( ~2 f& z8 U
  18.         else                                                                //如果外部没有数据,则执行该部分7 I' ?% g0 a1 ]
  19.         {
    3 U/ P& `, w% m/ j/ C/ V$ j
  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"));
    + M5 X: T9 C" j% R% s* F
  21.                 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);                //控制LED1闪烁8 k. b( C. Y; I" P
  22.                 HAL_Delay(500);
    ( l# I% r' p- j! ^
  23.         }
    9 R; w% i6 j) t; W1 w1 M9 D. ~
  24.         HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);       //重新打开DMA接收                               
    6 S3 e& l- O: E
  25.   }
    + E) d- @+ A# n
  26.   /* USER CODE END 3 */
复制代码
7 X/ a6 C5 T- G! |) ^4 h$ e+ E
stm32f1xx_it.c中添加代码如下:
# d/ F  m: X* \) t8 {3 l
  1. /* Private typedef -----------------------------------------------------------*/
    / G  I. M9 S. i
  2. /* USER CODE BEGIN TD */
    " e% E; A: p1 K* E2 p* U1 R
  3. #include "usart.h"
    4 a* t! C$ \, f
  4. /* USER CODE END TD */
    + J2 B! l( ^2 B8 Q/ w

  5. ) o* w5 ^% L$ W4 E
  6. /**% x% o+ G0 r5 {' a; Z$ s+ J% `
  7.   * @brief This function handles USART1 global interrupt.' y7 h; K) s& _& t
  8.   */8 h5 _; X1 E" S8 t
  9. void USART1_IRQHandler(void)8 q, H- P& R5 E- b4 v
  10. {
    0 D6 I1 I9 H7 C( \
  11.   /* USER CODE BEGIN USART1_IRQn 0 */7 Z! J4 T" {" g( y
  12.         uint32_t tmp_flag = 0;
    2 s* X7 B/ h+ Q# o- ]# _6 R
  13.         uint32_t temp;
    / j3 B/ `- V+ @/ V3 Z' z3 y- @
  14.         tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位
    % b2 ^" `. A2 m5 R1 {
  15.         if((tmp_flag != RESET))                                //idle标志被置位
    ' i" Y, S% Q* q) E
  16.         { 0 ?$ `; c0 D1 {- q. d# u
  17.                 __HAL_UART_CLEAR_IDLEFLAG(&huart1);                //清除标志位
    7 L0 V- G1 R; W' P- q8 g6 B/ ?; E
  18.                 HAL_UART_DMAStop(&huart1);     * E4 T3 u3 q* W' Z6 P9 I
  19.                 temp  =  __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);   // 获取DMA中未传输的数据个数   
    " ]' E* h. K0 f2 C' j& a% `! }
  20.                 rx_len =  BUFFER_SIZE - temp;    //总计数减去未传输的数据个数,得到已经接收的数据个数/ U: v- R: K( S" B" [$ s6 B- f) l. H; u
  21.                 recv_end_flag = 1;                                       // 接受完成标志位置1       
    - ~5 y  [) a. Q* h( b3 k6 b1 X, |, H
  22.          }' M& Q. S5 Z4 b* Z% J) A4 A% c
  23.   /* USER CODE END USART1_IRQn 0 */" E5 k1 Y2 d. a$ E0 d7 {- l% B
  24.   HAL_UART_IRQHandler(&huart1);
    9 ?8 G4 {9 [# u- S; d3 m) c
  25.   /* USER CODE BEGIN USART1_IRQn 1 */5 G; _. x9 @/ C* x# w* E

  26.   [8 Z1 _. N3 r% f
  27.   /* USER CODE END USART1_IRQn 1 */
    5 f1 m/ q3 w1 ~: @* D4 F
  28. }
复制代码
4 \; X7 i2 b# e- v6 g, w
(3)至此,串口DMA收发数据需要添加的代码已经完成。
0 H; u6 g+ b1 R: i) f5 f  ~
! w5 f8 F2 m/ h6 w2 ?  \4 d
5、设置编程仿真下载模式
& R3 i; p1 O- h. f! E% b(1)选择Options for target ...>>Debug>>J-Link/J-JTRACE Cortex,点击Settings>>选择Port(SW),可以看到搜索成功SW Device,表示芯片可用,可以下载。
" J4 T# A$ m, u8 F# v  E+ ~9 ]
& F1 X# b* N- o+ b7 X, j3 H: T) }
edefb6b9a2a14be3b1221ad6d5c7a8a2.png
0 s6 ~6 i6 U  {. r7 J; ?0 R; Y: Y0 L$ \+ k: o0 T( T  P
(2)点击编译,完成后提示“0 error(s),0 warning(s)”。( e4 V& \) A$ X
- t% ]/ z' ^- I3 }3 N( D
f0ed816a3ed14487bf9e857c317fc99b.png 4 {1 T! X5 g2 C2 V; ]1 ~
0 {" ?+ R# I2 o8 J
(3)点击Download(或者快捷键F8),即可下载程序。
6 g& N' i  Z: ^3 M1 @' Z4 c. g9 }6 p; u. z. X
ba221842d5db40808aa129dd83c593d0.png 1 v- a( Y. ]  l; X% h0 _8 E3 j

, H3 g* M9 k! X3 x. o" W# n. p3 J(3) 如果下载程序后,没有看到LED1灯闪烁,可以按下述方式设置一下(Reset and run表示下载后自动复位和重启运行)。或者重新彻底断电再次上电(或按开发板的Reset按键复位MCU即可)。
7 ?1 e8 R2 }0 X* v- A2 ~6 D9 f2 `' F) r/ i4 T/ a# ^0 @1 d
9f8aa1a4e8f04041bcf5cb183facd100.png
5 b0 [5 D$ N+ Q/ Y$ l% P7 G5 W6 [2 Q1 ?' S6 X. m, b6 J8 }
4、查看串口发送函数打印log效果9 B% O6 M, s' `
(1)设置串口助手参数为:115200、NONE、8、 1(和代码中串口初始化参数一致)。4 [/ F0 T5 e$ j+ u
1 N; U* ^7 b9 y! j: u; i
(2)设置成功后,就可以看到串口打印的效果。如果串口助手没有发送给MCU的数据,则MCU每隔500ms闪烁LED1指示灯一次,且串口输出一个log。7 V- w* y1 C7 n" T' F* m% O

0 P  K( A* P; J& ?* t(3)如果串口助手往MCU发送数据,MCU把接收到的数据发送到串口助手进行打印显示。
" l' p! N" ]/ S5 G& E8 r9 l% B5 N  _" n  R  X9 N# c
16cd1063057845399adc6f45e25a20c7.png . d2 I* B, y! q* n7 W" u% \2 q
6 B, M/ ]+ Y: m
————————————————
+ V- H) a: `! J( C; }1 ]6 Q版权声明:智能小屋ZYXC. l) G6 {1 P) i+ z1 f0 O
, d4 F4 ]) h" w/ A
% t  o% h6 X) H5 D" Y
赞 收藏 评论0 发布时间:2023-1-15 00:07

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版