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

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

[复制链接]
STMCU小助手 发布时间:2023-1-13 20:00
   一、开发板平台简介:
6 t2 i: L6 o* H3 U. u' k) ]' X. H1、开发板资源简介

( r1 |3 n1 `3 t9 k" P(1)开发板主芯片型号:STM32L431RCT6(2)开发板主芯片封装:LQFP-64_10x10x05P# }: v" {  r; W# {/ q' K! _; i# i0 b
(3)开发板主芯片内核:ARM® Cortex®-M4
5 r5 n4 f/ h( |# I$ W- L/ Y(4)开发板主芯片主频:80MHz
! k, b5 D( c7 X. e9 J/ ?(5)开发板主芯片Flash大小:256KB' L& e# h5 b0 [7 j
(6)开发板主芯片RAM大小:64KB
: Y$ Z: k3 R% b9 I: R
, ?7 @. q) Q2 a' N& H& X& \0 q: ~
bb91345227434ee7a43a34bf3fe366e6.png
7 @$ b/ p, ]: V* A2 P* r- y# s: _/ v, P1 d* [  k4 M( g7 ?
929c0cce04aa4115a8623703982bf3e1.png 1 V4 A" f( u  c3 z

0 z: V# L, @; X3 ^
2 {7 b' x. c, }# o5 e3 ~. R2、LED灯资源6 N( I4 Q+ C1 j0 @. p  H
(1) STM32L431RCT6开发板共5个LED灯资源,其中一个红色LED为系统指示灯,指示开发板供电系统是否正常,如供电系统正常,红色LED为上电常亮状态,硬件原理图如下图所示:
1 @! U7 N; \' Y. B, N+ j# Z2 C$ {% M2 A) d1 z. R0 ^
0f177691c5814f16a508bcfa747f87ac.png 8 _/ v# Q! h$ {: `

5 {% R4 T! e; c& B(2)其他四个LED灯为黄绿色可控LED,高电平点亮、低电平熄灭,计划用LED常亮验证看门狗的作用,硬件原理图如下图所示:9 E, D+ R" S  G% t9 |# P
. s4 K" g1 q" D4 H1 t" }+ U+ \
e923ad767b8448b7ac37c4ed693724bd.png
. L/ {! @5 T# l! D! _9 h
! ~5 c% O) Z  Q' l4 y+ }4 O# H1 D& R* m' n/ R3 X8 v; [4 Z6 R: Y$ W$ ]
​3、串口DMA收发工作原理* e7 Z& {5 j: M9 P
        串口全称为串行通讯接口,即数据在通信线上一次传输一位,按先后一定顺序传输。我们通常所说的单片机串口准确来说应该是串行异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART),使用TTL电平,串口需要RXD、TXD、GND三根线进行通信。
3 `0 x/ X) u3 |- f# D3 I% k
3 S: l7 g6 m; U# ^: b" b    (1)最常用的RS485收发换向方法是程序换向,即由MCU的一个I/O端口控制RS485收发器件的收发使能引脚,在平时使RS485收发器件处于接收状态
; U" i/ J! ?' I, e* u4 P
9 k! {. v9 l& p' X; F# V     (2)我们选用的STM32L431RCT6开发板串口2作为RS485通信的串口,PA1作为RS485串口收发的使能控制引脚。
7 H/ {: M0 \* ~& M  \" q4 q. |2 \: ^
     (3)RS485端口使用时,需要使用USB转485模块和开发板进行通信,使用方法为USB转485模块的A接开发板的A,USB转485模块的B接开发的B,GND可不接。( D3 v; Z% B; k

9 h- o# c/ {4 w& IRS485串口,硬件原理图如下所示:
' d  `$ D' h8 E* v% W* z2 W' {9 {3 x
1f72998fadef42548ee482c9fe064c08.png & j; U1 O+ K. S% k% i

6 |0 |) j0 L3 u) P4 h+ u, Y1 i* d
182841b93d1e40b0913e3a54b22d0704.png ) b, c$ [+ c# A6 i7 g# U

0 M) ~# S4 u8 f# U+ N# SDMA(Direct Memory Access) :直接存储器存取,是单片机的一个外设,它的主要功能是用来搬数据,但是不需要占用 CPU,即在传输数据的时候, CPU 可以干其他的事情,好像是多线程一样。数据传输支持从外设到存储器或者存储器到存储器,这里的存储器可以是 SRAM 或者是 FLASH。( B8 ]. i$ l6 I  b9 B

  p5 k( U2 q, I; z4 FDMA 控制器包含了 DMA1 和 DMA2,其中 DMA1 有 7 个通道, DMA2 有 5 个通道,这里的通道可以理解为传输数据的一种管道。要注意的是 DMA2 只存在于大容量的单片机中。0 r( r+ v+ m9 v3 q8 L) P7 u
3 H1 `  n. B$ W
354955ecc6b140049ec57af71fe199f1.png
4 P% L/ S* r; A9 D: U6 I6 h% f7 x
+ _3 s1 Y9 ?/ ?- p, Q; M  二、串口DMA收发实验过程/ ~" ^& T+ r( X! v5 V% Y
1、新建STM32CubeMX基础工程

% Z- e% O1 P+ `# J! y( L(1)打开STM32CubeMX,点击“File”-->"New Project"
. g, H) f1 {/ n( z  J
' g& w- p9 P$ k  e) B( ?$ |/ o
2399170347904e959c855fefd5877f84.png ! w  Q6 d+ l0 g- s
/ ^1 d5 j; i3 ^
(2)等待打开主芯片选项界面(大约1分钟时间)。
3 @; u2 Z- S$ M" k# Y! ~  ?& R5 z4 a& ?% y
d74d2fdc60c9440483e2b7cf8d928e7f.png 9 J& o$ j* e1 Q  Z

* Q" @0 b5 L$ d" s(3)昨天搜索框中输入(或选择)所需的主芯片型号(因为我们用的是STM32L431RCT6开发板,所以此处选择STM32L431RC),然后在右下角选择STM32L431RCTx(因为开发板主芯片是STM32L431RCT6),左键双击即可打开新建的项目。
- X( S& \" q( b$ S; j' \6 i: C2 P7 y2 l: [7 w1 F

. S3 Y6 O, Y- g/ Z) S5 n 7b80345238d74bea82ce70e1a348f7b4.png
8 t3 m2 B; q; D3 U' s) Q! v8 S

( s" d( y) F1 B0 F! p(4)选择时钟源。1 K) B$ a# r4 S- R- ?: e/ F
        因为开发板上有8M外部时钟,硬件原理图如下所示,所以此处选择使用外部高速时钟(HSE)。6 w8 ^, w# U6 u3 P
- m. Z& L  U9 L
3f65707eca104663a3dede6d25dfa961.png 2 a, ^' g, K( u  @9 b7 C( R# m
! L4 ^- C$ Q8 J0 a, Q# E, K
        因为我们没有用到外部低速时钟(LSE),此处不做处理,如下图所示。
0 f( b% x; o. E7 `, {/ t
. z& c6 K  K  M
72119b971f62410fa8344f7f9fb9f389.png
3 ?/ M# `$ V+ {5 y5 ?
! O$ r7 h- z& Q: ^: i+ t
2、配置GPIO控制LED, D5 Z$ U# Z/ z7 q
(1)查开发板原理图得,LED1、LED2、LED3、LED4的控制引脚分别为:
7 s) a; m. y! D5 TLED1——PC0
" O2 c7 s( m) x$ t) i/ NLED2——PC1
# [8 H5 ]/ v( T; jLED3——PC2- n! z: R2 F3 S8 o
LED4——PC3" G  i  s2 M* I. V9 m. j5 s
; p; i8 E2 Q1 \
(2)配置LED的控制引脚为输出,输出频率、输出方式默认即可。% i% Z! ^  p) O' b/ Y* E
鼠标左键点击PC0,选择“GPIO_Output”,表示设置该引脚为输出模式。2 ]( d" l) y6 \" p- \/ Q
鼠标左键点击PC1,选择“GPIO_Output”,表示设置该引脚为输出模式。
: B* n* F# Q- _3 u6 |6 Z鼠标左键点击PC2,选择“GPIO_Output”,表示设置该引脚为输出模式。/ a# Y( d  A8 f8 H3 _" p+ C
鼠标左键点击PC3,选择“GPIO_Output”,表示设置该引脚为输出模式。
, A2 K* j2 d. L7 D+ f  i* B" J) X) ~5 q! Y; s' Q* H
492907c1e71149819adbaee4516a2af4.png 6 z/ ~% x: x- `2 k2 n& U* l5 I
9 m1 X1 `: [) u0 f- y
c75d3f10ba2e427d9c1a10fad9bf5471.png
+ _! U5 L+ X+ J

. T* t8 o( a# R- J(3)也根据自己的需求配置GPIO的参数,如输出方式、输出频率、上拉下拉等。因为GPIO控制LED的要求比较低,此处采用默认参数即可,不用修改。
5 e& w5 T. ?4 f+ ~3 p9 E8 J+ [2 {( a& a0 W$ D' X+ L
38ff4b80e1c5495ba3076a5158fd91fa.png
8 [3 T, j/ Z0 Q' }
; J/ K$ p( K+ Z1 }. O​​3、配置PA2、PA3为串口
; x* E! D6 T8 b* Z5 n4 p  x(1)查原理图得知,串口2使用STM32L431RCT6引脚为PA2-USART2_TX,PA3-USART2_RX,引脚设置如下:
4 x% ~/ _7 v9 E: Z$ L& Q
9 v! h8 Q0 W5 F  a: h8 Y
9bd645a9032647d280107cc82b5a0f67.png 8 z1 j. F$ A6 ~
( O+ i3 }! ?: M! n5 l- ^% `
串口参数默认即可:波特率115200-N-8-1,并使能收发控制引脚。, x; x8 N" E6 p$ j

0 }$ y7 g( X7 C$ S  R
74f5d7878df343ae83c9af5ed79c6a7c.png
6 n: Y; \' A; {! g5 `

1 {. _9 t% b0 O% g: ]; U1 ?: K(2)设置NVIC settings 使能接收中断。- |: j) N/ w' s. U* o, ]2 c0 |

$ `! u2 O. ^/ e! q8 i! d
fde3c5c1ac9d4896b40dc5f5e15c3e61.png ( m* G6 G% j8 O# s

) t0 x2 N7 B: y  r; F' p3、串口DMA设置
2 p6 l5 r" R3 o* g! t, V4 f( p$ T
! |; ^$ P( C5 n! @" m
6d26b13dd9d34039a2b426ca47680f8c.png % I4 u: D/ _3 d# l' \3 x

* w4 T7 P% r' V1 ^! L7 z(1)根据DMA1通道预览可以得出,我们用的串口2的TX、RX分别为通道6、通道7:! B5 D2 ?; y( S# D* z; _' `
点击DMASettings 点击 Add 添加通道/ m% P5 v4 ?; o. [, Z; S9 O
选择USART_RX USART_TX 传输速率设置为中速  Z5 H' Q  ~+ G. G; j6 x) p
DMA传输模式为正常模式,即发送一次就结束。
/ K$ D7 o; e# A: y7 QDMA内存地址自增,每次增加一个Byte(字节)  L6 Z) J  D' S: J9 u0 b. e- v
5 d) g/ ]3 s* V4 B$ z
55bd687bfb1c4640847f6cba6ea373b9.png
4 g4 @; ?4 a3 M/ N# Y4 c0 V' _- J. n( g1 J0 T8 W
(2)DMA相关参数解析7 S" V! s' @. h4 {( [: u
Dirction : DMA传输方向有四类/ p' V, ?" ?3 g) R& B. w/ j
外设到内存 Peripheral To Memory! O# i, A* w! M7 }3 _8 |1 G
内存到外设 Memory To Peripheral
/ g1 Y1 B3 q# U3 e内存到内存 Memory To Memory
9 \9 l* l" O$ |; y外设到外设 Peripheral To Peripheral! L4 ^6 w1 y" K% A
- n% a7 U+ Z( Y) R; w* j6 W% p. M  L
Priority: DMA通信传输速度有四类- ]4 T* j0 d( j! h8 G
最高优先级 Very Hight
% \* E4 `! D3 ]# K! p+ l1 m: `高优先级 Hight
% ~6 Y# y% f0 S0 v8 ]6 W6 D# Y中等优先级 Medium! e/ Q+ x+ u1 ~7 R- z
低优先级;Low: i% w( @1 a: Y7 Q  e( w- _% ~
! W+ t/ u5 W& F9 ^) g: v
Mode:DMA传输模式有两类$ m, i' J3 ~; `" `6 n

4 H- l. w% y$ _0 N
9021c11fed3e4c1885477e062b846258.png 8 g  m# c  E( J( U) @0 O
2 H: L9 s5 O! g2 t# C: B. }, Q
Normal正常模式:当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次。
( T5 z* [* U" z8 H+ R6 ECircle循环模式:传输完成后又重新开始继续传输,不断循环永不停止。* c" J9 @# L- u4 P! V
8 m1 I0 v' K- n; p2 t8 \
Increment Address-DMA指针递增设置:
" O) I7 u% i0 a# [6 ]2 |# |6 M  m$ N6 H. q8 W0 \
2b1a952d6514444e9dbb019a9ae88c42.png
8 Y; w( N& Y3 w8 n1 e  |7 Y
& \- Z* j# r: S, Z# _/ V2 a
2 e% d+ V# I9 M* v9 k
4、配置项目工程参数
: X# g  \2 s/ G/ ]3 E6 a(1)配置时钟树,用于系统内部时钟,以及各个外设时钟等。此处选择外部8M晶振作为主时钟频率,内部最大倍频80MHz。
8 @0 |4 U/ K1 _! S+ A) x$ v0 L$ w* B( c
f3ecedd9323f4463b69539906b3c1199.png
. U: y+ Q6 x6 w7 B; P5 H) x/ u' a! G; b! \, |
(2)完成配置工程。2 U) a1 W9 j' w% u2 W5 K( O
备注:需要注意代码生成过程中的继承关系,如图所示:需要保留开发者自己编写的代码时,请根据配置设置,不然生成代码后会删除自己编写的代码(从这个方面也可以看出开发者备份自己的代码是多么的重要。)$ q  U* b, m3 M5 i% Y/ _, Q- W9 u

0 G  O4 [2 w$ N; }2 m
efdb616174f54925b6eac31109f227b5.png
: a. {3 a( I$ M8 p# F4 d& ~​​
7 R0 g, _0 L# M' P& c5 h 41c3f2716e4e4eda8f62fa3a1d871322.png / w  L4 l8 N1 M
: M3 {# G" B! @- e+ k
(3)生成代码。
+ r9 r: _+ b$ s6 n$ {, U: U备注:使用Generate CODE生成工程代码前,请确保文件路径无中文,否则会生成项目失败。  O4 ]$ |5 v$ L$ y7 E

3 J8 M7 }9 ?! }; s# j
8eaa7d0babea40ee93f158481a6ee471.png 4 \$ B' q- l6 `1 @
​​: g! A  ?6 O4 }9 n9 Z8 n5 S
(4)工程代码生成成功。- c% \: s; O  R. \; @1 f

- X7 ^' i3 t7 e6 Q8 D+ l' `
e8f46d59a1fb4af589feb613fdff17b4.png ; E8 Y8 S( L7 x* @3 Y9 a

9 Y  `3 p- A  J) w/ M" d1 o2 }% p1 U  Z# a
三、在KEIL 5中编写代码
. c% _- o4 A9 l: m3 ~, w1、使用KEIL 5(MDK)打开项目工程文件

. b* k5 `: T3 e' B( h9 E+ O源码使用说明:使用前必须把项目工程复制到无中文路径的文件夹下使用。
* h4 Z6 G3 J6 |1 R" m5 T2 L' F0 L% q0 ^/ P% G& E% u5 \% n& ]
(1)找到刚才新建工程的存储路径,安装项目名称,打开项目工程.uvprojx。
, g& o& l9 b( H* B; |5 O) ^2 @2 X3 X. q- f
ec2f10465e0a49e9845c70b067c393ff.png , ]0 e( g& p! F
% w, s  w8 I6 T
2、添加LED指示灯作为系统提示
$ L- y2 N' J! {1 N* u添加每隔100ms,LED1、LED2、LED3、LED4闪烁一次的系统提示,用于提示程序运行正常。
) Q3 q( V7 E8 I4 \8 C& R( y3 Q  c9 B7 J: s
2af9ef3cfaab45988c810d94d801fc34.png
. H9 q* ^/ Y" t8 b5 B3 ]& k! j8 S4 Q. t$ a" ]' N
3、添加HAL库UART  DMA 发送函数代码
, |$ k; e: ?1 I$ M(1)STM32 HAL函数库的串口DMA相关函数如下:
" |! s7 G% D* I% Z
  1. HAL_UART_Transmit();串口发送数据,使用超时管理机制% C  G$ ^! P" a8 `) ]7 G
  2. HAL_UART_Receive();串口接收数据,使用超时管理机制
    0 j1 B6 w+ z. k: @4 ?; C. l. i! Y
  3. HAL_UART_Transmit_IT();串口中断模式发送3 A5 D! m6 s! _* J
  4. HAL_UART_Receive_IT();串口中断模式接收
    ; B* `2 f: N! a0 e& U1 H4 Q; T2 K8 x
  5. HAL_UART_Transmit_DMA();串口DMA模式发送
    2 i2 Y% I! H' l$ X& L! [
  6. HAL_UART_Transmit_DMA();串口DMA模式接收# D$ H( y5 h, u+ q! p
  7. HAL_UART_DMAPause() 暂停串口DMA
    6 X7 T7 V3 Z& q" B! \8 l7 I$ i0 }
  8. HAL_UART_DMAResume(); 恢复串口DMA! p% {2 b8 n- i' q0 X; Q# M
  9. HAL_UART_DMAStop(); 结束串口DMA
复制代码
; q& R- o7 D2 q, A4 Y4 c0 l
(2)main.c添加RS485发送函数相关代码:
2 n4 [% E" J& @. ^0 {" D- p3 b$ q7 }! e; z; ^2 S) m; z- b% K1 C
33126cad704048e48421455e369f78bf.png
" d) [& ]/ `) _! q1 \$ R: w1 ]5 Y2 ~/ |6 p7 s/ m4 C9 O% ^# Q  ]  {
  1. /* USER CODE BEGIN 0 */
    0 Y# \  w. J, N
  2. uart_rx_struct uart_rx_struct_t= {0};                               //串口接收数组
    4 @& \4 N* M  c9 v9 D
  3. uart_rx_struct uart2_rx_struct_t= {0};                              //RS485串口接收数组" s  B9 [% B/ D3 w0 E; @
  4. /*******************************************
    / Z- J( f& C; `6 U
  5. *函数名:DMA_Usart_Send
    $ V% E# V! C& V, g* j, h) t
  6. *功能说明: 串口发送功能函数
    ' y) e3 y& u5 k( _0 r' O# `0 P
  7. *形  参: buf,len
      ]- b7 c- _0 B6 b; P% b3 c; L
  8. *返 回 值: 无
    1 Q. P, L2 j: d0 u0 Y
  9. ********************************************/" q6 b4 U0 X" `% u
  10. : q' E2 Z$ N  O# y' _6 v. @
  11. void DMA_Usart2_Send(uint8_t *buf,uint8_t len)
    2 v  p# l: n( e) C& C
  12. {
    ) z9 e8 u1 g& W# K0 o' |3 o: m
  13.     HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);                 //设置485为发送状态
    ; K6 E/ ~4 ~# |7 g
  14.     if(HAL_UART_Transmit_DMA(&huart2, buf,len)!= HAL_OK)     //判断是否发送正常,如果出现异常则进入异常中断函敿, x  @8 n4 f$ d) _/ I
  15.     {; I9 _. l1 J: B
  16.         Error_Handler();                                                                        //异常提醒
    ) |# j! F. P5 @7 ~" {( \& b
  17.     }/ O$ S, g# K4 Q$ T2 g$ _7 L2 j1 r
  18.     HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);    //设置485为接收状态. C$ Y) {! ?, c# W
  19. }
    * I5 ?& M! \8 W! [9 E7 K# J4 T
  20. 2 c& R$ W/ ?" H! P6 v7 _
  21. /* USER CODE END 0 */
复制代码

' n+ i* w9 N% M: X0 {+ J. g(3)main.c文件中添加main函数的处理,上电初始化打印一次log,然后等待接收,等串口收到数据后从原串口发出。
4 p, o( n& d" G
, M$ C8 F; C9 n
cb23e78dcc0c4cedbdd965cd95a06c07.png - K# t) e# p6 U8 [

4 s7 D$ E: ~* O: ?
af25c79e68fd48b8b0fb1e456645ff74.png
7 |+ W- g& p9 l& q8 m, w
5 u4 i; W/ G$ ^; ^1 U  R% o+ s
0952de54d7b341ee97e81e22114d369e.png , c# A/ x6 K/ a; j! e
% s# [/ u& T6 m: E5 c3 v  l( j) b3 f+ H
4 Z; m; N$ o. T' {4 z$ a3 U
  1. int main(void)# X3 C$ q6 Z5 q9 g: L
  2. {* j: K- M  Q" s2 s# Y* y
  3.     /* USER CODE BEGIN 1 */
    % L/ [2 r, x, F+ `0 L
  4.     uint8_t transmit_str[50]= {"hello world,this is uart dma function!\r\n"};
    : N0 w% P9 i/ r! N$ |8 {
  5.     uint8_t rs485_str[50]= {"hello world,this is uart2 dma function!\r\n"};
    $ @5 _% Z+ r5 c  W* {4 f
  6.     /* USER CODE END 1 */. D) e4 Q  F; o9 ~& Z' H+ s# P9 J2 t
  7. ) b: G9 o5 K1 ~, I1 E
  8.     /* MCU Configuration--------------------------------------------------------*/" t( Z( ?, Q; z
  9. & d6 w+ M2 w/ o9 L; K2 e
  10.     /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    3 Z& W9 w: u6 s! B- ~2 r
  11.     HAL_Init();
    9 ~& {4 h: v' F; L. p7 c1 i& E/ Z- _
  12. 7 I) ]) |" E; D& R" ]! V
  13.     /* USER CODE BEGIN Init */
    9 ^; X) t. O1 M! \8 ~, K5 c9 P

  14. " x( G0 Q/ Z1 S' E9 @& P7 a5 Q
  15.     /* USER CODE END Init */
    * p" F" s5 U1 Z

  16. + x4 ~. Q0 C* |8 a5 A1 w* ~0 W7 R2 X
  17.     /* Configure the system clock */2 D2 V& V* G5 X% F" t
  18.     SystemClock_Config();, K6 }& J9 j3 U" D$ Y

  19. ) @, }5 \6 f/ z; G* E. f
  20.     /* USER CODE BEGIN SysInit */+ x! \4 W% P2 a! z3 M

  21. ! h$ g2 x# p6 h/ u8 F( \2 a6 E
  22.     /* USER CODE END SysInit */, {$ R$ R2 s5 O

  23. $ M6 u0 ^$ Q" G4 y8 {# R( C
  24.     /* Initialize all configured peripherals */7 F7 @+ `. q; I/ X3 r) ~7 A
  25.     MX_GPIO_Init();( t) h9 U& \2 D+ ?/ E3 }
  26.     MX_DMA_Init();
    , O+ [6 P& D$ {/ _# Q. a1 a/ Z" b0 t
  27.     MX_USART1_UART_Init();& K  w) `4 B) `' A. Y, }
  28.     MX_USART2_UART_Init();- S& `7 l! `+ a: G  V9 C% C
  29.     /* USER CODE BEGIN 2 */! [) w- e& P5 d5 e/ y
  30.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮; C3 n( v7 |9 ?9 N0 u4 S; a
  31.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮( l4 H# S' N/ I- ^3 x6 S2 G$ P% T
  32.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮  H+ _$ M& `' F: }
  33.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮
    6 W( X; A5 s; n- o( z6 O4 U8 x) }
  34.     HAL_UART_Transmit_DMA(&huart1, (uint8_t*)transmit_str, sizeof(transmit_str));
    * Y1 X/ J+ A, [# _6 ^6 p5 U
  35.     DMA_Usart2_Send((uint8_t*)rs485_str, sizeof(rs485_str));                        //初始化log提示
    # G) ^9 }" E# c' {6 W* S4 o  R. m+ v( I
  36.     HAL_Delay(5);
    ) R9 l3 b* w! Q; e, z. {! [! ?2 a/ h
  37.     HAL_UART_Receive_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, UART_RX_LEN);         // 启动DMA接收
    & k% F- _5 h% o1 c
  38.     HAL_UART_Receive_DMA(&huart2, uart2_rx_struct_t.uart_rx_buf, UART_RX_LEN);        // 启动DMA接收/ w$ m+ x. M# V9 U  K
  39. . ?* L* I- j3 g0 _6 f0 p5 M3 e
  40.     __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);                                      // 使能空闲中断/ X" c( d1 Z- Y
  41.     __HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);                                      // 使能空闲中断  I$ r4 K0 V# U! z. T( b! w

  42. ( Q( i% q7 c9 C2 Y5 g# V
  43.     /* USER CODE END 2 */# ^+ W" T' K( V6 w1 l2 R: E
  44. : o( A/ M' i( U) v3 R. Z
  45.     /* Infinite loop */5 m! k( L) p$ K; e3 t% r3 j
  46.     /* USER CODE BEGIN WHILE */9 e* @& M1 S9 s
  47.     while (1)
    5 F+ b9 ~+ j7 v( m
  48.     {; |* n) O# S; r1 {
  49.         /* USER CODE END WHILE */. Q0 X# S# }6 D& l5 A
  50. - F" c: O6 j- T& l5 Y* A- c1 X+ \
  51.         /* USER CODE BEGIN 3 */7 |) V3 K9 G4 ~: ^/ g. Y; o# ?
  52.         HAL_Delay(100);9 `& M+ L1 n& Q
  53.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);                                                                        //反转LED点亮熄灭切换' ~9 B/ z% K" n) d- _
  54.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_1);                                                                        //反转LED点亮熄灭切换! g* {: u% [; R9 E5 _5 ^
  55.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_2);                                                                        //反转LED点亮熄灭切换
    : x  a- a+ S" j
  56.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_3);                                                                        //反转LED点亮熄灭切换
    ) Q  W' G; V' k2 ]' J. U
  57.         if(uart_rx_struct_t.uart_rx_flag & 0X80)                                //DMA接收完成9 V" u% a8 O& k& Z5 A
  58.         {
    + f2 e) ?" G# a* H+ y' |
  59.             HAL_UART_Transmit_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, uart_rx_struct_t.uart_len);    // 将接收到的数据发送回去8 a" M! d5 S- [. _
  60.             uart_rx_struct_t.uart_rx_flag = 0;
    3 h% }- [$ \6 J5 a! }6 C" S& k
  61.         }
    $ Y# u% P! Q' t2 g( S; G; \; L- M. C
  62.         if(uart2_rx_struct_t.uart_rx_flag & 0X80)                                //RS485 串口DMA接收完成+ z3 Y6 w0 S3 w9 o
  63.         {
    0 }8 y0 |0 V% c) a6 P3 _4 i
  64.             DMA_Usart2_Send((uint8_t*)uart2_rx_struct_t.uart_rx_buf, uart2_rx_struct_t.uart_len);                        //rs485发送
      w1 G( t% r+ t! b$ {, i" P% T
  65.             uart2_rx_struct_t.uart_rx_flag = 0;7 N5 `4 p( p  D& U8 r6 q+ N( U7 _
  66.         }) j# Z4 Y: R& V" M: v
  67. 5 q3 X: G/ {) S* Z- V; V
  68. ! _* Y% L% t; T# U$ Z# P
  69.     }
    $ R$ b, A/ V+ s; p7 G1 v
  70.     /* USER CODE END 3 */
    ; y. t5 H4 R- a3 A6 W( B
  71. }
复制代码
  _2 k$ ?! d2 _0 D- O: \
(3)main.h相关变量声明8 a9 s* e7 g( x1 _
; o' j$ j. S, ?% o
c30d0d2d5b464dfa93affa21394898a3.png
7 W5 {0 U7 m' s, Z1 y
; T' Y2 p( `0 k* k& I1 w5 S* v
  1. /* USER CODE BEGIN ET */  v, [% f" J+ r( n3 w0 {
  2. #define UART_RX_LEN 1024                // 一次最大接收的数据量8 W: _2 [5 B- K& t( j6 p
  3. typedef struct
    ( w8 L' c3 Y3 B) Q0 W  D2 [& K0 J
  4. {% x( s# R2 E) n/ o% R; I& s5 i
  5.     uint8_t uart_rx_buf[UART_RX_LEN];  // DMA数据接收缓存数组9 S, d2 d# U6 q4 e8 ~% M
  6.     uint16_t uart_len;                 //DMA数据接收长度/ m1 Z9 {/ M, T+ H
  7.     uint8_t uart_rx_flag;              //接收完成标志位+ I: G& C( w! O7 i/ Y3 f
  8. }uart_rx_struct;
    8 D2 F1 H3 c; o' g2 l' P. s
  9. extern uart_rx_struct uart_rx_struct_t;  
    4 Z# s7 k* S* v( W. J& a' x
  10. extern uart_rx_struct uart2_rx_struct_t;, {; j$ I* n' S" y
  11. /* USER CODE END ET */
复制代码
; V6 c' F* N6 I& p
4、添加HAL库UART  DMA 接收函数代码1 \3 ?) m, g  J+ q4 x3 Z& Q  e
(1)DMA接收设置前铺垫知识点:
4 W% F$ X; R8 m. q" S& M5 B; }- V- X# f7 U
        STM32的IDLE的中断产生条件:在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断停止。
9 A1 s1 U0 T9 U- Y# ^- W0 G6 f7 ~1 K: M
(2)stm32f1xx_it.c中添加添加DMA接收处理代码:
' e1 a; A2 |9 U& B: K+ P; I0 ?
  1. void USART2_IRQHandler(void)
    0 G8 e5 \. |7 q) d* M) F
  2. {
    , \$ K. }* g% A2 E2 P1 S+ X
  3.     /* USER CODE BEGIN USART2_IRQn 0 */
    / f3 e& i3 z( L1 t: t
  4.     if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) != RESET)       // 空闲中断标记被置使8 m$ @4 }7 I; E
  5.     {
    $ y- z1 ^7 S8 X1 G
  6.         __HAL_UART_CLEAR_IDLEFLAG(&huart2);                         // 清除中断标记
    % r, w" r# w6 d+ m0 l! j7 A
  7.         HAL_UART_DMAStop(&huart2);                                  // 停止DMA接收6 e+ m( ]9 N  c2 }$ F+ B2 o& v4 R
  8.         uart2_rx_struct_t.uart_len = UART_RX_LEN - __HAL_DMA_GET_COUNTER(huart2.hdmarx);  // 总数据量减去未接收到的数据量为已经接收到的数据量
    2 \9 C; P8 J4 ?' o$ K
  9.         uart2_rx_struct_t.uart_rx_buf[uart2_rx_struct_t.uart_len] = 0;                    // 添加结束笿8 g) H( n. i, q7 z2 f! v/ ^. r
  10.         uart2_rx_struct_t.uart_rx_flag |= 0x80;                                       // 标记接收结束4 P; d6 T  x* E) n" S
  11.         HAL_UART_Receive_DMA(&huart2, uart2_rx_struct_t.uart_rx_buf, UART_RX_LEN);        // 启动DMA接收3 |) ^6 t, p# \. X6 e, H) M

  12. & r. t- x; Q( L+ S+ F' m% _1 o
  13.     }
    9 `1 d) b- q; m; V* u4 ]/ Q" R
  14.     /* USER CODE END USART2_IRQn 0 */9 g9 D* T5 ]/ w6 M
  15.     HAL_UART_IRQHandler(&huart2);
    . J- l  ^. s0 A/ g5 L, K# ^
  16.     /* USER CODE BEGIN USART2_IRQn 1 */0 v' U8 R- o8 K7 t
  17. ( {$ W$ G( |' F; o
  18.     /* USER CODE END USART2_IRQn 1 */, _, A3 Q' y4 S5 }0 E, w0 b6 k
  19. }
复制代码
7 b& P! v/ E; ?$ Y( J( H
(3)至此,RS485串口DMA收发数据需要添加的代码已经完成。# b" o, K+ J0 x1 t! h/ I% P6 f8 r

, }! @) H7 v6 j/ {  q

' h; J! i3 F! C8 H% R5、设置编程仿真下载模式
- B* v; Y3 N7 M, Q4 V2 `(1)选择Options for target ...>>Debug>>J-Link/J-JTRACE Cortex,点击Settings>>选择Port(SW),可以看到搜索成功SW Device,表示芯片可用,可以下载。
8 f8 ]6 d( o3 R* |6 O1 o
2 }* C! X2 U6 I- [5 Y: D" O4 w. l2 m
edefb6b9a2a14be3b1221ad6d5c7a8a2.png ' V3 E1 J- f  B4 q( R$ G- c' u6 w
​​0 ^+ m5 h$ L+ O# C6 L
(2)点击编译,完成后提示“0 error(s),0 warning(s)”。
) b# U  ]7 a9 I$ |6 p7 S" Q% P8 ]( @, p3 h3 @3 M
e0b7e3e353b345a7987fe5f821de2dda.png
! W: N0 {) q9 t: v# b​​5 u& v( d' y" c  f# d; B" g* O
(3)点击Download(或者快捷键F8),即可下载程序。. S9 w, F, S2 }' b5 F" g
( u) a3 w" B  H: R4 M
eb3f250f19e44862a7df80c2492fcd01.png
  T5 o0 M' `6 |6 I! g& G5 z" T" S7 i2 p
(4) 如果下载程序后,没有看到LED1、LED2、LED3、LED4闪烁,可以按下述方式设置一下(Reset and run表示下载后自动复位和重启运行)。或者重新彻底断电再次上电(或按开发板的Reset按键复位MCU即可)。/ Q- y) x0 l) |. ^! P* Z! u

# y5 d( P7 p# `/ Y
9f8aa1a4e8f04041bcf5cb183facd100.png
. M# `* d, T7 L$ H/ G# m9 V1 F  V
/ r* i$ F8 {( j# l$ e  A/ p6、串口DMA收发实验效果展示
+ q, R: ]) ~8 x, K! ^4 D8 y
        程序烧录到开发板后,即可看到LED1、LED2、LED3、LED4初始化后每隔100ms闪烁一次,并且打开串口助手后(串口参数:波特率115200、N、8、1),通过串口助手可以看到,开发板接收到发送的数据转发出来。
) i/ p1 _6 i( d( j' E1 Z/ X- D, r/ P: e8 E: P' R. E% D
f63ffa52c1ea43439547f62c39130706.png   \9 n& C5 }7 L( \) }6 s2 P
7 r- b- j- C. y" l' P
————————————————4 F6 g! `  B- J: o. D9 W- A
版权声明:智能小屋ZYXC8 a) Q/ T. z4 [, ^% |

6 u$ @8 r; K, [+ J- |* z2 c4 z- M  L" x7 j+ M4 W# y) l
收藏 评论0 发布时间:2023-1-13 20:00

举报

0个回答

所属标签

相似分享

官网相关资源

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