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

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

[复制链接]
STMCU小助手 发布时间:2023-1-13 20:00
一、开发板平台简介:
1 O, K9 @/ r9 ?! k4 a; A1 _) g1、开发板资源简介
. b( `0 q& J9 G, U. [- H2 g
(1)开发板主芯片型号:STM32L431RCT63 A! g  g# F0 |* T$ W, ?8 _
(2)开发板主芯片封装:LQFP-64_10x10x05P
% b2 q& t+ S; b" a3 K% p( m9 Z(3)开发板主芯片内核:ARM® Cortex®-M4
% n/ w$ ?& ]% t& ](4)开发板主芯片主频:80MHz7 g! `7 q) _5 m9 n& Z
(5)开发板主芯片Flash大小:256KB" Q& L* {6 r3 l. a
(6)开发板主芯片RAM大小:64KB
* V$ F% z( `& K1 b
& f: `  [* F: |, k1 L" C, ]
bb91345227434ee7a43a34bf3fe366e6.png * I; G1 m" o5 j) P/ J

8 f0 `+ ]" ?. \8 ?
929c0cce04aa4115a8623703982bf3e1.png
6 W( E$ \  [4 n
) N( j" I  Y) \' G) q$ }9 w
2、LED灯资源$ r) o" q& ]; |
(1) STM32L431RCT6开发板共5个LED灯资源,其中一个红色LED为系统指示灯,指示开发板供电系统是否正常,如供电系统正常,红色LED为上电常亮状态,硬件原理图如下图所示:
/ E4 K, m$ n! N/ f3 r  Y% N
. b" J9 G9 K$ U1 |
0f177691c5814f16a508bcfa747f87ac.png
* B4 L6 w2 [! T( K6 t
# a" S# x+ T7 ~: p4 V
1 S% L0 q, x9 o- ]1 q) i( N
(2)其他四个LED灯为黄绿色可控LED,高电平点亮、低电平熄灭,计划用LED常亮验证看门狗的作用,硬件原理图如下图所示:: i8 Q. M( N+ I/ o

- m9 z4 O" i$ B2 t
e923ad767b8448b7ac37c4ed693724bd.png 7 s) h6 w; t7 [
, {% X6 a% z- R8 j. L6 o0 v9 T
​3、串口DMA收发工作原理- I+ ?8 \' w7 U2 v' _7 `) `$ p
 串口全称为串行通讯接口,即数据在通信线上一次传输一位,按先后一定顺序传输。我们通常所说的单片机串口准确来说应该是串行异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART),使用TTL电平,串口需要RXD、TXD、GND三根线进行通信。
0 b; Y% n# q6 b+ ~$ O: G' n1 D: X! }8 Q  t& @4 D
     (1)我们选用的STM32L431RCT6开发板串口1已通过USB转TLL串口芯片CH340G引出,使用时,只需要用公对公USB线连接电脑即可(注意也得需要安装CH340G驱动),后期验证试验也可使用该串口作为debug串口。
2 S8 Q+ h; r* E; X. G' L

1 ]0 D! f' ?/ t2 k     (2)开发板上的其他串口已通过排针引出,为TTL电平,通信的时候需要注意选择对应的电平模块,如USB转TTL串口模块等。; n9 I# a; Q+ t  D
( Y: b0 D. m$ h" Y
TTL转CH340串口,硬件原理图如下所示:
' w  a: [6 I; A
% q. q. x0 d6 x
4df1b489cb944c26b55013001061675d.png * `" Q# T2 @2 S6 q1 \) X

8 c* q: \. C5 k6 ]- dDMA(Direct Memory Access) :直接存储器存取,是单片机的一个外设,它的主要功能是用来搬数据,但是不需要占用 CPU,即在传输数据的时候, CPU 可以干其他的事情,好像是多线程一样。数据传输支持从外设到存储器或者存储器到存储器,这里的存储器可以是 SRAM 或者是 FLASH。
8 B0 J( p" h" T4 z7 [
( L- U' a8 B; e5 s6 rDMA 控制器包含了 DMA1 和 DMA2,其中 DMA1 有 7 个通道, DMA2 有 5 个通道,这里的通道可以理解为传输数据的一种管道。要注意的是 DMA2 只存在于大容量的单片机中。
3 O0 i9 S! S/ @+ W/ n8 g( E& O$ N7 D) O
354955ecc6b140049ec57af71fe199f1.png
5 h' \" \, M6 U1 q! x$ f7 ~, ^. L+ F' ?! l" G8 ]/ x6 Z  X
  二、串口DMA收发实验过程
/ Z) L0 L& F9 U6 M; p6 |/ J1、新建STM32CubeMX基础工程
2 Z4 P+ x! L, Q3 I
(1)打开STM32CubeMX,点击“File”-->"New Project"  m$ ]2 l4 }) {/ K$ {
* K; a/ R& E# R4 a
2399170347904e959c855fefd5877f84.png
( f- }3 }. o) c$ K" I$ s

1 H! I) v* L) c(2)等待打开主芯片选项界面(大约1分钟时间)。4 e: @6 f( M( Q) M

- B. v  ]* R+ i2 S  c
d74d2fdc60c9440483e2b7cf8d928e7f.png ! m+ p1 A9 h1 W. w+ ^

( \  U  }' B: V(3)昨天搜索框中输入(或选择)所需的主芯片型号(因为我们用的是STM32L431RCT6开发板,所以此处选择STM32L431RC),然后在右下角选择STM32L431RCTx(因为开发板主芯片是STM32L431RCT6),左键双击即可打开新建的项目。
" j/ j. O) p1 j$ k4 \$ @" F% d, @) m4 n- d1 ~# O
7b80345238d74bea82ce70e1a348f7b4.png ; [0 ^4 k, I$ `
4 a3 u( R" `, `
(4)选择时钟源。) B7 Z; z, S3 `9 @* B
( q  @- s5 C7 E0 l6 U; a! n
        因为开发板上有8M外部时钟,硬件原理图如下所示,所以此处选择使用外部高速时钟(HSE)。
$ X8 u( ], o& l, ?' ?
: @! q4 q3 a: R, R+ k& @# Q3 n7 J1 Q
3f65707eca104663a3dede6d25dfa961.png 9 ]/ U/ z" @& N" u/ U. v2 U
, o8 L, a: ]* t/ }7 G0 ]

& q% E$ d9 R: X' g4 v: Z. A        因为我们没有用到外部低速时钟(LSE),此处不做处理,如下图所示。* [4 b& S, D8 g: n5 B9 J% G6 C

- w$ J$ X( |9 A+ @: P
72119b971f62410fa8344f7f9fb9f389.png
) z9 n, m0 ]: t. O3 ]9 V4 T
2 |$ I1 @5 f4 V2、配置GPIO控制LED
/ ?* w1 W  Y7 z+ x8 f(1)查开发板原理图得,LED1、LED2、LED3、LED4的控制引脚分别为:8 V" X, l  }- a$ s
LED1——PC0* m, Z6 T  K3 ?: Y- c1 D/ q
LED2——PC1
6 V* f# ]! k" w/ FLED3——PC2
. F% \! ?$ P) O9 DLED4——PC3
8 f% T4 l4 N" I$ W$ h! j) s* Z
+ g. @* L1 j6 [3 L(2)配置LED的控制引脚为输出,输出频率、输出方式默认即可。
+ X+ g, N1 T: w
8 q! N+ O7 k! ~" J: x鼠标左键点击PC0,选择“GPIO_Output”,表示设置该引脚为输出模式
. V2 B( l  m" c* x; R6 o$ ?/ L鼠标左键点击PC1,选择“GPIO_Output”,表示设置该引脚为输出模式。& ?" S9 i. n3 p0 a* `4 i
鼠标左键点击PC2,选择“GPIO_Output”,表示设置该引脚为输出模式。
+ L8 }8 c* B% z) f" N鼠标左键点击PC3,选择“GPIO_Output”,表示设置该引脚为输出模式。: ^( }6 V" @. o6 w4 g# s0 p

. _, e: ]8 T/ g; ?' J, i
492907c1e71149819adbaee4516a2af4.png 3 I# Q# V: A0 L9 G0 O7 }

' ]  s, G4 E; Z" \4 j! p, b
c75d3f10ba2e427d9c1a10fad9bf5471.png
$ Y  |5 z# o$ c, @: r, e% }
& K) U5 E8 L1 O" l& u" T$ P% s(3)也根据自己的需求配置GPIO的参数,如输出方式、输出频率、上拉下拉等。因为GPIO控制LED的要求比较低,此处采用默认参数即可,不用修改。
( m; u+ e' c& Z& j4 I' \: l/ O- U) a) j
38ff4b80e1c5495ba3076a5158fd91fa.png # G- W6 D2 p  J, @

' J' K) m& i1 j​​3、配置PA9、PA10为串口
) m! u3 D, `8 q* `(1)查原理图得知,串口1使用STM32L431RCT6引脚为PA9-USART1_TX,PA10-USART1_RX,引脚设置如下:
0 R, R* k  Y& `, I# v  u3 ?; f( S1 H9 \4 Y+ L# @" {  C
497b8ee0243e446784e64a3c31e8a26f.png 4 C( s7 `$ e' [9 g" U% r
& G! {, W. {. p2 t( X3 y) g$ `
序号1用来设置串口收发引脚的选择。* B, x* z9 Q# t8 f9 x$ y
序号2-3-4-5-6设置串口参数,如波特率115200、8位、NONE无奇偶校验等。0 t0 X6 w" j6 H4 m
/ G( Q( ~2 z$ z& y
(2)设置NVIC settings 使能接收中断
* l6 m# C- W' `) o* z' J% q' J# q" |( u- R! Q+ S
f9d7783b08304465815834f4d2095571.png 4 P9 f6 j6 j$ t( Q4 b

5 P) U( g9 ~! a0 O) C) }5 S9 E; O' `3、串口DMA设置 2 k7 P4 g& B$ \; u' H6 \4 S

/ J3 y* n3 ^1 \! J
6d26b13dd9d34039a2b426ca47680f8c.png
- l) h0 X; C6 ?& E% f& h1 G; f! l/ B2 ]5 r
(1)根据DMA1通道预览可以得出,我们用的串口1的TX、RX分别为通道4、通道5:& J/ z7 Y5 k/ `# z/ I- ~7 V
点击DMASettings 点击 Add 添加通道2 m- u3 F4 a& p
选择USART_RX USART_TX 传输速率设置为中速- `3 K/ _7 o2 `, O
DMA传输模式为正常模式,即发送一次就结束。
: L  g( a" ?! C1 `. ODMA内存地址自增,每次增加一个Byte(字节)
: G' ^8 W2 }0 o, j9 B$ k) H5 [  p3 {# x: w$ e$ G" B% p( T
976712e0494a4482bf65c69fc09fcabd.png . j% v6 O- Y" J2 B

+ k+ }( s1 |2 J, } (2)DMA相关参数解析
' b% C) J7 c' L  O- uDirction : DMA传输方向有四类2 Q5 u7 j0 k3 }  ^' l
外设到内存 Peripheral To Memory$ @& ~2 e0 o9 P  J
内存到外设 Memory To Peripheral
3 |! d; ^7 I1 Y! e  G内存到内存 Memory To Memory
/ H+ q2 c2 S6 e0 T9 |0 ^" b外设到外设 Peripheral To Peripheral
( d* B( ^7 J2 h% G' X; D# m8 J, [
$ h$ C) |7 y4 i  i
Priority: DMA通信传输速度有四类
; X7 P1 {; u; L- K2 L2 @0 b5 v: g. E最高优先级 Very Hight
- `. |) T! H1 z( Z" ]高优先级 Hight
: T, V! D$ e1 u$ N% N- a$ S& f1 Q中等优先级 Medium+ q6 v  m# W- n" m- l7 ^( ]
低优先级;Low
. t/ E  @6 F/ H: O. B
: [6 ?6 Y/ i' S& e1 k. ^8 v" r
Mode:DMA传输模式有两类
' a- d8 ^0 d- G. P6 U
5 a0 `6 U& L" z9 o  e
9021c11fed3e4c1885477e062b846258.png
  F/ L* }  F' B# v! Q( e7 }
/ D  ]% u, M6 dNormal正常模式:当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次。
, V9 F# u' o% i3 P7 ECircle循环模式:传输完成后又重新开始继续传输,不断循环永不停止。6 [: Y' P9 _6 @  _, }

$ r% z; p" y* @' `
Increment Address-DMA指针递增设置:4 A. F, a9 w. z3 {

! ^; V4 B& G6 E& b4 H: L( [
2b1a952d6514444e9dbb019a9ae88c42.png 2 Z8 W+ |8 i+ l/ V3 T" I
' n3 w; d2 k& z8 Q2 z0 ^

! k+ u# H5 U5 J4、配置项目工程参数
$ q6 F# x6 \7 Y0 S& B+ T(1)配置时钟树,用于系统内部时钟,以及各个外设时钟等。此处选择外部8M晶振作为主时钟频率,内部最大倍频80MHz。
8 i- \4 X, t8 x# k! ~' F+ }% b, P2 B% T( m$ r* U3 x# \+ e  F+ u/ a
f3ecedd9323f4463b69539906b3c1199.png
+ V+ d: l6 x; C! |) s' B" `* S/ e  @+ C) O' O7 v/ M8 ?
(2)完成配置工程。
% S* X: p6 q2 q& T1 k% }* S( @备注:需要注意代码生成过程中的继承关系,如图所示:需要保留开发者自己编写的代码时,请根据配置设置,不然生成代码后会删除自己编写的代码(从这个方面也可以看出开发者备份自己的代码是多么的重要。)- K' [8 X2 A3 k4 j: C  N

  U- |2 R/ Q) s; A
efdb616174f54925b6eac31109f227b5.png 6 ^5 ?) L+ N0 h* ~5 V" l: R

+ B3 s; ?+ x' v 41c3f2716e4e4eda8f62fa3a1d871322.png 5 F9 ~; ~* s3 P" Z) d

% {. Y- j0 v. i! x4 }  u5 l(3)生成代码。4 A) u* b3 y- R6 ?( f0 ~

& H* ?8 z% e$ R' W& }  n备注:使用Generate CODE生成工程代码前,请确保文件路径无中文,否则会生成项目失败。
' \; [( F2 E7 i5 p4 x8 x4 Y) Z: c% g5 i( d$ N
8eaa7d0babea40ee93f158481a6ee471.png
* e$ I0 @+ Q" R: G" b​
; s% y; w% G5 l) v5 N$ w$ e& o2 F(4)工程代码生成成功。
* a5 `6 ^1 t1 E0 Q! T; k& k" ^" T2 k* }% k5 i
e8f46d59a1fb4af589feb613fdff17b4.png % [9 I( M$ |$ k" t  k& d8 a3 W

" i' S& X' f( W# ]8 @9 C 三、在KEIL 5中编写代码
6 `4 q& Y% ~" f! D) ^' K1、使用KEIL 5(MDK)打开项目工程文件( L( V( _/ j8 `+ ~9 I
源码使用说明:使用前必须把项目工程复制到无中文路径的文件夹下使用。
, e+ B1 l# s+ L# C(1)找到刚才新建工程的存储路径,安装项目名称,打开项目工程.uvprojx。% h& j. g' R* K
8 D1 u) e/ ]# n1 ]7 z5 B( O
a2198e7b52e642bdb05a708c7fb8061a.png
, D7 |3 B- `( |8 ^3 F2 b, a5 j+ Z8 ?
2、添加LED指示灯作为系统提示
6 D: |! m; C# F4 _添加每隔100ms,LED1、LED2、LED3、LED4闪烁一次的系统提示,用于提示程序运行正常。
6 s3 n: U  r$ \2 s$ Q/ r% G7 U' ?6 |, m
2af9ef3cfaab45988c810d94d801fc34.png * Z* P- l  u/ |- s6 e# y
) i5 K' B( k/ |3 d. C
3、添加HAL库UART  DMA 发送函数代码
( W! l1 R' L/ r  J  H$ Q$ S(1)STM32 HAL函数库的串口DMA相关函数如下:1 y/ S8 T" n5 D! z- ^
  1. HAL_UART_Transmit();串口发送数据,使用超时管理机制
    : K% ^) B( N+ R7 e" A0 M4 U
  2. HAL_UART_Receive();串口接收数据,使用超时管理机制% J4 K+ U6 i& I" h* ~' B4 R3 v
  3. HAL_UART_Transmit_IT();串口中断模式发送. Q* Z1 k6 s7 I& k4 n( E
  4. HAL_UART_Receive_IT();串口中断模式接收+ [4 w4 z* @1 G" a* }+ X
  5. HAL_UART_Transmit_DMA();串口DMA模式发送
    ! j) N( f0 l2 ?1 y1 t
  6. HAL_UART_Transmit_DMA();串口DMA模式接收. B7 y) ^3 E" [9 l% `, Z! `
  7. HAL_UART_DMAPause() 暂停串口DMA
    - A& ?8 g/ ^, T: Y( u, b* N) z- m/ u
  8. HAL_UART_DMAResume(); 恢复串口DMA# B7 z* Q0 W. U, k7 h; Q
  9. HAL_UART_DMAStop(); 结束串口DMA
复制代码
0 ?4 h; }# W: w9 g, I. x6 J" F: Q& P
(2)main.c添加串口DMA发送函数相关代码:" t" l0 A, \4 r* Z7 E5 b
  1. /* Private user code ---------------------------------------------------------*/: d$ _/ Q. r8 ]7 j3 e! Z+ P& S
  2. /* USER CODE BEGIN 0 */$ s3 j0 J4 X# q  r. k1 o
  3. uart_rx_struct uart_rx_struct_t={0};                                //串口接收数组
    * ]1 p4 M; Q, @. f' j, Q5 j
  4. /* USER CODE END 0 */
复制代码
  1. int main(void)
    $ a* s+ m( E6 F4 h5 ?2 b
  2. {- I$ d) E+ d  G1 [
  3.     /* USER CODE BEGIN 1 */
    + l1 _4 y" }  p" b. {4 R
  4.     uint8_t transmit_str[50]= {"hello world,this is uart dma function!\r\n"};
    6 H3 D8 X  d$ h' C/ H4 ^
  5.     /* USER CODE END 1 */" z4 W* {7 n/ W5 n

  6. ' [+ m* I  ]5 G9 z2 ^0 I8 o$ f2 ?
  7.     /* MCU Configuration--------------------------------------------------------*/6 F3 e5 F  F1 J

  8. 0 L: s0 V, g6 }/ d% q6 E
  9.     /* Reset of all peripherals, Initializes the Flash interface and the Systick. */. A8 T0 C2 Q( a% N4 j; q/ J. t
  10.     HAL_Init();
    ! I  l; M1 E! g0 Z5 r/ |

  11. ) u. Q  r5 `) @3 I9 j
  12.     /* USER CODE BEGIN Init */
    % S! g$ R) m1 u9 W& l3 C$ o
  13. $ k- S" {* Q6 y7 G) A9 W( n
  14.     /* USER CODE END Init */, D. H# ]) j! k3 z
  15. 0 |. J, k8 p' @7 X8 ?* ~, l% J* w
  16.     /* Configure the system clock */
    + e; l( ]1 j& _/ A( F1 G
  17.     SystemClock_Config();
    9 F0 N9 ~& I! o

  18.   a- u* ?8 C( e8 k' C8 u
  19.     /* USER CODE BEGIN SysInit */
      h% z, N0 m) j) E$ m% K
  20. # Q3 }) r0 z/ ?* _. y
  21.     /* USER CODE END SysInit */
    " _5 u2 V/ {4 ^" E& N7 K1 Z

  22. 5 c$ s- G3 Y* Y% b' U
  23.     /* Initialize all configured peripherals */
    8 Z4 m* [. z, _# ^% U
  24.     MX_GPIO_Init();, F6 y5 B2 x+ K
  25.     MX_DMA_Init();
    . \. O' [# a- C/ o
  26.     MX_USART1_UART_Init();
    & V. ^$ _; i+ \: E+ n
  27.     /* USER CODE BEGIN 2 */
    1 L* E% E; t! d0 `9 H' B6 _
  28.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮
    5 {- G% o" D: t. g6 g7 a: Z7 i$ y
  29.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮& ^. D2 p% e* v5 j) A* c
  30.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮$ [4 ~  J2 ]/ n
  31.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮; m4 a1 v2 I; h. C- W8 f: m
  32.     HAL_UART_Transmit_DMA(&huart1, (uint8_t*)transmit_str, sizeof(transmit_str));    //
    ; y) h. |/ O$ _: {( Y. V+ K
  33.     HAL_Delay(5);: \3 t: R: ~+ e' r5 Y2 R5 B
  34.     HAL_UART_Receive_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, UART_RX_LEN);         // 启动DMA接收# V3 m/ m' a9 J1 c0 k1 O' \
  35.     __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);                                      // 使能空闲中断9 F% h. J3 F9 `/ d, Q
  36. ( a+ H4 S3 \9 P5 S0 f  H2 a
  37.     /* USER CODE END 2 */
    . e2 `* p1 J9 e
  38. " O7 V% a! @* w2 Z- U- H
  39.     /* Infinite loop */& R4 v1 e0 I6 M) H1 b/ P6 x
  40.     /* USER CODE BEGIN WHILE */
    8 C/ y+ I4 A& @6 T' P
  41.     while (1)
    2 a8 Q9 G0 a& }
  42.     {
    ' Z! p" g1 D( s% `: E! J8 ]
  43.         /* USER CODE END WHILE */2 p9 c4 w& k9 H( k: O+ \
  44. ) J* d# l$ a6 }; V2 h4 G# S$ t
  45.         /* USER CODE BEGIN 3 */
    2 u/ v2 L# P) ]
  46.         HAL_Delay(100);
    6 d! r8 j) d& p
  47.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);                                                                        //反转LED点亮熄灭切换* e; H/ t8 k: Z* }" ]8 X6 ~3 T! N
  48.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_1);                                                                        //反转LED点亮熄灭切换* \0 q8 n+ A1 L- P
  49.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_2);                                                                        //反转LED点亮熄灭切换
    ! S  J7 V1 K1 q* S* C! x; H% k+ `
  50.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_3);                                                                        //反转LED点亮熄灭切换
    * h) P, }% v$ A% }  Z
  51.         if(uart_rx_struct_t.uart_rx_flag & 0X80)                                //DMA接收完成
    8 r: [) J) ~7 v9 z& j; i
  52.         {# H' s( M" A  \. s7 X- g$ c8 H
  53.             HAL_UART_Transmit_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, uart_rx_struct_t.uart_len);    // 将接收到的数据发送回去
    8 W- }" t! j+ E. J
  54.             uart_rx_struct_t.uart_rx_flag = 0;
    + m, h) j% H* @7 `
  55.         }
    4 v2 X# r' b% R9 M5 ^

  56. % }2 |2 W2 q8 s* y2 ~
  57.     }5 V% y! A& t# m
  58.     /* USER CODE END 3 */
    & V0 `# V5 ]: h
  59. }
复制代码

$ S' q# x" V* y% H, N  @2 r(3)main.h相关变量声明
, s; k) y6 u% s7 i: t5 V
  1. /* USER CODE BEGIN ET */
    % t. z3 n+ B- a9 I# i% ]
  2. #define UART_RX_LEN 1024                // 一次最大接收的数据量
    4 A5 |5 o$ }* J+ S7 V' J
  3. typedef struct
    * O0 W7 T$ a  t3 I2 T
  4. {( E) B+ y) W1 M8 q. y8 p
  5.     uint8_t uart_rx_buf[UART_RX_LEN];  // DMA数据接收缓存数组+ X  l2 Q  ^4 x5 j  E* R' X
  6.     uint16_t uart_len;                 //DMA数据接收长度
    7 d3 U/ x( P5 G  c7 C
  7.     uint8_t uart_rx_flag;              //接收完成标志位# L& |! {. S/ [" C2 G
  8. }uart_rx_struct;) F5 i7 }. Q8 W' ~
  9. extern uart_rx_struct uart_rx_struct_t;  
    9 _! }0 @3 h+ w% F2 e; q$ T

  10. ( }9 L. y- C2 N5 c/ T( t
  11. /* USER CODE END ET */
复制代码

5 k+ \' l- {2 S" w$ R9 p- ]/ r4 d  d9 E4、添加HAL库UART  DMA 接收函数代码
  i2 X8 n7 W" A" j6 P& e(1)DMA接收设置前铺垫知识点:) h2 ]0 Q3 m9 e8 o
        STM32的IDLE的中断产生条件:在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断停止。
2 ]+ s1 C" o* C, o% f9 F$ U6 n  h
(2)添加DMA接收处理代码' N8 ?2 z- A# i. ^* l( @9 B

2 b. a- p: l  r# a) _
stm32f1xx_it.c中添加代码如下:, K; ]- j# x4 R, q, [* ]3 D
  1. void USART1_IRQHandler(void), E  V, a: q8 x) S1 z9 e# I
  2. {
    8 F) i) e* |, I! ]8 z
  3.     /* USER CODE BEGIN USART1_IRQn 0 */8 `8 F$ ]. z; m. l8 \
  4.     if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) != RESET)       // 空闲中断标记被置位& ~, X  e( O+ B
  5.     {
    5 \) u) n$ G8 Q, m
  6.         __HAL_UART_CLEAR_IDLEFLAG(&huart1);                         // 清除中断标记" ~; ~4 c& U( ^3 E9 i
  7.         HAL_UART_DMAStop(&huart1);                                  // 停止DMA接收
    + O. X) @1 ^9 [
  8.         uart_rx_struct_t.uart_len = UART_RX_LEN - __HAL_DMA_GET_COUNTER(huart1.hdmarx);  // 总数据量减去未接收到的数据量为已经接收到的数据量. U. N% J: `% a( B
  9.         uart_rx_struct_t.uart_rx_buf[uart_rx_struct_t.uart_len] = 0;                    // 添加结束符
      `# \0 z4 }) i5 P; f8 U  f
  10.         uart_rx_struct_t.uart_rx_flag |= 0x80;                                       // 标记接收结束9 K1 R. {  X" u" r/ ?
  11.         HAL_UART_Receive_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, UART_RX_LEN);    // 重新启动DMA接收
    ! r& O" P2 `, T, N3 _- |
  12.     }" ], s7 d5 I/ x
  13.     /* USER CODE END USART1_IRQn 0 */' [. X) L& @" L% o5 o# f
  14.     HAL_UART_IRQHandler(&huart1);4 y2 u6 U8 @9 w: i. s
  15.     /* USER CODE BEGIN USART1_IRQn 1 */( p2 `, o/ U0 {( e6 K6 I

  16. 8 W+ G5 \/ M* ^" r0 G! v
  17.     /* USER CODE END USART1_IRQn 1 */$ U6 f' W/ F2 a% `7 `
  18. }
复制代码
* ~& j+ [" z7 h% W+ t+ M" w
(3)至此,串口DMA收发数据需要添加的代码已经完成。# |1 o6 a* q) q. f; T! E" h

# H$ g$ i3 r5 |5 u5、设置编程仿真下载模式" v; F; O4 m3 d: U' d
(1)选择Options for target ...>>Debug>>J-Link/J-JTRACE Cortex,点击Settings>>选择Port(SW),可以看到搜索成功SW Device,表示芯片可用,可以下载。
( ~. ?8 p) m4 p% M$ a7 M: J, t4 `( [8 o$ t2 D9 N
9f8aa1a4e8f04041bcf5cb183facd100.png 2 s" b" E& f8 B& V  o
​/ g- v4 R; ~" B* ?$ s* _5 N5 I  z
(2)点击编译,完成后提示“0 error(s),0 warning(s)”。$ O% v% e- I4 L6 M0 v; c

/ H: F5 u0 J$ Q( X) {5 H/ u
e0b7e3e353b345a7987fe5f821de2dda.png
& |5 ?+ R; W7 e% G: E: O
3 P/ o5 S# z# g) s* N& v(3)点击Download(或者快捷键F8),即可下载程序。% U6 i8 @2 d( h4 G
7 P/ @2 c, |1 O8 |2 K8 O3 j
eb3f250f19e44862a7df80c2492fcd01.png
! E1 @) F! R6 P2 }: A​​
1 T/ ^. l, I) o! N6 q" t  {$ m: u& ]
(4) 如果下载程序后,没有看到LED1、LED2、LED3、LED4闪烁,可以按下述方式设置一下(Reset and run表示下载后自动复位和重启运行)。或者重新彻底断电再次上电(或按开发板的Reset按键复位MCU即可)。
4 ~9 K% n; [& S. P+ O, I0 x" h+ M3 W! \' e$ `

* w  N6 {7 b! T$ d ​​
3 \& A! m1 H- N+ v6、串口DMA收发实验效果展示

' R; B$ g6 v2 D. D' x+ j/ P        程序烧录到开发板后,即可看到LED1、LED2、LED3、LED4初始化后每隔100ms闪烁一次,并且打开串口助手后(串口参数:波特率115200、N、8、1),通过串口助手可以看到,开发板接收到发送的数据转发出来。2 f# R: m) q/ `8 x
$ X# w% Q) t* m, A; R) c& s/ Y
2a8f9f6486b04eeb8747ce0b09a6352c.png : }/ K+ v, [+ d4 Q' q1 W

; Z& H5 v. Q  r( K' Q3 h3 k————————————————
9 C( U6 p: J5 y8 p版权声明:智能小屋ZYXC9 |! O3 g; i+ f( [. |) e

3 S% B: g+ A) A% u5 y. Q2 w( {, k, [% |/ S: A7 Q  h/ K
edefb6b9a2a14be3b1221ad6d5c7a8a2.png
赞 收藏 评论0 发布时间:2023-1-13 20:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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