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

【实测教程】STM32L43之串口DMA收发实验

[复制链接]
STMCU小助手 发布时间:2023-1-13 20:00
一、开发板平台简介:' W9 V/ V9 K- Q3 ~/ h+ i4 Q- w
1、开发板资源简介

* C/ s% g7 g; n* {8 ~! K(1)开发板主芯片型号:STM32L431RCT65 L. M. t* t5 `0 w7 h: N0 e. d
(2)开发板主芯片封装:LQFP-64_10x10x05P
$ p) b. k; A6 q, l! a(3)开发板主芯片内核:ARM® Cortex®-M4
+ h1 S1 ]% T+ J5 j4 n(4)开发板主芯片主频:80MHz
5 L4 B1 r  @0 t$ o(5)开发板主芯片Flash大小:256KB3 d7 e( @; ?! L& v+ H; G4 P3 H
(6)开发板主芯片RAM大小:64KB
) u; W$ G4 |$ g( T' B
; l$ p5 {5 p9 w
bb91345227434ee7a43a34bf3fe366e6.png
( X3 [1 U) Y5 O4 P5 @( K! v% s% Z) H5 z
929c0cce04aa4115a8623703982bf3e1.png # E2 l  [9 q" D  `5 y! |4 ]" }
" ?, p. f0 x- U9 c, y8 g: z' S9 P
2、LED灯资源7 S2 ?" z8 N1 F$ I; F9 J
(1) STM32L431RCT6开发板共5个LED灯资源,其中一个红色LED为系统指示灯,指示开发板供电系统是否正常,如供电系统正常,红色LED为上电常亮状态,硬件原理图如下图所示:
" t5 S8 S, o! K& P7 k
& e$ P* M" M* W1 j4 n
0f177691c5814f16a508bcfa747f87ac.png ) k, \, v6 g% T4 Y) [
6 \. q  n. ^0 Y, N: k- X8 x4 p; n1 s
8 E/ t6 f+ p( w
(2)其他四个LED灯为黄绿色可控LED,高电平点亮、低电平熄灭,计划用LED常亮验证看门狗的作用,硬件原理图如下图所示:
/ T6 F1 o3 h/ C3 ~/ ]! ?! a' m' g) f
e923ad767b8448b7ac37c4ed693724bd.png
! ?; X. V- j0 a
0 ?4 `0 k2 ^& Y$ {​3、串口DMA收发工作原理) e9 p9 I  n0 O! M
 串口全称为串行通讯接口,即数据在通信线上一次传输一位,按先后一定顺序传输。我们通常所说的单片机串口准确来说应该是串行异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART),使用TTL电平,串口需要RXD、TXD、GND三根线进行通信。# s8 D6 c  X2 W9 z
- S) {8 k1 O3 P5 q
     (1)我们选用的STM32L431RCT6开发板串口1已通过USB转TLL串口芯片CH340G引出,使用时,只需要用公对公USB线连接电脑即可(注意也得需要安装CH340G驱动),后期验证试验也可使用该串口作为debug串口。* D  _( P& B7 G6 x+ d

' X4 p, ~! o$ P2 \3 B2 k( u& s     (2)开发板上的其他串口已通过排针引出,为TTL电平,通信的时候需要注意选择对应的电平模块,如USB转TTL串口模块等。
1 h+ U- U; p/ p+ b5 h. [* a# e& I4 l' W
TTL转CH340串口,硬件原理图如下所示:2 v- Q. `$ J' `( @* E

* X; D' N- L, A5 m7 o
4df1b489cb944c26b55013001061675d.png : ]4 W# O5 t6 C

5 C' V. u9 @- u; h* I2 y: aDMA(Direct Memory Access) :直接存储器存取,是单片机的一个外设,它的主要功能是用来搬数据,但是不需要占用 CPU,即在传输数据的时候, CPU 可以干其他的事情,好像是多线程一样。数据传输支持从外设到存储器或者存储器到存储器,这里的存储器可以是 SRAM 或者是 FLASH。
. h2 q4 l: K# P5 Y1 }4 s6 y3 L+ Y- c
DMA 控制器包含了 DMA1 和 DMA2,其中 DMA1 有 7 个通道, DMA2 有 5 个通道,这里的通道可以理解为传输数据的一种管道。要注意的是 DMA2 只存在于大容量的单片机中。/ j" i5 F0 `, h$ {

) g; K5 c8 p) Q
354955ecc6b140049ec57af71fe199f1.png 7 c! a0 d+ q5 f/ o0 y. H6 h

: b2 L2 k7 m, h. \8 W  二、串口DMA收发实验过程5 C1 X* ]8 r. W* t
1、新建STM32CubeMX基础工程
! Q$ o6 a" W, t5 a! q3 a/ D% b3 O
(1)打开STM32CubeMX,点击“File”-->"New Project"
# }& ^* Y4 |0 [; |
& u/ ?3 ~& J) R9 [* G3 `! ?
2399170347904e959c855fefd5877f84.png : _7 i( W6 h0 b" a& i* W

2 W( d( `( [9 k7 ~! y(2)等待打开主芯片选项界面(大约1分钟时间)。0 z/ G* Y% [4 n  B- n' V

! V2 r% X6 `  {# S: H: L: u/ U3 o
d74d2fdc60c9440483e2b7cf8d928e7f.png # `  T  p1 v3 {% f+ u" V+ r  t& _
$ o, x2 D% ^) \1 q0 p( V8 i
(3)昨天搜索框中输入(或选择)所需的主芯片型号(因为我们用的是STM32L431RCT6开发板,所以此处选择STM32L431RC),然后在右下角选择STM32L431RCTx(因为开发板主芯片是STM32L431RCT6),左键双击即可打开新建的项目。
& i/ i7 x5 `7 r1 B+ K/ l1 R0 _! O' L
; e0 @" a' E4 o6 x) h: p" i- V
7b80345238d74bea82ce70e1a348f7b4.png 2 @3 _7 B" ?9 X/ R$ v
( F, Q+ e2 ~  l0 U! N/ n0 {& p) O! u
(4)选择时钟源。! ]; z! U( V( e

6 T4 J& _7 S3 p. ^& s2 y        因为开发板上有8M外部时钟,硬件原理图如下所示,所以此处选择使用外部高速时钟(HSE)。, \- M8 t' x( _3 u

# x7 F3 D: `8 t. O2 R" N1 v/ D
3f65707eca104663a3dede6d25dfa961.png   w0 n3 B' @% @

4 s6 y( B) i8 x

+ ]: D+ L/ i+ O        因为我们没有用到外部低速时钟(LSE),此处不做处理,如下图所示。% k$ \1 n% w: Y: V

' ?* s6 ~2 W! i
72119b971f62410fa8344f7f9fb9f389.png . u1 z7 i9 I0 ?; o; `0 U) \
( B5 h5 s: M) T$ V7 J+ n8 C  c
2、配置GPIO控制LED8 T# u$ L3 _: K% `9 _: F
(1)查开发板原理图得,LED1、LED2、LED3、LED4的控制引脚分别为:; R; I7 U6 f( R$ [( F" b( {, q1 C
LED1——PC0  ]2 U# S' q+ I& O+ n5 z
LED2——PC1
8 M, r8 V7 J! r0 RLED3——PC2
+ l- P% u# Y* O8 ]/ NLED4——PC3  G5 V0 p7 F! O/ w

# U3 n! f% B6 x* N(2)配置LED的控制引脚为输出,输出频率、输出方式默认即可。: h+ ?& |* K7 D6 z
0 B$ s8 r( o4 _5 ~" u
鼠标左键点击PC0,选择“GPIO_Output”,表示设置该引脚为输出模式* ~+ z+ n* p! j2 J
鼠标左键点击PC1,选择“GPIO_Output”,表示设置该引脚为输出模式。$ d. `: W- I- g
鼠标左键点击PC2,选择“GPIO_Output”,表示设置该引脚为输出模式。2 T7 H' Y% R$ P; \1 y1 G
鼠标左键点击PC3,选择“GPIO_Output”,表示设置该引脚为输出模式。
5 p' M4 M5 t: R# a* {$ c3 G# W# D3 b% o0 e/ t
492907c1e71149819adbaee4516a2af4.png 3 Q5 i9 V7 B' g; B" e4 k- V) r

( e' L  j! }+ Q& l- ?( B  n
c75d3f10ba2e427d9c1a10fad9bf5471.png
$ c3 k( U' D& k+ I7 }/ N1 ~. L; A; c- M9 R' ~
(3)也根据自己的需求配置GPIO的参数,如输出方式、输出频率、上拉下拉等。因为GPIO控制LED的要求比较低,此处采用默认参数即可,不用修改。
9 v# ]/ X; o9 E/ g+ x' r
/ {% L' O0 `2 E, o; @4 Q
38ff4b80e1c5495ba3076a5158fd91fa.png
4 C8 T; f4 N% ~; A
/ _3 }* r& H8 x4 P$ T+ d4 p​​3、配置PA9、PA10为串口1 a" L; K1 m+ N! i
(1)查原理图得知,串口1使用STM32L431RCT6引脚为PA9-USART1_TX,PA10-USART1_RX,引脚设置如下:
% u7 o; D( X# S4 i. |; q
- f7 M% k  V' o' C4 o
497b8ee0243e446784e64a3c31e8a26f.png 4 K$ }7 j: K7 ?& b2 {. \& Z, P

& E5 x" S( D" _, u' W, ~- L 序号1用来设置串口收发引脚的选择。
8 n5 }0 _* Z- n: D: |, o序号2-3-4-5-6设置串口参数,如波特率115200、8位、NONE无奇偶校验等。
4 ^8 f9 j5 N; H. ?( H8 `+ u9 D
( ], A7 T) H/ L' c7 Y+ G(2)设置NVIC settings 使能接收中断
% D& K0 ~; \4 g0 n1 F# q- B; u
2 `8 m" Z; v: |4 Q! `( n
f9d7783b08304465815834f4d2095571.png
: p% c# P7 g! B) J8 f& n4 y; \" d8 _7 E) @5 P! d0 A. h2 N
3、串口DMA设置 1 r) U, w" r5 \- }3 o
* E  {) T4 z+ U2 x2 S, A3 K
6d26b13dd9d34039a2b426ca47680f8c.png 4 O& ~" T% [) S  H8 z% I, }
  E- ~. V) ?; Z& V5 e( h
(1)根据DMA1通道预览可以得出,我们用的串口1的TX、RX分别为通道4、通道5:, z" Q6 V7 n4 {
点击DMASettings 点击 Add 添加通道
' A' H6 U( @6 @: s$ O- |选择USART_RX USART_TX 传输速率设置为中速; O8 l1 h* Q4 W! w
DMA传输模式为正常模式,即发送一次就结束。, c! S& `5 P$ J3 s3 W
DMA内存地址自增,每次增加一个Byte(字节)
+ o0 `) J0 b; Q9 D: b2 ?
! n6 E9 v/ u  P1 f6 @+ S
976712e0494a4482bf65c69fc09fcabd.png " I! V: C8 |2 ^* B+ U: F  k: \
9 {  ]7 V/ [7 l! G& o8 X
(2)DMA相关参数解析- O, G% C- m! L4 h: H& o, k" Z0 [
Dirction : DMA传输方向有四类
! G- ]! N- I7 Q" g0 e- T' j外设到内存 Peripheral To Memory
( H- L. x' F8 R  n0 C# S1 g! w, f7 M/ K内存到外设 Memory To Peripheral
2 G! i) k2 E1 U/ ?  g) r7 E内存到内存 Memory To Memory8 [5 @$ E1 E# y. v3 n, V
外设到外设 Peripheral To Peripheral
% u7 {& N/ e" E, K2 O& r$ g, j: z  w5 f9 ?
Priority: DMA通信传输速度有四类
- J- \- s% d( ~# `9 K5 l最高优先级 Very Hight" z2 N% \+ }# b& @5 S" d
高优先级 Hight8 |5 T6 V. W' [$ D- k' Y
中等优先级 Medium
8 R" W5 a9 ?# u低优先级;Low: q" X2 L) {! B: S
1 S, k! R& y, T! t. q8 |3 m
Mode:DMA传输模式有两类
6 X8 }7 N4 S' q9 u: b5 D6 i) _
1 z, W% O/ \8 u/ e
9021c11fed3e4c1885477e062b846258.png
/ y8 Y5 x6 v( i3 k: m$ Z7 f# c8 A3 V% U& ^, i
Normal正常模式:当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次。$ I6 Z' I" j* @" C
Circle循环模式:传输完成后又重新开始继续传输,不断循环永不停止。+ x5 k) e! |* ?: G9 ?
/ }/ N6 P$ `/ p$ h9 N
Increment Address-DMA指针递增设置:
+ M9 q0 a. t4 U8 p% E
/ X% N% l+ T0 B0 |+ N: s8 [, h
2b1a952d6514444e9dbb019a9ae88c42.png
/ u& V2 e& m( A7 e# ~. k% R+ t: A
; W' D  D4 Q* M# B
: x/ c. m6 ~0 `4 ~0 s. ^: U5 N4、配置项目工程参数9 l) O# M0 K5 o
(1)配置时钟树,用于系统内部时钟,以及各个外设时钟等。此处选择外部8M晶振作为主时钟频率,内部最大倍频80MHz。
6 u7 d! ]- u& ^- E( y% E' X
/ J! x5 U% A3 P; x0 D- S4 b
f3ecedd9323f4463b69539906b3c1199.png " E  |1 l# N: J" b) B5 Q9 G  C# J- g
7 u8 E! l. j# \- V* d% ^
(2)完成配置工程。
5 U! n$ Q1 Y, T4 }备注:需要注意代码生成过程中的继承关系,如图所示:需要保留开发者自己编写的代码时,请根据配置设置,不然生成代码后会删除自己编写的代码(从这个方面也可以看出开发者备份自己的代码是多么的重要。)* @# r  L' t5 \5 g- k

! `; M/ a; U- [- V& ^( [1 H
efdb616174f54925b6eac31109f227b5.png
( E9 X5 t5 l5 C4 m" I
/ a+ [1 O4 y; Q# A/ Q- b- f/ S 41c3f2716e4e4eda8f62fa3a1d871322.png # }& V) k5 M0 l6 c# ~' J0 @2 B

3 {" T) m7 p% O( P5 ~(3)生成代码。; N0 @4 i: Y, ?& e. Z7 R
) _  b# a/ O7 @" Z: f' ~, B$ r
备注:使用Generate CODE生成工程代码前,请确保文件路径无中文,否则会生成项目失败。# |# a" t( P0 F, l* h

' C1 k9 i( Z$ S
8eaa7d0babea40ee93f158481a6ee471.png
: l5 R. ?5 ^, @​! i% y) r( w* w. `8 K, R9 {
(4)工程代码生成成功。
  e7 W) {' c1 j& ?) U2 n
% f: X3 L6 c5 _- e- P) V& d
e8f46d59a1fb4af589feb613fdff17b4.png 5 t# S; Z% y6 x9 I: J

/ U" h- i& h$ ~4 O4 B! T 三、在KEIL 5中编写代码) r3 B- G: q! O- e) K, z
1、使用KEIL 5(MDK)打开项目工程文件
  q0 w- g9 ^0 r1 {5 ]0 R, V- J源码使用说明:使用前必须把项目工程复制到无中文路径的文件夹下使用。
8 R  s, ^6 |; ^! H. J1 O(1)找到刚才新建工程的存储路径,安装项目名称,打开项目工程.uvprojx。! V: D% m1 s3 B3 t- \5 }$ j. Q5 j
3 L4 S$ T6 f* [" m
a2198e7b52e642bdb05a708c7fb8061a.png 5 O! ?  B: f+ f: i
3 f" S3 n/ ]) {, _, M$ E
2、添加LED指示灯作为系统提示
) f5 K8 g# T1 P/ c  Y, q3 _添加每隔100ms,LED1、LED2、LED3、LED4闪烁一次的系统提示,用于提示程序运行正常。
$ c3 f+ ^! F" Q. b% ~9 E3 E8 X
0 M+ Q5 Z6 ?; t: j( s3 _
2af9ef3cfaab45988c810d94d801fc34.png   F) }9 {5 K2 H( E- Y

% @. _2 _& B8 M, h% y( B3、添加HAL库UART  DMA 发送函数代码
/ A4 o& E- r$ U% v# ~% [(1)STM32 HAL函数库的串口DMA相关函数如下:. Z( o, b# j8 E3 L
  1. HAL_UART_Transmit();串口发送数据,使用超时管理机制
    + c  C9 }6 b$ w) {) W9 P
  2. HAL_UART_Receive();串口接收数据,使用超时管理机制; ?: ?' X& A- ]( N$ G0 ]
  3. HAL_UART_Transmit_IT();串口中断模式发送
    " ~  E4 V" B+ H/ e
  4. HAL_UART_Receive_IT();串口中断模式接收
    4 t7 z; ~& d& }
  5. HAL_UART_Transmit_DMA();串口DMA模式发送
    : C, e, G1 M: L
  6. HAL_UART_Transmit_DMA();串口DMA模式接收
    ' P! }" f& d. S- Y' Y* g
  7. HAL_UART_DMAPause() 暂停串口DMA
    $ d/ T# V& u" z/ k$ N# b% Z/ o
  8. HAL_UART_DMAResume(); 恢复串口DMA1 L* G' [* ]% G0 y- {8 Q2 ?
  9. HAL_UART_DMAStop(); 结束串口DMA
复制代码

% d* q- S" o, S(2)main.c添加串口DMA发送函数相关代码:0 Z, [0 Y( A1 p7 J5 F# M+ Z
  1. /* Private user code ---------------------------------------------------------*/6 X9 `) K# G& d1 q7 C  n/ H
  2. /* USER CODE BEGIN 0 */
    / J) }1 g+ h; ^( R- d
  3. uart_rx_struct uart_rx_struct_t={0};                                //串口接收数组
    * t9 x$ x9 R, K2 c6 n
  4. /* USER CODE END 0 */
复制代码
  1. int main(void); w9 x' q% ~; ~. m2 n; Y0 W$ Z
  2. {7 d4 w$ q4 `7 c4 B
  3.     /* USER CODE BEGIN 1 */
      _0 x, D4 S3 b, B% ?
  4.     uint8_t transmit_str[50]= {"hello world,this is uart dma function!\r\n"};
    ( I' ]9 i) Q$ U6 l, K5 |' U
  5.     /* USER CODE END 1 */
    3 M& c+ Y( c' ~" N
  6. . Q& G8 V! F7 `# i2 g- L
  7.     /* MCU Configuration--------------------------------------------------------*/" o' M( {$ q( w8 u. R
  8. 3 x- w; h: _: r7 Q
  9.     /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    6 a1 E. U. m3 t3 t  K8 p# b
  10.     HAL_Init();! c0 K1 }2 ^( {3 F8 r
  11. / G3 u2 U$ p$ C' q4 Q! ~
  12.     /* USER CODE BEGIN Init */
    4 y8 L' z# ]6 P1 X) O
  13. & O! N! y5 Q2 C4 Q
  14.     /* USER CODE END Init */
    ; j6 n% w2 \6 x4 G! [5 G9 j5 U7 h

  15. : i  {: F  {' Q8 ]0 l% k. Q; H/ u
  16.     /* Configure the system clock */
    # [7 M; o. Y9 u! O' [
  17.     SystemClock_Config();
    4 j' b$ _- F+ d2 }& m% d& A% f
  18. " B5 ^6 T" ^- e' ~$ Z
  19.     /* USER CODE BEGIN SysInit */
    1 I0 V7 d  f  \' o# f

  20. ) X- k1 ~+ P6 Z& l
  21.     /* USER CODE END SysInit */3 s# P" O8 B6 M5 w: S$ {) [! T) X& w
  22. , E0 m8 W  p) y4 O' @9 y
  23.     /* Initialize all configured peripherals */% w" w! c" q" g# N  C
  24.     MX_GPIO_Init();
    $ n# I. |8 L" H# x. m% [; D
  25.     MX_DMA_Init();) P! ]6 {# U! F2 G, x, e/ B7 I& S
  26.     MX_USART1_UART_Init();
    ) O; R7 g- O& u  ]* g
  27.     /* USER CODE BEGIN 2 */
    ) ]  V: |0 \* w: n! o# `, M
  28.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮
    & C0 ?+ R' G( i  o4 D; A
  29.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮
      E, K# l3 L5 y1 a, `2 p
  30.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮
    2 ~1 a2 ^- O" |6 ^- k+ M& o' i
  31.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮# S1 a* v" y+ B! n# \; u
  32.     HAL_UART_Transmit_DMA(&huart1, (uint8_t*)transmit_str, sizeof(transmit_str));    // 1 c: E& o3 U6 f! X
  33.     HAL_Delay(5);
    2 [7 O& |7 |( R$ q- W3 i$ o
  34.     HAL_UART_Receive_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, UART_RX_LEN);         // 启动DMA接收
    2 E- e% S$ }9 G7 R
  35.     __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);                                      // 使能空闲中断
    5 M" j1 w* I' y# V

  36. 4 C3 m9 G! y0 J6 `5 ]
  37.     /* USER CODE END 2 */$ W  C% `- W* }9 l. S0 ~, I8 a# V
  38. 2 t' e) K( m8 [" a* \" l% H: P
  39.     /* Infinite loop */) b% x- M9 }" b' H7 T6 N
  40.     /* USER CODE BEGIN WHILE */- P! g/ U2 ]- m, g! \; S
  41.     while (1)7 @: f" f1 _$ D1 d5 N
  42.     {1 ?/ h9 k$ e( R" U7 |
  43.         /* USER CODE END WHILE */
    " H5 G  f- [3 [, m) d

  44. $ c" q+ [9 a0 b/ J. Q6 i* D9 `0 w, V
  45.         /* USER CODE BEGIN 3 */
    ) R3 F1 C7 z+ w$ N- x+ _5 r% A' x
  46.         HAL_Delay(100);
    6 V- f- a( F" g
  47.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);                                                                        //反转LED点亮熄灭切换- g5 C( ~2 U9 c2 B
  48.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_1);                                                                        //反转LED点亮熄灭切换: p- U9 m4 ^  p$ W; b$ [. B& U0 S
  49.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_2);                                                                        //反转LED点亮熄灭切换( @5 |( T% i9 _) U, z8 s' b
  50.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_3);                                                                        //反转LED点亮熄灭切换8 G+ V6 e$ N  `) s6 C/ q2 ]6 G
  51.         if(uart_rx_struct_t.uart_rx_flag & 0X80)                                //DMA接收完成6 b% M! f4 E. ]' C; J0 B4 ^
  52.         {) s% z- I3 E+ m: ~. _$ W
  53.             HAL_UART_Transmit_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, uart_rx_struct_t.uart_len);    // 将接收到的数据发送回去
    0 k5 L0 R3 D8 Q/ \
  54.             uart_rx_struct_t.uart_rx_flag = 0;' N, D% W  X" R& `
  55.         }2 a& d7 ~0 ~; P' H

  56. 3 J8 D& M9 D* r8 \4 c
  57.     }2 {( `# V& A: W* _1 |8 T6 u* G
  58.     /* USER CODE END 3 */
    9 O4 u4 N& t0 _1 u' J! X! I6 V
  59. }
复制代码
' n% m$ F- }+ x2 A6 T! U2 w
(3)main.h相关变量声明5 D' Y9 G3 S; K4 V, L
  1. /* USER CODE BEGIN ET */4 t- T! O1 [5 i9 i3 t
  2. #define UART_RX_LEN 1024                // 一次最大接收的数据量2 v& z' A0 Q" o- C7 M4 G
  3. typedef struct
    8 J4 A4 R) N) P8 H1 C. p, B
  4. {6 i% J" |4 @7 {2 y0 T
  5.     uint8_t uart_rx_buf[UART_RX_LEN];  // DMA数据接收缓存数组  v' [; m3 I- \' Q  _
  6.     uint16_t uart_len;                 //DMA数据接收长度+ S$ x% P% \5 W+ z  y* O4 o
  7.     uint8_t uart_rx_flag;              //接收完成标志位% S7 ~6 a  U9 v# n/ ^& {
  8. }uart_rx_struct;
    + H; T" X5 w; n' [% T+ @
  9. extern uart_rx_struct uart_rx_struct_t;  
    ! t! W4 R( H0 e: i) E: r4 c' T- i- A

  10. 3 g! p6 C; F2 ?* _
  11. /* USER CODE END ET */
复制代码

. ^! D% [4 K: b5 k4 R( }! _$ q4、添加HAL库UART  DMA 接收函数代码" l5 f1 k8 d4 v  v$ k/ d  K
(1)DMA接收设置前铺垫知识点:
0 u7 Y* u; Q$ J3 w        STM32的IDLE的中断产生条件:在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断停止。
  k( H' t2 ~# y3 W% E9 U% N" r+ u! x/ a
(2)添加DMA接收处理代码3 [, D* H6 @: T$ w

- {/ M" p" {3 e$ _. y% n
stm32f1xx_it.c中添加代码如下:
( w* _; \' U  n  A6 ?
  1. void USART1_IRQHandler(void)
    & Q- M, l1 ^# i% W' ?
  2. {
    " v  V( i* p2 r+ b
  3.     /* USER CODE BEGIN USART1_IRQn 0 */
    0 _4 [7 X. z3 W
  4.     if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) != RESET)       // 空闲中断标记被置位
    ) |2 @, U0 a# u0 e9 X4 j
  5.     {
    4 q8 ?+ B) l% ^; M7 X8 T; g
  6.         __HAL_UART_CLEAR_IDLEFLAG(&huart1);                         // 清除中断标记
    5 I+ ^3 R" k" i
  7.         HAL_UART_DMAStop(&huart1);                                  // 停止DMA接收
    + l' Z4 o( A( k& g" U/ I
  8.         uart_rx_struct_t.uart_len = UART_RX_LEN - __HAL_DMA_GET_COUNTER(huart1.hdmarx);  // 总数据量减去未接收到的数据量为已经接收到的数据量
    0 R) e8 G6 H$ Z
  9.         uart_rx_struct_t.uart_rx_buf[uart_rx_struct_t.uart_len] = 0;                    // 添加结束符; e" x, |+ i9 Y/ v+ m* ?
  10.         uart_rx_struct_t.uart_rx_flag |= 0x80;                                       // 标记接收结束, ]' ?. t& h7 N/ g4 d- ~
  11.         HAL_UART_Receive_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, UART_RX_LEN);    // 重新启动DMA接收
    * H& |$ U9 z. W8 j: k, ]& _
  12.     }
    . Y  V# x# N8 b: J+ [2 q
  13.     /* USER CODE END USART1_IRQn 0 */
    : j# }7 a1 d1 M* l4 i7 M9 r2 `# h
  14.     HAL_UART_IRQHandler(&huart1);0 ]6 ^9 j% d: ]4 C. e4 j# K/ g
  15.     /* USER CODE BEGIN USART1_IRQn 1 */
    7 w* Y: l6 T7 F) ^7 V7 O

  16. % V0 y" I) v6 c! d8 T+ E% o8 ^
  17.     /* USER CODE END USART1_IRQn 1 */
    : \+ ~; p8 H* j) [2 s
  18. }
复制代码
! l6 d% o- Y( V/ K& P5 ]& d! V2 o. v
(3)至此,串口DMA收发数据需要添加的代码已经完成。
9 W$ u+ r1 c! F2 D% V7 W4 v% \

4 t) [  s# d# D" a) g5、设置编程仿真下载模式. R" m) `- D- ?" F- U8 I7 c" h
(1)选择Options for target ...>>Debug>>J-Link/J-JTRACE Cortex,点击Settings>>选择Port(SW),可以看到搜索成功SW Device,表示芯片可用,可以下载。; G" S) y  U+ W) }0 y/ ~/ d

$ t* y& A* p0 @
9f8aa1a4e8f04041bcf5cb183facd100.png
# k8 ]5 t; e1 ~; T& n​5 B! V& c7 A9 {! e5 X
(2)点击编译,完成后提示“0 error(s),0 warning(s)”。
1 t- F/ G8 ~" @( N$ h
/ X' B1 y$ l$ S- b, E" U' b
e0b7e3e353b345a7987fe5f821de2dda.png
" B) ~- i1 Y9 ^: S2 h3 d' h% ]4 R4 X. Y7 U, O# M9 L) E8 ?
(3)点击Download(或者快捷键F8),即可下载程序。0 l2 T9 M$ ~; _
! ?  _# t  U9 x5 J- k
eb3f250f19e44862a7df80c2492fcd01.png 5 v! j$ F- g! `1 L/ ~
​​
0 k/ y5 X$ n3 `% v8 F0 J8 y+ V& [% f& q! ^) \( j+ A
(4) 如果下载程序后,没有看到LED1、LED2、LED3、LED4闪烁,可以按下述方式设置一下(Reset and run表示下载后自动复位和重启运行)。或者重新彻底断电再次上电(或按开发板的Reset按键复位MCU即可)。8 A% v. h( i# w4 C4 I

* s7 C& j' p6 Y& d6 o
+ X* t) X- s% a1 G. ?
​​9 q/ W; \3 A& {; R! h
6、串口DMA收发实验效果展示

6 I- b8 ]; M/ I$ ^        程序烧录到开发板后,即可看到LED1、LED2、LED3、LED4初始化后每隔100ms闪烁一次,并且打开串口助手后(串口参数:波特率115200、N、8、1),通过串口助手可以看到,开发板接收到发送的数据转发出来。
+ ^0 e( T1 x+ F7 s
4 d- x# F, |+ G8 ~8 e# ]1 G- H
2a8f9f6486b04eeb8747ce0b09a6352c.png ' o! y9 Z1 M' i: j0 }2 b

* p* r& j" f  K' X+ B5 y. u& L————————————————4 s& S  |! ]' K
版权声明:智能小屋ZYXC8 j3 g4 g) w6 l1 v" h/ _

3 x( a6 l" S+ f! y. E- d
) F$ X5 J, B1 i
edefb6b9a2a14be3b1221ad6d5c7a8a2.png
赞 收藏 评论0 发布时间:2023-1-13 20:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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