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

【实测教程】STM32L4之收发实验

[复制链接]
STMCU小助手 发布时间:2023-1-13 20:00
   一、开发板平台简介:. w. v7 _4 a* J. J1 O& K/ B8 O2 W: J
1、开发板资源简介

8 f9 a' i! i0 k% ^6 l$ R7 z(1)开发板主芯片型号:STM32L431RCT6(2)开发板主芯片封装:LQFP-64_10x10x05P
3 ~# B  B  T. Y1 o(3)开发板主芯片内核:ARM® Cortex®-M4
- I$ h" v4 q1 ?) i" L(4)开发板主芯片主频:80MHz
. ?* ~0 n! \$ n(5)开发板主芯片Flash大小:256KB
9 ?/ U2 ?2 y& ]' |(6)开发板主芯片RAM大小:64KB% f( I+ q6 v) H0 r' l( [) a
6 m( X/ o+ B4 b2 L
bb91345227434ee7a43a34bf3fe366e6.png   x  O; ^- N/ q1 A

; h3 u: Z0 ^  T3 s: A0 P% v# Q- V
929c0cce04aa4115a8623703982bf3e1.png + U$ W. s; R3 p  T0 {
  ~! a. u( a  f9 V* m

# p' @/ l& r0 m; C1 K. d# C- \2、LED灯资源
1 |  Z( L1 @! q+ Z5 T6 Y(1) STM32L431RCT6开发板共5个LED灯资源,其中一个红色LED为系统指示灯,指示开发板供电系统是否正常,如供电系统正常,红色LED为上电常亮状态,硬件原理图如下图所示:
0 X/ J" h! q" D
9 S0 l/ r6 b: i2 p! `
0f177691c5814f16a508bcfa747f87ac.png
/ |5 A' R4 o- \% _2 P
* k2 k- d. o5 i(2)其他四个LED灯为黄绿色可控LED,高电平点亮、低电平熄灭,计划用LED常亮验证看门狗的作用,硬件原理图如下图所示:
7 z. l+ y. t4 a$ F9 {; R/ s7 ~# y* F2 |( n( S% H5 S
e923ad767b8448b7ac37c4ed693724bd.png
  f/ Y* Z9 h. L
: m, t9 B& q5 m/ w" R3 }
3 T8 {) P/ u- ?3 ^" J: n% e​3、串口DMA收发工作原理
! M, e' ]7 Z1 O) F9 b+ q        串口全称为串行通讯接口,即数据在通信线上一次传输一位,按先后一定顺序传输。我们通常所说的单片机串口准确来说应该是串行异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART),使用TTL电平,串口需要RXD、TXD、GND三根线进行通信。5 M7 g7 t$ A% b7 D8 U% p

/ p$ ?  a, @1 Q. F  u# j    (1)最常用的RS485收发换向方法是程序换向,即由MCU的一个I/O端口控制RS485收发器件的收发使能引脚,在平时使RS485收发器件处于接收状态
8 i& Q, ?9 h- f( T* Y) D" ?
2 X% ]4 e8 ~- P     (2)我们选用的STM32L431RCT6开发板串口2作为RS485通信的串口,PA1作为RS485串口收发的使能控制引脚。
( g# |$ e. _- l( J' b7 W
8 n# }. h# Z5 c     (3)RS485端口使用时,需要使用USB转485模块和开发板进行通信,使用方法为USB转485模块的A接开发板的A,USB转485模块的B接开发的B,GND可不接。
0 b% x6 I* ~9 X2 v$ T6 z, u, W* t) E1 a6 a5 C9 Y
RS485串口,硬件原理图如下所示:
8 l0 d% S+ M. R
: _8 n6 V, Z% ~3 _
1f72998fadef42548ee482c9fe064c08.png
! g) U! w+ p7 O; [9 {( Z: f: F( h% K9 }8 N! f5 P- ]
182841b93d1e40b0913e3a54b22d0704.png : K, @" F- F. i5 `. h

5 |0 ^& Y$ S! t: N7 JDMA(Direct Memory Access) :直接存储器存取,是单片机的一个外设,它的主要功能是用来搬数据,但是不需要占用 CPU,即在传输数据的时候, CPU 可以干其他的事情,好像是多线程一样。数据传输支持从外设到存储器或者存储器到存储器,这里的存储器可以是 SRAM 或者是 FLASH。: M: g, f/ c0 g8 o) @
, ?* H/ _. x8 @; a
DMA 控制器包含了 DMA1 和 DMA2,其中 DMA1 有 7 个通道, DMA2 有 5 个通道,这里的通道可以理解为传输数据的一种管道。要注意的是 DMA2 只存在于大容量的单片机中。1 ]6 ]6 t) K3 K* b  p  z( d
* G" M" x5 Q! t% C' {# H) t  ?/ C1 a
354955ecc6b140049ec57af71fe199f1.png
! ^5 M; C8 z- X' |( F
1 F$ }$ y9 N# \+ D' e& f6 g* L  二、串口DMA收发实验过程
8 f1 s* k/ _6 j0 Y2 N1、新建STM32CubeMX基础工程

+ J, x* _. Y, V) P(1)打开STM32CubeMX,点击“File”-->"New Project"
5 J9 `& p& R' ~9 [4 z% A3 `( H  ^
2399170347904e959c855fefd5877f84.png
8 g1 k% q2 t( n; R5 Q2 H
+ g6 v, [/ K6 D(2)等待打开主芯片选项界面(大约1分钟时间)。
; H6 {; G* D; W4 g2 K- L$ ~9 ]$ Z: U' @; W' x6 d
d74d2fdc60c9440483e2b7cf8d928e7f.png 9 T* i) _. `: V% a5 ~

  F' o/ g5 J2 C* C. _3 ~(3)昨天搜索框中输入(或选择)所需的主芯片型号(因为我们用的是STM32L431RCT6开发板,所以此处选择STM32L431RC),然后在右下角选择STM32L431RCTx(因为开发板主芯片是STM32L431RCT6),左键双击即可打开新建的项目。3 O* M1 T6 N- L% s# K! q5 w$ e

' p- }+ a' W; r$ `9 O9 o% b+ k

6 m: i. d2 z, U: ]) n) `8 v3 s  ?% I 7b80345238d74bea82ce70e1a348f7b4.png
) P& u4 ~1 Z% e8 ?  p! h
) J4 M9 j/ {% I) S6 |
(4)选择时钟源。
- F" ]) I' D% I; V" _        因为开发板上有8M外部时钟,硬件原理图如下所示,所以此处选择使用外部高速时钟(HSE)。
  n1 X1 ^1 g( s; o& c
! {+ ?6 T' H/ |# P
3f65707eca104663a3dede6d25dfa961.png 8 ?# E; C2 c8 b/ {9 l$ S2 Z5 Q
% y3 q5 }/ R5 r! J" B
        因为我们没有用到外部低速时钟(LSE),此处不做处理,如下图所示。
3 F' i# s2 @6 F1 {0 z2 O; [+ r* d0 x, u3 A; O4 \+ q0 v
72119b971f62410fa8344f7f9fb9f389.png
7 u$ n9 W8 S. N0 c  h: V3 t4 h( n

% |2 L4 i) [+ D7 k% Q# d: w2、配置GPIO控制LED
8 f0 Q* y6 t" I; h7 |6 g$ g/ L(1)查开发板原理图得,LED1、LED2、LED3、LED4的控制引脚分别为:( C* @. D  o0 a
LED1——PC0
7 B# t1 q( D$ y, Z$ e5 pLED2——PC1
6 D1 y- C8 Y& R: _LED3——PC2
% f$ M0 C3 f! T7 I( ULED4——PC3
& ]' T  R/ E9 V5 X! g# u- f. ]7 u/ R  r; `* ~8 c7 W7 t/ W
(2)配置LED的控制引脚为输出,输出频率、输出方式默认即可。, @- [$ ?) b5 n) S) q' }
鼠标左键点击PC0,选择“GPIO_Output”,表示设置该引脚为输出模式。
( q. {' s; x4 ?) L4 Y- x鼠标左键点击PC1,选择“GPIO_Output”,表示设置该引脚为输出模式。
1 K% T, x' V. L8 x1 D: j& Q鼠标左键点击PC2,选择“GPIO_Output”,表示设置该引脚为输出模式。' a- m. C. q( x6 I# ?
鼠标左键点击PC3,选择“GPIO_Output”,表示设置该引脚为输出模式。
9 _! |" Z* E/ P" o. W5 t/ L. M) c! }7 E2 \- W# O
492907c1e71149819adbaee4516a2af4.png ' n7 T  L! e% J" q" X3 ?

7 I3 ~' ^$ p7 O9 ^2 N* j. F0 g; M
c75d3f10ba2e427d9c1a10fad9bf5471.png $ J* v* i. f6 ?, u2 r$ K  D9 J/ D4 Z
, F3 q1 r5 V* h
(3)也根据自己的需求配置GPIO的参数,如输出方式、输出频率、上拉下拉等。因为GPIO控制LED的要求比较低,此处采用默认参数即可,不用修改。* x; g6 v+ I# z( a

# u1 v6 p( ?0 F
38ff4b80e1c5495ba3076a5158fd91fa.png
+ K  D8 \3 j5 p0 X  {! p/ f6 d* l5 p4 R1 K  P7 f5 Q
​​3、配置PA2、PA3为串口( u" t3 Y) V9 W2 @
(1)查原理图得知,串口2使用STM32L431RCT6引脚为PA2-USART2_TX,PA3-USART2_RX,引脚设置如下:
& \  o% l% p/ o) Q. i
; o% @- A) \1 ^: \# N5 P. r! s
9bd645a9032647d280107cc82b5a0f67.png ' ^" g" [7 T$ ]/ u$ a) |8 ?- v
" j8 @" V- R/ ]/ Y* N# F; V
串口参数默认即可:波特率115200-N-8-1,并使能收发控制引脚。
3 r0 G  J" m( A* \4 a5 v2 S. a$ ?9 e: ?) h0 f
74f5d7878df343ae83c9af5ed79c6a7c.png
: U4 v( d6 ~* G
6 m1 R0 ^4 Y/ z0 {1 k5 N
(2)设置NVIC settings 使能接收中断。
0 }  c: ?5 g- I& P% q; N' B& q5 @# A' A- y; N  V  J
fde3c5c1ac9d4896b40dc5f5e15c3e61.png
6 Q' c& ~% `5 m6 R6 P! J1 U: N6 j

8 E3 h3 [2 c0 m  t) B: E! X% R3、串口DMA设置 ' `2 {/ v: y6 k5 f' P. J! ~( A
. g! `! F0 W2 l! l
6d26b13dd9d34039a2b426ca47680f8c.png , L9 k9 o! }2 [
  q2 T5 p: G7 G2 d: t
(1)根据DMA1通道预览可以得出,我们用的串口2的TX、RX分别为通道6、通道7:/ F9 m* T0 L  r7 i# k- x8 N, U( `
点击DMASettings 点击 Add 添加通道3 c1 P) ?" y( E9 M* `
选择USART_RX USART_TX 传输速率设置为中速
& l. D2 f0 O1 VDMA传输模式为正常模式,即发送一次就结束。
7 w3 Z" P5 @& G7 _2 H; eDMA内存地址自增,每次增加一个Byte(字节)4 w- C4 h. _9 N3 g

8 }& F: F3 K9 i
55bd687bfb1c4640847f6cba6ea373b9.png
) i8 M$ V- X: a/ ^4 W( [+ {
% R0 q; {4 r8 Z# ?; F) V4 ?) e (2)DMA相关参数解析& j. g, Z1 v$ ?( M" e5 z
Dirction : DMA传输方向有四类' e' p1 r$ W0 n. \9 k
外设到内存 Peripheral To Memory, b+ ~7 g% w8 u. k1 n
内存到外设 Memory To Peripheral' z0 A2 v0 W1 ?2 P# w; w
内存到内存 Memory To Memory
0 U. X% W4 {# y" c外设到外设 Peripheral To Peripheral& h/ f# o, {/ J8 @
: M1 m2 [8 Z4 `2 P
Priority: DMA通信传输速度有四类+ G$ V- [6 U8 A4 u
最高优先级 Very Hight
& U" ^7 p, J! U/ I( V# k高优先级 Hight9 @/ B& G2 X: c
中等优先级 Medium
1 @, O) E8 J- Z! c, f* e. @低优先级;Low+ {- e, a8 Z6 j2 O

8 L+ J) A+ Z( z9 B& G- ~
Mode:DMA传输模式有两类
8 U; C4 v3 Z' [
5 R( b1 A+ ^3 ^: H- @
9021c11fed3e4c1885477e062b846258.png 5 U( K* R; r7 H
4 J! ]! {! Z- ~9 y, f% V
Normal正常模式:当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次。- a$ c0 e: X' m( ~  s  F
Circle循环模式:传输完成后又重新开始继续传输,不断循环永不停止。
* r# c7 d1 K7 B9 `3 z0 Z
2 D# h$ @" t5 J) d+ k) v
Increment Address-DMA指针递增设置:( p1 C+ w0 \' o

/ G' b* U$ a& u* R" V
2b1a952d6514444e9dbb019a9ae88c42.png
$ m- ?$ n- X, y" S4 N
% D5 R% f' P* c; f, s# s' w

2 m. _  z( D8 ]+ M8 U9 F4、配置项目工程参数; ]" A# _$ v& S  Y% x2 E5 s
(1)配置时钟树,用于系统内部时钟,以及各个外设时钟等。此处选择外部8M晶振作为主时钟频率,内部最大倍频80MHz。0 x6 r5 ^; m& s; c: u  d
) ~% c) v! Z+ d6 D  q- l
f3ecedd9323f4463b69539906b3c1199.png 2 `; \/ e$ }' {2 F7 s- B

! g& q1 I2 F9 o# b(2)完成配置工程。
( Z: t. l4 ~& x: Y( O9 a备注:需要注意代码生成过程中的继承关系,如图所示:需要保留开发者自己编写的代码时,请根据配置设置,不然生成代码后会删除自己编写的代码(从这个方面也可以看出开发者备份自己的代码是多么的重要。)
9 Q$ k; @- ^. x; R- y! p" ^# \3 v
: F3 M! i" {8 ?' h
efdb616174f54925b6eac31109f227b5.png 2 b! J8 V& n0 o9 k7 |
​​
0 w) h  S# a& O9 v" _5 X 41c3f2716e4e4eda8f62fa3a1d871322.png + B% ?" ?& Q7 O5 K
( r* C) ~9 f4 `" J
(3)生成代码。
6 b9 R. u, r  D* b) i9 m" w8 g备注:使用Generate CODE生成工程代码前,请确保文件路径无中文,否则会生成项目失败。! U* s9 M+ F. }# v- F

9 p3 J" S: Q- l$ X: g& F9 U
8eaa7d0babea40ee93f158481a6ee471.png
, m' W7 G+ q) H* q# s. H  [​​- p+ o5 t$ A1 K) P  Q, n. O; n
(4)工程代码生成成功。
# p" A/ o: _& |, |1 P- E3 J1 G, P6 h& s/ U0 a! B
e8f46d59a1fb4af589feb613fdff17b4.png % s% n( L+ G! D

; e) ?5 L- w% j4 W+ w
. U  n, a/ I* P$ [ 三、在KEIL 5中编写代码/ g- W% w6 |5 y: Y; j% R
1、使用KEIL 5(MDK)打开项目工程文件

) o" t( _. ^6 A7 P8 h- Y# I源码使用说明:使用前必须把项目工程复制到无中文路径的文件夹下使用。
# C& A" q& e, F, \7 B/ c: X) n) h# w
(1)找到刚才新建工程的存储路径,安装项目名称,打开项目工程.uvprojx。8 k6 c# z% G- l; ]4 [0 l
/ a! u" y; ]' F8 l, p
ec2f10465e0a49e9845c70b067c393ff.png # A& _8 ^0 ^4 T% r. {  A7 ~1 b
0 N  N/ V$ F5 h- s5 i+ g
2、添加LED指示灯作为系统提示
. A( \" w  O2 A* n添加每隔100ms,LED1、LED2、LED3、LED4闪烁一次的系统提示,用于提示程序运行正常。
$ {5 I$ K4 X" B( N3 i* z; }5 P7 o3 g' m* j  z& i, Z. R9 u5 k9 A* U) g
2af9ef3cfaab45988c810d94d801fc34.png ; L/ O$ v) `; D! r
# f4 R/ ]; P+ y; j) V5 D7 L
3、添加HAL库UART  DMA 发送函数代码
6 e5 }& g" s# b+ g$ ]& _(1)STM32 HAL函数库的串口DMA相关函数如下:9 n) W; s& s: M% ^
  1. HAL_UART_Transmit();串口发送数据,使用超时管理机制
    ( o. N9 E# l6 P' k
  2. HAL_UART_Receive();串口接收数据,使用超时管理机制5 i# q9 N* B1 }2 |  C/ g  a
  3. HAL_UART_Transmit_IT();串口中断模式发送
    / R  o  v0 b' Z% M. |* j! n
  4. HAL_UART_Receive_IT();串口中断模式接收6 b* |) y8 A: Q
  5. HAL_UART_Transmit_DMA();串口DMA模式发送
    " x7 @0 b& h5 }6 X
  6. HAL_UART_Transmit_DMA();串口DMA模式接收
    1 \* x" J: H! h8 O% b9 \( q% h
  7. HAL_UART_DMAPause() 暂停串口DMA
    + v% _6 G/ v1 T/ A
  8. HAL_UART_DMAResume(); 恢复串口DMA
    : U6 L( X8 i2 C( \  ~9 r, T4 o
  9. HAL_UART_DMAStop(); 结束串口DMA
复制代码
; X5 }2 R# d9 U/ I
(2)main.c添加RS485发送函数相关代码:/ L$ Q/ A& t4 }

7 B# s0 i, |1 W% J+ }
33126cad704048e48421455e369f78bf.png
3 P- G) p) X# o+ u7 Y+ g. p9 q
  1. /* USER CODE BEGIN 0 */' D! M0 R0 v/ z* Q
  2. uart_rx_struct uart_rx_struct_t= {0};                               //串口接收数组
    2 Y! b, ^& O9 c, |
  3. uart_rx_struct uart2_rx_struct_t= {0};                              //RS485串口接收数组  ^. L4 e# g+ F
  4. /*******************************************
    ( Y2 S3 m8 z: u. B
  5. *函数名:DMA_Usart_Send: n+ S7 b9 ?3 X7 Z
  6. *功能说明: 串口发送功能函数
    $ i6 y. Q4 s; b' Q
  7. *形  参: buf,len& [- b# @% W4 Z! M5 {8 v7 A" A0 P
  8. *返 回 值: 无1 j$ k  |$ o: M' I$ _( @
  9. ********************************************/4 C+ O6 C/ _7 b# G: m3 Q! U$ a

  10. ! a) Z( t) g3 f
  11. void DMA_Usart2_Send(uint8_t *buf,uint8_t len)
    6 u5 ]$ S: W8 V! h* p' ]/ k2 X  W
  12. {- D! f) ~! B9 `/ {
  13.     HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);                 //设置485为发送状态
    1 E3 u5 L, W, K+ D
  14.     if(HAL_UART_Transmit_DMA(&huart2, buf,len)!= HAL_OK)     //判断是否发送正常,如果出现异常则进入异常中断函敿  }/ r. d  C6 j  W% E; i
  15.     {3 \. h* W; d" b7 j4 y9 x6 ~
  16.         Error_Handler();                                                                        //异常提醒
    4 c# _9 Y9 I0 T
  17.     }0 Q9 i" W& j. E
  18.     HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);    //设置485为接收状态
    . h- ]3 L: g2 f  {
  19. }4 ^4 e1 ]/ F2 i5 c

  20. ) n; r2 ^# @2 U7 s
  21. /* USER CODE END 0 */
复制代码

6 b8 v0 K6 \0 n% F; v1 K8 U1 C" A(3)main.c文件中添加main函数的处理,上电初始化打印一次log,然后等待接收,等串口收到数据后从原串口发出。( l% k! x- h' y
* c5 X- z' t" c' j+ O
cb23e78dcc0c4cedbdd965cd95a06c07.png
8 `# V# u3 D7 j0 \: w) u4 F2 f. S1 E  b% U) @% n
af25c79e68fd48b8b0fb1e456645ff74.png / Q$ H0 q2 p; a7 l. @

9 D- E& [+ ^" N7 G5 Y
0952de54d7b341ee97e81e22114d369e.png + v2 t% e& D0 [6 w& X1 Y
! W4 y6 J; r' O4 g) w+ w, x
: P" ^% a; x: {7 h  w
  1. int main(void)/ F0 C. P5 A8 ~0 t) d0 s/ I" f% e
  2. {
    ( j5 g. V5 O# F1 y- L" s' J$ U# m( a$ B
  3.     /* USER CODE BEGIN 1 */1 ~1 {. W* t6 a3 y/ D9 @" y
  4.     uint8_t transmit_str[50]= {"hello world,this is uart dma function!\r\n"};( g) T$ `1 ]6 O* M. R) [) F- J2 T
  5.     uint8_t rs485_str[50]= {"hello world,this is uart2 dma function!\r\n"};; @9 q9 t% g' h3 Z0 W! p
  6.     /* USER CODE END 1 */
    " a0 @2 f4 _$ ^1 o0 Y
  7. , X! i4 M) l1 I& E) Z' m% M
  8.     /* MCU Configuration--------------------------------------------------------*/  U9 L; Y* Q( f) P6 x# i
  9. ; ?( N: N8 P' J- F1 l* N
  10.     /* Reset of all peripherals, Initializes the Flash interface and the Systick. */, R5 @2 W) h4 d
  11.     HAL_Init();, Z! i5 U% C) g5 F3 K1 [9 v
  12. 2 Y% D4 G( D# T- T2 R( |4 a
  13.     /* USER CODE BEGIN Init */
    5 m. W3 }2 ^$ h) _
  14. 3 e8 \3 \/ d/ V
  15.     /* USER CODE END Init */
    2 q" W+ d5 M2 P! ?. p

  16. ( E# h) W  Z& W: x% M" Y
  17.     /* Configure the system clock */, d' d2 c5 j( l" _  E: Q2 {" Z5 T
  18.     SystemClock_Config();8 _: s% M5 P! m( N  H

  19. : _8 Z! Y- F0 S9 U( m! ]  m
  20.     /* USER CODE BEGIN SysInit */
    ; _. K& T( G( C% {+ x4 Z2 V
  21. & |- {  ~; E" r" K+ O. @+ y
  22.     /* USER CODE END SysInit */8 k. g  l. V+ ^  D4 o0 C

  23. - {* @& g' C" A, f+ u/ w% E
  24.     /* Initialize all configured peripherals */
    . P+ Q. C+ e7 I, ?! H* Q
  25.     MX_GPIO_Init();5 m2 I% N% n" T" V: c+ b
  26.     MX_DMA_Init();- @- q% e9 {- M9 N
  27.     MX_USART1_UART_Init();7 z9 I. V/ }0 J$ `; `0 A
  28.     MX_USART2_UART_Init();1 z2 M' p- o5 Y4 N$ H! @
  29.     /* USER CODE BEGIN 2 */0 u2 \$ Y6 ^  R. B# E1 D% _
  30.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮# S+ T2 a9 R% D( A# q5 A
  31.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮0 X3 H* w7 z; D- F- d* A
  32.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮
    1 a% C- S' W0 _/ C, h2 g$ L  Y
  33.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮
    - j' j1 e- ]5 W* w. r
  34.     HAL_UART_Transmit_DMA(&huart1, (uint8_t*)transmit_str, sizeof(transmit_str));
    . i- s2 R% @$ M* O7 l
  35.     DMA_Usart2_Send((uint8_t*)rs485_str, sizeof(rs485_str));                        //初始化log提示
    ( K: z" L; p! ~( d+ s8 @
  36.     HAL_Delay(5);
    9 F8 e6 t$ A0 J
  37.     HAL_UART_Receive_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, UART_RX_LEN);         // 启动DMA接收; x: Z9 b3 Z3 T4 @- ]
  38.     HAL_UART_Receive_DMA(&huart2, uart2_rx_struct_t.uart_rx_buf, UART_RX_LEN);        // 启动DMA接收
    & w7 `5 ~; [& o: f# X2 y

  39. 6 h: p( M6 b& f8 @0 y5 e5 R* |
  40.     __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);                                      // 使能空闲中断. V2 ?  z3 [! i# |- o( E# W
  41.     __HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);                                      // 使能空闲中断
    / F7 K7 n! V! ^# r
  42. , o' f: ]3 c/ P/ B' W' {5 h
  43.     /* USER CODE END 2 */" P1 I! Y  p3 W! Z

  44.   s$ H' [2 S, d0 D
  45.     /* Infinite loop */
    $ O8 n1 X5 Q- y! X( v: P7 O6 L* z
  46.     /* USER CODE BEGIN WHILE *// y; Y+ c, S' t- j3 s
  47.     while (1)2 _8 m2 \8 y0 t, A  _  z
  48.     {
    4 |" Z5 Y6 v( i0 }+ s9 s3 S
  49.         /* USER CODE END WHILE */
    ) C4 Y% M- {: I# R' Y$ A
  50. ! J0 F4 |+ K3 S( ]& h3 V7 G* F
  51.         /* USER CODE BEGIN 3 */: d4 h6 p( c4 N
  52.         HAL_Delay(100);
    ! h: j( l& W- S
  53.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);                                                                        //反转LED点亮熄灭切换
    : I6 f% D/ f" Q: j& F* z! X
  54.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_1);                                                                        //反转LED点亮熄灭切换
    6 U2 i7 Q2 v2 H* z) G
  55.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_2);                                                                        //反转LED点亮熄灭切换
    0 e1 K: Z5 e% v+ T* v0 n3 W/ ?
  56.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_3);                                                                        //反转LED点亮熄灭切换) m, K, z1 b0 U5 S4 T
  57.         if(uart_rx_struct_t.uart_rx_flag & 0X80)                                //DMA接收完成
    $ U! g0 ^* `( L9 V. d0 u5 u& y* \
  58.         {
    ' x$ n/ X, E0 y* p, W+ Y- F  e! I
  59.             HAL_UART_Transmit_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, uart_rx_struct_t.uart_len);    // 将接收到的数据发送回去( @6 M3 J1 _' |0 Z! {0 }
  60.             uart_rx_struct_t.uart_rx_flag = 0;
    3 c" ~  H/ d) m1 T1 a1 i
  61.         }
    ! D4 E/ d% s( a( ]6 o8 ?0 D9 R
  62.         if(uart2_rx_struct_t.uart_rx_flag & 0X80)                                //RS485 串口DMA接收完成8 \2 c5 l  N) O* b6 H
  63.         {$ Z% ?; X+ I" [& t
  64.             DMA_Usart2_Send((uint8_t*)uart2_rx_struct_t.uart_rx_buf, uart2_rx_struct_t.uart_len);                        //rs485发送
    : |0 [$ p$ u) _- q! J: Y" U( _
  65.             uart2_rx_struct_t.uart_rx_flag = 0;
    ) X$ i. C$ J+ U4 Y) t
  66.         }1 r( e( I2 ~6 C! z5 t9 s  e# B" a
  67. - F5 [+ o1 h8 }- F

  68. ' d" i2 c- m; ?( P4 ^" i2 M
  69.     }
    % h2 K$ M* M( _; m
  70.     /* USER CODE END 3 */
    % j% ]; F5 l# `0 q  T1 G( F* f6 I/ k  N
  71. }
复制代码

% Y+ L3 Q2 r; e$ h3 `$ M(3)main.h相关变量声明" L8 L8 E+ S3 t. k0 x
" Y1 d( a' }3 j( e$ B$ \2 Y
c30d0d2d5b464dfa93affa21394898a3.png
; p" B: y' E+ d$ M- u, @! J) H2 N! r( t+ h
  1. /* USER CODE BEGIN ET */
    ( i' j5 ]+ w* z4 @1 l
  2. #define UART_RX_LEN 1024                // 一次最大接收的数据量' j8 R& _( c0 i" F6 P
  3. typedef struct
    7 p: Q; v/ D/ k* I9 b
  4. {+ i! Q) T; n& a0 p& [. |4 G( j
  5.     uint8_t uart_rx_buf[UART_RX_LEN];  // DMA数据接收缓存数组  A- O- `2 |" b( M
  6.     uint16_t uart_len;                 //DMA数据接收长度- O& Z4 P! E- N# |* C% l) _
  7.     uint8_t uart_rx_flag;              //接收完成标志位& K( ?3 m  x+ i7 v$ w
  8. }uart_rx_struct;/ X# ?4 E" ?& T; }& r# t
  9. extern uart_rx_struct uart_rx_struct_t;  
    : C' m: n1 y! w2 a5 d" Q, i
  10. extern uart_rx_struct uart2_rx_struct_t;
    5 m" I" l) S! w
  11. /* USER CODE END ET */
复制代码
% J. f  a3 H( {, O
4、添加HAL库UART  DMA 接收函数代码& F& z( h+ g) J* Q1 c# i1 H5 k
(1)DMA接收设置前铺垫知识点:
7 h. g, J. y+ s3 c4 Y& C8 q; H* F" d
5 f" K6 F' l6 W        STM32的IDLE的中断产生条件:在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断停止。
. Z$ U( l/ C8 k& Q  P0 E2 T
! u) K* Q! W! I$ U(2)stm32f1xx_it.c中添加添加DMA接收处理代码:" L  i5 q! J0 f- t+ n3 E
  1. void USART2_IRQHandler(void)" m$ N! K- a9 V6 k3 |) {6 O
  2. {
    7 B8 Q# t) {* t6 H7 H" J+ Q
  3.     /* USER CODE BEGIN USART2_IRQn 0 */
    ! D# v$ b  n5 W
  4.     if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) != RESET)       // 空闲中断标记被置使" f0 z8 P1 B& Y7 n% b/ I
  5.     {
    0 p8 e- G! s% P6 q! K+ o1 K
  6.         __HAL_UART_CLEAR_IDLEFLAG(&huart2);                         // 清除中断标记
    ( s9 i& U/ r* [/ E; w
  7.         HAL_UART_DMAStop(&huart2);                                  // 停止DMA接收+ A* w9 C8 N! X
  8.         uart2_rx_struct_t.uart_len = UART_RX_LEN - __HAL_DMA_GET_COUNTER(huart2.hdmarx);  // 总数据量减去未接收到的数据量为已经接收到的数据量
    $ @& [! _; g0 Z- c2 N% K; T7 Z
  9.         uart2_rx_struct_t.uart_rx_buf[uart2_rx_struct_t.uart_len] = 0;                    // 添加结束笿, W/ w& [, _( g; l" h
  10.         uart2_rx_struct_t.uart_rx_flag |= 0x80;                                       // 标记接收结束: S7 x; U: h  x/ C- k
  11.         HAL_UART_Receive_DMA(&huart2, uart2_rx_struct_t.uart_rx_buf, UART_RX_LEN);        // 启动DMA接收
    ! ~+ D1 R& T  X% d5 G

  12. / g9 g  I, C/ [( F: n
  13.     }- S0 t: \2 I" U2 R& b. v7 Z
  14.     /* USER CODE END USART2_IRQn 0 */
    ) R( R/ M; |7 e1 @  {/ u/ F
  15.     HAL_UART_IRQHandler(&huart2);
    ) f3 q8 i$ Z( Z
  16.     /* USER CODE BEGIN USART2_IRQn 1 *// ~2 k& v' c7 b' D# A0 n) i

  17. % e, w" U3 ?; E6 L, V
  18.     /* USER CODE END USART2_IRQn 1 */4 N4 ?9 M9 K9 F2 g( G  ~
  19. }
复制代码

7 d& l' T5 g8 c4 i# _(3)至此,RS485串口DMA收发数据需要添加的代码已经完成。, t/ c+ `" J$ h0 z! O' M
2 b# {2 x9 h; ^0 E- u
; Q% W, V* n/ o& `& _
5、设置编程仿真下载模式5 A; q3 {0 A% B' |
(1)选择Options for target ...>>Debug>>J-Link/J-JTRACE Cortex,点击Settings>>选择Port(SW),可以看到搜索成功SW Device,表示芯片可用,可以下载。
& y2 {9 T0 ~. v) I
" P4 H3 }7 q5 H; V/ ?
edefb6b9a2a14be3b1221ad6d5c7a8a2.png 3 R2 i& h: t4 a( o6 X
​​
3 V5 w# S9 p0 X# g% _# i( o(2)点击编译,完成后提示“0 error(s),0 warning(s)”。8 U& [1 m" t" L8 h: r' n$ Q* j4 L
: ~# ~! z  ?' f: [
e0b7e3e353b345a7987fe5f821de2dda.png ( g( T1 l/ K' a4 h+ D3 m( G9 Z
​​, J0 N5 a" X& v1 i8 W
(3)点击Download(或者快捷键F8),即可下载程序。
- X- m0 z* |2 C% D9 _/ J, P4 t5 v' _( t7 i' Q
eb3f250f19e44862a7df80c2492fcd01.png 3 h4 N' C7 [) @/ \/ s
​
8 _/ g4 O: ?4 h( c2 D(4) 如果下载程序后,没有看到LED1、LED2、LED3、LED4闪烁,可以按下述方式设置一下(Reset and run表示下载后自动复位和重启运行)。或者重新彻底断电再次上电(或按开发板的Reset按键复位MCU即可)。
4 q' n4 K6 ]& ^' y4 l$ e+ W7 i/ P" M# w" w
9f8aa1a4e8f04041bcf5cb183facd100.png 8 P2 M0 M" T4 u# u8 n2 G( {
​4 s- ^7 O+ H% n, u
6、串口DMA收发实验效果展示

8 O9 {; B. L; Z* I0 G+ v  r        程序烧录到开发板后,即可看到LED1、LED2、LED3、LED4初始化后每隔100ms闪烁一次,并且打开串口助手后(串口参数:波特率115200、N、8、1),通过串口助手可以看到,开发板接收到发送的数据转发出来。) n: a+ u7 Y! j" r* |' r; B2 ]2 x
: ]& l# L" A& X+ A
f63ffa52c1ea43439547f62c39130706.png * H4 M2 P2 T  N) E6 K% i' Q& l

% P5 C, [8 w8 R% }6 d) w0 _————————————————2 H. E8 R7 D" v5 {0 Y- y$ X
版权声明:智能小屋ZYXC
  B. {/ H6 L* K4 |6 s2 H- D6 W7 x: o. e! B9 c: Y" H# R
4 p9 W8 j5 d3 H+ f; T- j; }1 b) n
赞 收藏 评论0 发布时间:2023-1-13 20:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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