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

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

[复制链接]
STMCU小助手 发布时间:2023-1-13 20:00
一、开发板平台简介:
5 V, q- W0 b3 M3 }8 g9 B# U1、开发板资源简介
- ~! q% y  ?% E3 a( K) \. [" r
(1)开发板主芯片型号:STM32L431RCT6
8 z, O# s4 [, x6 i7 R(2)开发板主芯片封装:LQFP-64_10x10x05P( A/ \7 v2 t* N  c( |8 x* U" R2 [
(3)开发板主芯片内核:ARM® Cortex®-M4+ k. P3 a5 v& K6 W; `  A6 e  ?; s* s
(4)开发板主芯片主频:80MHz1 b7 ^& E: X3 j$ x* X; d, q* R  |
(5)开发板主芯片Flash大小:256KB0 S: W6 C' i+ x8 l- x
(6)开发板主芯片RAM大小:64KB
9 m) m& C$ [" h; F2 E/ J. J# d+ x: z! ?) H) J5 O/ L  e. v  Q
bb91345227434ee7a43a34bf3fe366e6.png # {6 c# ]& q5 a  ]- ]) a7 u
- D& E: Z/ R# ~1 s8 I3 F% Y
929c0cce04aa4115a8623703982bf3e1.png
! w& P- A$ n/ b- P- G1 ?7 g

/ U& \* b3 W  l7 O) X5 M" p. i4 w2、LED灯资源
2 V6 I( g: ~. r4 ^; q9 \( `(1) STM32L431RCT6开发板共5个LED灯资源,其中一个红色LED为系统指示灯,指示开发板供电系统是否正常,如供电系统正常,红色LED为上电常亮状态,硬件原理图如下图所示:
4 V# Q+ m. A7 K' t
4 k! c8 L& ]: w6 e6 q
0f177691c5814f16a508bcfa747f87ac.png
! Q% t  ]& e+ v. {/ @, k  v9 N$ W# ^8 ~2 q/ N
4 h9 R+ T4 g: e& R3 j& C4 v7 V
(2)其他四个LED灯为黄绿色可控LED,高电平点亮、低电平熄灭,计划用LED常亮验证看门狗的作用,硬件原理图如下图所示:
( k4 r* l6 k- O: k7 {! x
( d; B; f; ?+ g- |# C* {
e923ad767b8448b7ac37c4ed693724bd.png
1 B* I: W. s( d0 d  K6 Y) E
( Q6 V! h7 u- p) t  W5 D3 Y​3、串口DMA收发工作原理
4 b$ S$ x% H/ j7 A+ K5 m 串口全称为串行通讯接口,即数据在通信线上一次传输一位,按先后一定顺序传输。我们通常所说的单片机串口准确来说应该是串行异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART),使用TTL电平,串口需要RXD、TXD、GND三根线进行通信。( Q3 s% T2 M& @) v2 |
8 E* H0 `+ o9 l: B$ H# o
     (1)我们选用的STM32L431RCT6开发板串口1已通过USB转TLL串口芯片CH340G引出,使用时,只需要用公对公USB线连接电脑即可(注意也得需要安装CH340G驱动),后期验证试验也可使用该串口作为debug串口。
" r( C) t" _9 z! B( _7 r- v4 d
8 R7 g1 w( m- [( n" h4 \6 F0 \
     (2)开发板上的其他串口已通过排针引出,为TTL电平,通信的时候需要注意选择对应的电平模块,如USB转TTL串口模块等。
8 C/ [  m0 r* F! P( `5 G2 F* g" b+ o8 s/ Q5 e" z/ C
TTL转CH340串口,硬件原理图如下所示:3 Z8 u/ _. R; a3 c! u. C3 g. c

2 ?, R6 [+ v0 Z+ V7 `
4df1b489cb944c26b55013001061675d.png
. G+ ?+ U, s% @& ^  b& A
! ^8 W; Y/ c3 JDMA(Direct Memory Access) :直接存储器存取,是单片机的一个外设,它的主要功能是用来搬数据,但是不需要占用 CPU,即在传输数据的时候, CPU 可以干其他的事情,好像是多线程一样。数据传输支持从外设到存储器或者存储器到存储器,这里的存储器可以是 SRAM 或者是 FLASH。
- ^# W; V2 _& A0 ]5 n% R/ I
# X9 o1 g2 q3 I0 m0 XDMA 控制器包含了 DMA1 和 DMA2,其中 DMA1 有 7 个通道, DMA2 有 5 个通道,这里的通道可以理解为传输数据的一种管道。要注意的是 DMA2 只存在于大容量的单片机中。
! E/ l  `" V& }, r" f
: W( _7 O  \9 B2 o* P
354955ecc6b140049ec57af71fe199f1.png
- P, b# V# K  k+ k: S+ d0 `1 p4 B7 K: m# w( K
  二、串口DMA收发实验过程
8 a  C2 u2 r3 {0 s1 i6 L; b- G: ?1、新建STM32CubeMX基础工程

& W1 u+ Y7 h" f0 J* X(1)打开STM32CubeMX,点击“File”-->"New Project"4 ^2 Y% ]* z5 j5 z. a

/ ]5 p) I4 H+ D7 P
2399170347904e959c855fefd5877f84.png
$ K% V" m1 Q. s# k+ C- i4 i1 \

; v. v  u, N2 R(2)等待打开主芯片选项界面(大约1分钟时间)。
9 J! C/ M, j7 o7 C' U, `+ {9 \
) o0 a, F' v" L0 p  i
d74d2fdc60c9440483e2b7cf8d928e7f.png
' m, }# ^5 u9 m7 y: T$ z( x! i# z( r& n5 g8 J
(3)昨天搜索框中输入(或选择)所需的主芯片型号(因为我们用的是STM32L431RCT6开发板,所以此处选择STM32L431RC),然后在右下角选择STM32L431RCTx(因为开发板主芯片是STM32L431RCT6),左键双击即可打开新建的项目。
, \" {: T; u9 Z  I8 @& m% C  B  D7 p6 L) c% n1 C& _6 @3 b3 K
7b80345238d74bea82ce70e1a348f7b4.png
9 X+ t( O; N8 q1 ]5 I! h& o$ b5 H; [/ P% J2 \; e' I  d3 [
(4)选择时钟源。4 _4 H; O. U0 \
7 F# R2 w3 U  R/ V6 H* |6 h% W. P$ Q
        因为开发板上有8M外部时钟,硬件原理图如下所示,所以此处选择使用外部高速时钟(HSE)。$ E- ~0 ?. b" ^4 e# Q
/ J  _  e7 T; N" S0 Z+ i
3f65707eca104663a3dede6d25dfa961.png " |; w+ f+ `- F; \, L5 M, u& h/ x
1 n* {: r8 F5 W' d: c9 I

# t. P3 i. H8 |" x! G        因为我们没有用到外部低速时钟(LSE),此处不做处理,如下图所示。
7 m( M, j! Q: n4 s! m& ]2 Z8 Z  A, H! P) t# N8 |0 W  o
72119b971f62410fa8344f7f9fb9f389.png
2 F2 {& S' e/ G0 L; H8 x2 W4 H/ c5 H" ?! J
2、配置GPIO控制LED& c! U8 A* ~7 \2 J1 g9 e4 v/ F
(1)查开发板原理图得,LED1、LED2、LED3、LED4的控制引脚分别为:
0 K* |. b% X( {0 ~5 _9 U0 aLED1——PC0. x. r( V, r3 F  u% Z/ V
LED2——PC1
% {5 q; K# T7 K  T. O- SLED3——PC2
. A, A  X( \. F8 D" t/ N( H2 G% VLED4——PC3' T; S  R) N- W6 g  I, _# n$ l
! }( y& ?; ]: |! y8 h6 g* F2 j
(2)配置LED的控制引脚为输出,输出频率、输出方式默认即可。
2 g9 w# i% g  r2 @
% K7 T$ A! Y6 X( R; b鼠标左键点击PC0,选择“GPIO_Output”,表示设置该引脚为输出模式
( h; a" r8 ~# ?9 p$ ^5 [3 |鼠标左键点击PC1,选择“GPIO_Output”,表示设置该引脚为输出模式。
  Z6 n& S- G$ O0 }% |' _- v9 m. [+ ]鼠标左键点击PC2,选择“GPIO_Output”,表示设置该引脚为输出模式。
2 ^: ?4 i3 N9 z' J5 F8 d鼠标左键点击PC3,选择“GPIO_Output”,表示设置该引脚为输出模式。  K0 j! |4 x7 w: ^* E6 e
) w8 o- S4 r' S" n& E, f4 ?4 S
492907c1e71149819adbaee4516a2af4.png
% R. j3 E9 A+ a
1 [0 v; H# ?4 T" K8 z4 p% G
c75d3f10ba2e427d9c1a10fad9bf5471.png
; n; b5 n0 b- i0 M0 J# a
7 x' l  G# G; `4 X/ D% p4 ]. ^$ j(3)也根据自己的需求配置GPIO的参数,如输出方式、输出频率、上拉下拉等。因为GPIO控制LED的要求比较低,此处采用默认参数即可,不用修改。
6 H" O5 x4 w$ `  o8 n; i: ~1 r: r& u# J6 {% d. _2 \
38ff4b80e1c5495ba3076a5158fd91fa.png : e# V6 C1 L: O2 ]2 t/ r+ f/ M2 Z
5 T* N! d9 b; x& T8 b
​​3、配置PA9、PA10为串口
# @/ l% g7 n6 N8 K(1)查原理图得知,串口1使用STM32L431RCT6引脚为PA9-USART1_TX,PA10-USART1_RX,引脚设置如下:, s) M2 X; g) U" g: K+ O

8 R* S/ |2 L) Z% I0 A8 \4 ^
497b8ee0243e446784e64a3c31e8a26f.png , s: K2 m! v& J- L
7 f* @* G5 H- `4 B/ t
序号1用来设置串口收发引脚的选择。: e- L/ j; E0 J1 n; Z+ H; f
序号2-3-4-5-6设置串口参数,如波特率115200、8位、NONE无奇偶校验等。% h( |( c/ G" g9 {: G; Z

7 z" S: B1 G: R7 {5 d5 p8 C% Q0 o(2)设置NVIC settings 使能接收中断
  U% `* E% H* N+ }! y" W2 y( C$ Y' \$ X. ?$ A
f9d7783b08304465815834f4d2095571.png
9 ~4 a" F0 v+ f+ ]3 x
5 q" V( P. _. @8 W5 H4 z: m3、串口DMA设置 9 |  P! V, N6 I9 f4 P
7 Z- H5 A, X4 B
6d26b13dd9d34039a2b426ca47680f8c.png # W! Y+ a' W  }7 I- |9 R/ Z0 T

2 W' e7 Q" ^8 N1 g& y(1)根据DMA1通道预览可以得出,我们用的串口1的TX、RX分别为通道4、通道5:
  T* l, `4 g9 S" u/ o" Q, l  t点击DMASettings 点击 Add 添加通道$ s# |7 L9 s7 W, E
选择USART_RX USART_TX 传输速率设置为中速
# K1 Q: }8 R: \  iDMA传输模式为正常模式,即发送一次就结束。. i1 f7 C4 L! D
DMA内存地址自增,每次增加一个Byte(字节)  V  r7 V5 _0 i4 l4 k6 T
& d! M5 T! G9 {# H, N5 B6 a% g
976712e0494a4482bf65c69fc09fcabd.png + y! `; G6 g% H, b* ?, Y; D
$ G& P* J3 O0 y4 |% g5 `
(2)DMA相关参数解析
0 s# @. z9 \3 F3 i1 _  V4 T" qDirction : DMA传输方向有四类; l% q+ s; G5 R$ ^+ @
外设到内存 Peripheral To Memory
2 W, |+ N9 J2 b  R  `) `4 N内存到外设 Memory To Peripheral
# O$ u' r7 F8 d! Z! _+ B内存到内存 Memory To Memory6 a( _; M7 W; }
外设到外设 Peripheral To Peripheral
0 p' U/ V2 x3 i5 Y& {7 J; `9 w! S6 ]8 I% \; b- y1 p; _* \
Priority: DMA通信传输速度有四类
) j' v4 u& w5 N  v最高优先级 Very Hight' B7 c/ ^" J* `
高优先级 Hight
3 v) N" W! P: i& k# \& }8 F中等优先级 Medium2 F+ b& o3 ~: p. K2 h* ]7 I# Q
低优先级;Low
; [7 h3 F6 [' g3 F- q
9 O) ^, r. y. u% P  @/ n
Mode:DMA传输模式有两类3 W1 O# N5 c) t5 ?

9 o3 m7 N; J4 T/ J
9021c11fed3e4c1885477e062b846258.png
" J) V2 w, d% `3 Y1 g' s
& `- U. q0 ]3 d: B: p$ fNormal正常模式:当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次。/ t" `. ~) r, V% L$ T1 v' z0 g
Circle循环模式:传输完成后又重新开始继续传输,不断循环永不停止。0 b/ o# M* {7 K) R

0 o5 x% s6 P1 m0 J
Increment Address-DMA指针递增设置:& B. {) v4 V8 d: y7 _) E

$ O' N$ @0 O- s: y; D
2b1a952d6514444e9dbb019a9ae88c42.png 0 Z. |  @& Y" W! p4 A4 D
9 i5 f( w9 T0 g9 k8 {* @) x+ f
& t* O% I4 u" s
4、配置项目工程参数
- S" H  ?$ e# [5 ]" W(1)配置时钟树,用于系统内部时钟,以及各个外设时钟等。此处选择外部8M晶振作为主时钟频率,内部最大倍频80MHz。, G; k: r& g/ K$ C

5 s  ]- }" V* Q8 D
f3ecedd9323f4463b69539906b3c1199.png 6 I; c2 L8 _: N$ Y" p
! e" G' ~( p+ j9 p3 P
(2)完成配置工程。" [% z5 ?% J; T  s& f, ^
备注:需要注意代码生成过程中的继承关系,如图所示:需要保留开发者自己编写的代码时,请根据配置设置,不然生成代码后会删除自己编写的代码(从这个方面也可以看出开发者备份自己的代码是多么的重要。)( t! a/ V7 X2 i* ~/ V

  f! E. @' v7 o$ J& Q0 S/ g- B) ?
efdb616174f54925b6eac31109f227b5.png 2 `8 L! Y9 i! ^6 B9 ]& ^% z8 O2 j. @
. e9 }: v# M3 B. U! J# t: J
41c3f2716e4e4eda8f62fa3a1d871322.png + G9 p. M/ ?3 ~, r
; M. t) z( ^7 V. k" Y4 y
(3)生成代码。
! h& Y; L7 {& n$ ]5 [9 j( S
" Z, a" R" D; Z3 s1 j4 T% Q备注:使用Generate CODE生成工程代码前,请确保文件路径无中文,否则会生成项目失败。
# d. v2 `2 \9 V, u5 ?
. ]& o$ o$ x# p
8eaa7d0babea40ee93f158481a6ee471.png + v; v1 r7 \- e( c7 e# ^" y, \5 l$ d1 a
* D, ^, x1 O' N4 Z9 e, M
(4)工程代码生成成功。
2 }/ e4 Q: I( r% G& y6 I6 l; g* h1 \  v: q
e8f46d59a1fb4af589feb613fdff17b4.png
; {+ S+ E; u9 F# B' ~. e5 i& Z; r- n) r1 d
三、在KEIL 5中编写代码
7 s; ~  _' l% c$ M1、使用KEIL 5(MDK)打开项目工程文件
0 }+ u( p/ L% a, y$ S源码使用说明:使用前必须把项目工程复制到无中文路径的文件夹下使用。9 l6 f9 n8 Y& d! l
(1)找到刚才新建工程的存储路径,安装项目名称,打开项目工程.uvprojx。
4 i( a) _. S7 u1 P3 F4 s) F; h, {0 o' H
a2198e7b52e642bdb05a708c7fb8061a.png ! f) C$ _, v2 V4 A4 d
8 |0 |6 m" [9 u3 U) b. S' {
2、添加LED指示灯作为系统提示
- y) T2 v, q: e& L' A添加每隔100ms,LED1、LED2、LED3、LED4闪烁一次的系统提示,用于提示程序运行正常。+ d& B5 G' V( N! H1 P. X5 Z
$ g) v4 E# W" V/ ]* R0 z
2af9ef3cfaab45988c810d94d801fc34.png ( k0 v4 k: D7 v. n/ ~
) \* ]% I3 v! R" s) C+ a8 P
3、添加HAL库UART  DMA 发送函数代码# O' x; x3 z; n$ I. @- @( [! k/ |
(1)STM32 HAL函数库的串口DMA相关函数如下:! b( U7 J5 W8 R; z! m
  1. HAL_UART_Transmit();串口发送数据,使用超时管理机制1 {  h/ G1 \3 L/ T4 s5 \4 ^+ E1 {  x
  2. HAL_UART_Receive();串口接收数据,使用超时管理机制" k/ r' I! X" Y0 t" b/ h
  3. HAL_UART_Transmit_IT();串口中断模式发送8 _+ f; K0 O8 k" P- y* V0 V
  4. HAL_UART_Receive_IT();串口中断模式接收9 L9 l. i: Z* V7 h  o% }5 D0 j
  5. HAL_UART_Transmit_DMA();串口DMA模式发送
    ! i! X6 T' ]$ A/ s/ R+ _! N2 k# D
  6. HAL_UART_Transmit_DMA();串口DMA模式接收
    . x$ D" L2 P! l9 V& N; U; Q
  7. HAL_UART_DMAPause() 暂停串口DMA
    3 c0 o( M4 X9 E/ g2 l1 r! A
  8. HAL_UART_DMAResume(); 恢复串口DMA
    . O6 K0 S% M% z3 I8 r
  9. HAL_UART_DMAStop(); 结束串口DMA
复制代码
9 j/ I& y+ B1 F
(2)main.c添加串口DMA发送函数相关代码:
  a7 ?; ^8 K2 H" Y% o$ b. n
  1. /* Private user code ---------------------------------------------------------*/
    # n4 ?8 x+ n& x6 |, m
  2. /* USER CODE BEGIN 0 */
    0 q1 B8 M( |% h: H. q3 r; }
  3. uart_rx_struct uart_rx_struct_t={0};                                //串口接收数组
    1 J( L2 g: u6 Z$ F9 }: m
  4. /* USER CODE END 0 */
复制代码
  1. int main(void)
    % h" j# Y) q) Q  i8 Q4 b# y
  2. {. V2 Y! y! O* Q9 O% X, n% E: \
  3.     /* USER CODE BEGIN 1 */  J6 d; @* X! `3 W; f  H) j% B
  4.     uint8_t transmit_str[50]= {"hello world,this is uart dma function!\r\n"};
    1 d8 W( X# ^+ m0 @, L
  5.     /* USER CODE END 1 */
    * z0 I0 e4 l- Y3 J6 }
  6. & P4 W/ m) E; {# ^% a* A6 J
  7.     /* MCU Configuration--------------------------------------------------------*/' E8 A7 S; Q4 k1 J8 H! F
  8. * U4 f+ t+ F. k9 q8 Z$ f
  9.     /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    - }; d. P  D' Z
  10.     HAL_Init();& S* {0 _" N9 o2 A; v3 P7 y- S- o

  11. : v! k+ T: C8 {3 {, ?
  12.     /* USER CODE BEGIN Init */: u! k% W) O* A9 M

  13. # l9 w0 W0 J( Q
  14.     /* USER CODE END Init */
    7 D5 m; u+ k! [, y3 ~- O

  15.   j" c* X4 Q0 V; B+ t- x( ~
  16.     /* Configure the system clock */: O# l3 j% I) v2 f; ~7 S: o5 {
  17.     SystemClock_Config();5 x6 n7 }: h  x
  18. . ~2 S$ o; c0 Y/ S0 [* N
  19.     /* USER CODE BEGIN SysInit */
    % k6 b! I3 ]/ L! l6 h) f& G
  20. , j6 O% q# g9 s5 h, ?
  21.     /* USER CODE END SysInit */, _$ t, p( S- J: n0 `
  22. " u8 ^2 J% M9 w, |! Z
  23.     /* Initialize all configured peripherals */, I- P: B  ?. C0 {& M
  24.     MX_GPIO_Init();
    " V) S# [+ J8 |, G, _9 F9 r/ Q- s  R
  25.     MX_DMA_Init();6 j; K# i: H# ^
  26.     MX_USART1_UART_Init();$ [: U  Q  |/ v8 l! }5 T) [
  27.     /* USER CODE BEGIN 2 */
    ! o3 a0 n( y. Y
  28.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮
    & E3 }: [4 V7 `! E; [
  29.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮  k& ?  Y; M; e& a; ^
  30.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮: t% X- k5 q" [* X& ^, k5 J: a* J
  31.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮
    & _5 u& \9 R( x+ h8 X: B
  32.     HAL_UART_Transmit_DMA(&huart1, (uint8_t*)transmit_str, sizeof(transmit_str));    //
      G+ Z& c9 h0 L( Z# f" f2 g* Z3 e
  33.     HAL_Delay(5);
    6 `$ ~6 U& J% n/ o
  34.     HAL_UART_Receive_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, UART_RX_LEN);         // 启动DMA接收
    & S$ q2 k) N' D$ ?# M
  35.     __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);                                      // 使能空闲中断; A# C- a1 n; m+ Y+ f) y
  36.   O/ n$ w/ m6 B1 i+ J( W
  37.     /* USER CODE END 2 */- H: E' B0 K5 ^" H% T  R: [/ c

  38. 0 h6 n4 [6 F0 v' t
  39.     /* Infinite loop */  \6 q+ h; r2 h+ b7 A& C& U
  40.     /* USER CODE BEGIN WHILE */
    . q0 S) M" @- _7 }; K  @5 y: r
  41.     while (1)
    1 g# h: v6 e9 [) |( h8 B: j( k7 {4 p; Y
  42.     {# [( y9 `4 P4 _) h, a$ k; G3 w8 D
  43.         /* USER CODE END WHILE */. L3 P+ ~* C7 ]3 u
  44. - C' {% w  h3 G! W6 F% U
  45.         /* USER CODE BEGIN 3 */
    ) e' k9 B/ F& g3 p$ F
  46.         HAL_Delay(100);5 r1 g- f6 v7 L( }
  47.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);                                                                        //反转LED点亮熄灭切换* y6 E* _' T% E: Z
  48.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_1);                                                                        //反转LED点亮熄灭切换9 S+ ?) @# g* [& I) l
  49.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_2);                                                                        //反转LED点亮熄灭切换
    6 o2 ]! x8 H; |3 O& ^
  50.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_3);                                                                        //反转LED点亮熄灭切换
    0 i7 p2 u5 Z& N7 g! f' m1 E
  51.         if(uart_rx_struct_t.uart_rx_flag & 0X80)                                //DMA接收完成, G3 B/ V% G# Q" ?4 G, j
  52.         {/ B6 q$ X9 t( G- |1 b% b5 q% G
  53.             HAL_UART_Transmit_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, uart_rx_struct_t.uart_len);    // 将接收到的数据发送回去
    : p/ w: v3 V) T/ _7 ?* r
  54.             uart_rx_struct_t.uart_rx_flag = 0;
    3 k8 t6 D2 P. k2 K3 O8 F
  55.         }
    ; G9 ~5 O6 `- s- x" t  S) s

  56. ( b, }8 G' {( p. Y4 o
  57.     }2 o) K  a) C- O1 I! b: N5 n" Z
  58.     /* USER CODE END 3 */
    2 U# d4 W$ {9 \" t
  59. }
复制代码

. o2 J: j7 f1 |& \* s(3)main.h相关变量声明
( O. R% Q4 M3 J7 Z& C; ~% m3 n. y
  1. /* USER CODE BEGIN ET */$ ]4 \. C4 n. F8 _
  2. #define UART_RX_LEN 1024                // 一次最大接收的数据量- n# A) }( r5 t, k
  3. typedef struct6 i# n  V( x1 m( I
  4. {/ E& y5 u! q% q/ l8 D/ u
  5.     uint8_t uart_rx_buf[UART_RX_LEN];  // DMA数据接收缓存数组
    ; X; f& b9 t9 E+ d- S
  6.     uint16_t uart_len;                 //DMA数据接收长度
    $ c8 }; `- w1 C1 K  l# c  B
  7.     uint8_t uart_rx_flag;              //接收完成标志位4 ?8 P6 R' i! D! X
  8. }uart_rx_struct;5 d; f* R; e) h2 b1 z+ Z' V
  9. extern uart_rx_struct uart_rx_struct_t;  
    * p; m) {" ]4 ?/ j

  10. ! @$ ~: U3 Z  M  @( B, W
  11. /* USER CODE END ET */
复制代码

) D# }% U' b6 g( d2 z4 a5 X1 r4、添加HAL库UART  DMA 接收函数代码5 x1 i- S# S5 `: a
(1)DMA接收设置前铺垫知识点:
( h5 a7 e% i1 O        STM32的IDLE的中断产生条件:在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断停止。4 @1 ~5 ^3 m! o+ M4 j
  L3 {; V: i2 y  q, w; X
(2)添加DMA接收处理代码: ^7 R6 }5 X6 u3 ]" D6 u& T

! y0 z" s! i& p# x, q1 _& g% M6 j
stm32f1xx_it.c中添加代码如下:& g7 M, G3 @9 o  r, s/ w
  1. void USART1_IRQHandler(void)' M) l9 m5 C7 X7 ^( g* I- U
  2. {
    0 [' i9 Q9 T6 y- m; x! `
  3.     /* USER CODE BEGIN USART1_IRQn 0 */
    3 f5 _& R; [8 e& I0 g* b
  4.     if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) != RESET)       // 空闲中断标记被置位3 T  E- y( m  J
  5.     {
    9 U; L! N2 u9 X
  6.         __HAL_UART_CLEAR_IDLEFLAG(&huart1);                         // 清除中断标记
    5 m1 R3 l( f. E5 t+ b
  7.         HAL_UART_DMAStop(&huart1);                                  // 停止DMA接收( ]& K2 t2 y! J' i
  8.         uart_rx_struct_t.uart_len = UART_RX_LEN - __HAL_DMA_GET_COUNTER(huart1.hdmarx);  // 总数据量减去未接收到的数据量为已经接收到的数据量. [; ^! u; y: A6 W& K/ y
  9.         uart_rx_struct_t.uart_rx_buf[uart_rx_struct_t.uart_len] = 0;                    // 添加结束符! C9 k8 B2 j; X- K
  10.         uart_rx_struct_t.uart_rx_flag |= 0x80;                                       // 标记接收结束: t7 N8 |+ l( n' A0 ?7 [, _8 s& U( G  d8 z9 q
  11.         HAL_UART_Receive_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, UART_RX_LEN);    // 重新启动DMA接收8 e! s, U+ E$ r# |: ~: Q6 v
  12.     }+ W9 B4 G2 b& W
  13.     /* USER CODE END USART1_IRQn 0 */
    ) e! a8 {" g2 V+ q$ L" b0 s
  14.     HAL_UART_IRQHandler(&huart1);
    ; @0 f6 n2 F- u: R# T6 ~) ^! ]5 X
  15.     /* USER CODE BEGIN USART1_IRQn 1 */
    ' s; ~# `  L# B) X9 Q3 s

  16. 1 w5 E$ Y( |  s: p
  17.     /* USER CODE END USART1_IRQn 1 */. u% F9 E# L1 V. V6 {* O8 Z( c
  18. }
复制代码
6 R5 a$ x. K# J3 A7 m$ s
(3)至此,串口DMA收发数据需要添加的代码已经完成。
0 W- X$ ?  f3 i# b

( C, g0 y9 ^3 [0 h5、设置编程仿真下载模式2 i  r# M9 @8 o+ {, p/ q
(1)选择Options for target ...>>Debug>>J-Link/J-JTRACE Cortex,点击Settings>>选择Port(SW),可以看到搜索成功SW Device,表示芯片可用,可以下载。* e! I" g' F1 |( I

! {5 Q7 ~% ^. b& X9 [
9f8aa1a4e8f04041bcf5cb183facd100.png & Q/ v) E+ N& S

; t8 F  ^! {, ]/ m(2)点击编译,完成后提示“0 error(s),0 warning(s)”。
7 q3 s$ A  c+ m* i: y
. w  W# P# G0 k' b$ `& M3 d$ [( D& j+ u
e0b7e3e353b345a7987fe5f821de2dda.png " c. |0 r9 J- Y3 ?7 S

, ]7 Z3 ^& e8 g(3)点击Download(或者快捷键F8),即可下载程序。/ S2 M# W! K- O: Z3 D

5 n: R1 T/ l/ u4 B" }( e
eb3f250f19e44862a7df80c2492fcd01.png   }* R+ s5 Q; q& \  n3 n
​​
2 J8 j9 w% w5 b9 x5 m) c, c
# L7 q+ F4 W- G. w5 C% C(4) 如果下载程序后,没有看到LED1、LED2、LED3、LED4闪烁,可以按下述方式设置一下(Reset and run表示下载后自动复位和重启运行)。或者重新彻底断电再次上电(或按开发板的Reset按键复位MCU即可)。4 F; I  u/ L+ U* r2 `0 W" Z

* K- L1 e' r3 S7 ]

# Z) V# l9 B: `1 H! S8 ] ​​
& M6 [2 p* ~+ D) J4 }- r) L( [6、串口DMA收发实验效果展示

, w7 G( G1 D& E3 F- C8 P, e        程序烧录到开发板后,即可看到LED1、LED2、LED3、LED4初始化后每隔100ms闪烁一次,并且打开串口助手后(串口参数:波特率115200、N、8、1),通过串口助手可以看到,开发板接收到发送的数据转发出来。; u& M( @! L' Q4 |1 c4 ]

! x* _4 b4 s2 e) b
2a8f9f6486b04eeb8747ce0b09a6352c.png
! i% B( [8 Z  l* ~  ]" O
5 U& i3 R9 |5 W9 S0 G4 @8 q————————————————; c% M' O  P9 V7 B8 Z
版权声明:智能小屋ZYXC( S4 a- y1 G7 L1 t* x
5 B! F9 z% N. j3 p9 ~5 A
# g; h, g1 [+ H3 Q& X. ?
edefb6b9a2a14be3b1221ad6d5c7a8a2.png
收藏 评论0 发布时间:2023-1-13 20:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版