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

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

[复制链接]
STMCU小助手 发布时间:2023-1-13 20:00
   一、开发板平台简介:
5 M$ {& O5 n7 R/ D6 t1、开发板资源简介
; g) D2 M6 R3 {* W! z; o1 O9 l
(1)开发板主芯片型号:STM32L431RCT6(2)开发板主芯片封装:LQFP-64_10x10x05P
, s5 @, J0 k+ i% u(3)开发板主芯片内核:ARM® Cortex®-M43 w# q' W7 a5 R
(4)开发板主芯片主频:80MHz
( D9 p1 @7 N- h' [(5)开发板主芯片Flash大小:256KB
( B# W: j0 n# {9 s" ~$ E6 L(6)开发板主芯片RAM大小:64KB
  h3 ]) R; f% g" i/ z) d1 x1 g$ `* {; T2 A
bb91345227434ee7a43a34bf3fe366e6.png 5 G, S2 i4 H% d, j+ \2 e
# W$ c5 ?! m0 ?9 Z# K( H
929c0cce04aa4115a8623703982bf3e1.png
8 b5 z7 F+ o7 c) A) l* J! C3 T6 u( ~0 w! q; T

5 g) I0 w) @: J! M2、LED灯资源
' _) A# t+ k' i5 {& @(1) STM32L431RCT6开发板共5个LED灯资源,其中一个红色LED为系统指示灯,指示开发板供电系统是否正常,如供电系统正常,红色LED为上电常亮状态,硬件原理图如下图所示:% ?8 A. |0 K( [! I7 Q
7 }1 B6 a$ Q, S& ^( \4 x$ x4 C
0f177691c5814f16a508bcfa747f87ac.png
% C  }6 m* }( n
5 K+ {% o! S4 ?" f' e$ u: V+ ](2)其他四个LED灯为黄绿色可控LED,高电平点亮、低电平熄灭,计划用LED常亮验证看门狗的作用,硬件原理图如下图所示:
6 Z5 b6 b8 C; A  f0 e# ~/ \
5 _' D$ j7 M; `( f5 T& l
e923ad767b8448b7ac37c4ed693724bd.png
' A( \& z1 b) j3 P2 [+ m' K% A  b; ~& ^: `, y
8 {, T# g  H% j/ }4 h6 s
​3、串口DMA收发工作原理4 S+ m" l4 O% k4 p! n
        串口全称为串行通讯接口,即数据在通信线上一次传输一位,按先后一定顺序传输。我们通常所说的单片机串口准确来说应该是串行异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART),使用TTL电平,串口需要RXD、TXD、GND三根线进行通信。
1 s* P0 T/ m% m/ Z# \! t7 q4 B6 }6 F  q/ r- ?
    (1)最常用的RS485收发换向方法是程序换向,即由MCU的一个I/O端口控制RS485收发器件的收发使能引脚,在平时使RS485收发器件处于接收状态
, f, m* X: W: Y  j' t8 ^
& L; Z7 j) ]% D% S& r     (2)我们选用的STM32L431RCT6开发板串口2作为RS485通信的串口,PA1作为RS485串口收发的使能控制引脚。
# N- D4 F% |6 b# }- X8 [
7 u2 a  F! t0 a1 k- n9 T     (3)RS485端口使用时,需要使用USB转485模块和开发板进行通信,使用方法为USB转485模块的A接开发板的A,USB转485模块的B接开发的B,GND可不接。7 {; Z% V2 B: x9 B" U- i

4 p+ E# y* R1 v+ E5 hRS485串口,硬件原理图如下所示:
5 z- t0 Y& ?5 H9 w' r
3 z7 r4 z9 w+ k6 }( I% x
1f72998fadef42548ee482c9fe064c08.png # p8 ]: [; V) {% f, C8 M

/ ]% ?" B6 l, E: I
182841b93d1e40b0913e3a54b22d0704.png
1 X+ A1 g/ f4 y8 C( q8 e# N  h
! v2 r& f* l" O% s* s! R
DMA(Direct Memory Access) :直接存储器存取,是单片机的一个外设,它的主要功能是用来搬数据,但是不需要占用 CPU,即在传输数据的时候, CPU 可以干其他的事情,好像是多线程一样。数据传输支持从外设到存储器或者存储器到存储器,这里的存储器可以是 SRAM 或者是 FLASH。
9 J; m9 c! e  B7 _% A
  L9 }4 z& y+ n: U+ [& R( NDMA 控制器包含了 DMA1 和 DMA2,其中 DMA1 有 7 个通道, DMA2 有 5 个通道,这里的通道可以理解为传输数据的一种管道。要注意的是 DMA2 只存在于大容量的单片机中。
& O( d8 L+ C0 @- P9 s: u: c* M5 n- Q2 b$ U
354955ecc6b140049ec57af71fe199f1.png
) b& Z& }6 B( A- X$ ~, |+ q) P
- c2 {( g2 ^. S& M  二、串口DMA收发实验过程
; s9 O8 A# ^( n/ |1、新建STM32CubeMX基础工程
5 v9 J6 W5 w) P3 Z: S2 s' T: z6 B
(1)打开STM32CubeMX,点击“File”-->"New Project"
  y- p7 q; W0 V; y5 V! T; J; f2 w6 j. t
2399170347904e959c855fefd5877f84.png % `# G' x$ Z- V5 x

1 O* B) a& e% N# R3 y; L! i: |(2)等待打开主芯片选项界面(大约1分钟时间)。
, l- p2 W, A* n* U. Y1 R5 g0 `2 Q& O  v  S: K  Y5 k
d74d2fdc60c9440483e2b7cf8d928e7f.png
, S, D, ?" p0 Y8 m; x, l/ q* c
- O/ t, }9 G5 c' o" G7 D
(3)昨天搜索框中输入(或选择)所需的主芯片型号(因为我们用的是STM32L431RCT6开发板,所以此处选择STM32L431RC),然后在右下角选择STM32L431RCTx(因为开发板主芯片是STM32L431RCT6),左键双击即可打开新建的项目。! W: i8 G! f, c1 w

0 ^* [( v# @5 z8 g$ d
6 i, ]  Q* K) Q4 ]% v: n; W: @
7b80345238d74bea82ce70e1a348f7b4.png
" ]; k3 H4 R3 G) }- R2 [3 V
! E4 k) m- q. {" @4 c4 t1 b/ t. A
(4)选择时钟源。
/ ?: m/ }# n* x( C        因为开发板上有8M外部时钟,硬件原理图如下所示,所以此处选择使用外部高速时钟(HSE)。
# d: e! e! ]" a& Z5 V" h
+ [: Q& w& k# l; X+ z# \% M
3f65707eca104663a3dede6d25dfa961.png 5 n3 J) \5 o& Z3 ?$ a" F0 L9 L2 C- _$ U& Z

; H) e/ ]6 c' K) R# v        因为我们没有用到外部低速时钟(LSE),此处不做处理,如下图所示。8 w3 J: V7 c! R# w# k

/ h0 q1 K: \' a9 z6 j4 s
72119b971f62410fa8344f7f9fb9f389.png * |- J5 C* h* |
+ ?2 p3 j' [+ d0 s$ S( q' c
2、配置GPIO控制LED3 G, \( g2 n7 b4 J5 u  Y$ @
(1)查开发板原理图得,LED1、LED2、LED3、LED4的控制引脚分别为:/ N8 C  E+ O, Q8 j: V
LED1——PC0
6 a6 _' c4 J1 E6 N6 T! k- ~8 sLED2——PC1+ Z2 n  t9 e- ?% s6 w$ k2 u
LED3——PC2) \( w; I3 R. K4 P9 I. w9 J9 Y; D
LED4——PC3: [- a, i- T) x6 A6 S8 ~* u. e8 I
- H8 Z+ w! p; E7 ]! ^
(2)配置LED的控制引脚为输出,输出频率、输出方式默认即可。3 c* G% V+ B  N0 j7 m1 L
鼠标左键点击PC0,选择“GPIO_Output”,表示设置该引脚为输出模式。' ~, r1 `  X: w- B$ R
鼠标左键点击PC1,选择“GPIO_Output”,表示设置该引脚为输出模式。
! X2 Z, M! I9 K8 U鼠标左键点击PC2,选择“GPIO_Output”,表示设置该引脚为输出模式。% ~; W: R( N$ b$ G0 o
鼠标左键点击PC3,选择“GPIO_Output”,表示设置该引脚为输出模式。( T" i# D4 _- b2 a- X6 R

* F8 l- b+ @4 j4 g
492907c1e71149819adbaee4516a2af4.png ; F& k$ y$ j! @' l- ~4 z& T
6 A* e2 \0 X7 W- t4 f) L2 G
c75d3f10ba2e427d9c1a10fad9bf5471.png 3 ], \3 Q: y: N# d8 _

: o$ p1 F2 f; |' E* C. X3 O8 F(3)也根据自己的需求配置GPIO的参数,如输出方式、输出频率、上拉下拉等。因为GPIO控制LED的要求比较低,此处采用默认参数即可,不用修改。
% y5 W) h$ w9 G7 U( z
7 G& h" K& }- R0 C2 R- y% }
38ff4b80e1c5495ba3076a5158fd91fa.png - G$ R; `) Q/ h9 D1 }" p3 d

% y' _; R) R- \2 ]' r​​3、配置PA2、PA3为串口
! B( R" O( S7 ^! n3 F0 G(1)查原理图得知,串口2使用STM32L431RCT6引脚为PA2-USART2_TX,PA3-USART2_RX,引脚设置如下:
3 a9 [' [, A3 b: d; k* R, U2 t# s( ~
9bd645a9032647d280107cc82b5a0f67.png
7 a: u6 Q9 R' D. l3 |4 n9 V
6 p0 C4 @" m8 J. K: G1 Y: n6 y串口参数默认即可:波特率115200-N-8-1,并使能收发控制引脚。4 \9 ~3 n7 y2 T9 F# _5 F3 M
1 J! A7 |& L5 x2 t5 r
74f5d7878df343ae83c9af5ed79c6a7c.png
5 ~* U4 k& P; J8 i
" u& E( o# `6 D! \# @& V( ~
(2)设置NVIC settings 使能接收中断。
7 W$ S* s- k- I! M; r
" H6 o3 E1 Q; B$ E
fde3c5c1ac9d4896b40dc5f5e15c3e61.png ' [' o; _% d+ y! n
3 \: D/ z- D7 W5 Z
3、串口DMA设置
$ }( S* l- F- [# O  Y
7 R0 ]. w4 T2 S, K5 v% i' d7 P
6d26b13dd9d34039a2b426ca47680f8c.png
5 G9 u/ m6 I/ W" L# a, k1 }( B0 t& a; ^" r  i! S& h: @8 W4 B
(1)根据DMA1通道预览可以得出,我们用的串口2的TX、RX分别为通道6、通道7:6 W& p- A. S- c8 d
点击DMASettings 点击 Add 添加通道9 E$ B7 U: @! b* J9 q, T& i
选择USART_RX USART_TX 传输速率设置为中速! w5 R- Z6 |4 q; c9 x  i$ p% u
DMA传输模式为正常模式,即发送一次就结束。
* \3 L8 X9 k% J% i" FDMA内存地址自增,每次增加一个Byte(字节)
* [% y$ y- ^+ U2 V. X+ j# P  T. h( ?+ t0 U; e& a! g! \! N# B( D) r
55bd687bfb1c4640847f6cba6ea373b9.png " q4 F1 c& F) t, L; R
+ _3 l; [$ ^. W9 i( R. n
(2)DMA相关参数解析
& o; u$ T+ R- c+ ~Dirction : DMA传输方向有四类
" j; _* R$ d8 y外设到内存 Peripheral To Memory! U, Z* i0 [8 x1 V7 |$ ?* t
内存到外设 Memory To Peripheral- Y( ^. y2 |- n# z* c# Q5 o& i
内存到内存 Memory To Memory8 ^# h- Z$ p0 v  n2 H: p) z  A
外设到外设 Peripheral To Peripheral
+ h4 u: ~( f; W" s$ d' V% F: e  {" w; P; j, w5 n% E* z9 G
Priority: DMA通信传输速度有四类
* ]. }! _5 n1 s最高优先级 Very Hight
5 W9 S  M+ h. q& [* `高优先级 Hight
; `$ E7 t# ]/ E- ^& p: ?; Y4 b中等优先级 Medium7 E# [, s. q" J3 k
低优先级;Low
2 Z3 |1 C7 B# |. J! G6 n3 H5 j8 v
( ]5 t: @  @; V! A0 \
Mode:DMA传输模式有两类; T! A& a" N- Y* x) [1 ^/ v6 U
; Y2 q6 V1 l6 x7 z6 S; W- r- Y
9021c11fed3e4c1885477e062b846258.png
' g+ a, {# X3 W) a6 A- A. ~  R! {, t6 N  l4 @' |# D6 h4 w
Normal正常模式:当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次。
2 a1 v6 b1 C. o7 pCircle循环模式:传输完成后又重新开始继续传输,不断循环永不停止。+ R& Q. }4 B7 G+ r0 P( E1 i

; E: N% d& \5 H6 [3 W: L
Increment Address-DMA指针递增设置:" y) }0 ^* ?2 H. N

! }0 u2 b2 C* l# l6 E6 ]) B4 W0 i$ [- \
2b1a952d6514444e9dbb019a9ae88c42.png & Z% E, v# S8 K" m# N& b* r8 j# V& b4 l
7 U2 t8 Y2 j: c2 x( e4 W; O
7 f4 p. i) V8 A+ k
4、配置项目工程参数  ^; h, @* t7 C5 P9 r' D3 @7 ~; x
(1)配置时钟树,用于系统内部时钟,以及各个外设时钟等。此处选择外部8M晶振作为主时钟频率,内部最大倍频80MHz。
1 i# F: k- D" ^  B6 E6 {  M
1 G1 a( Q6 S) c8 ?$ y' |
f3ecedd9323f4463b69539906b3c1199.png ' R1 f! D# W4 D# ^. B$ `/ }
0 Y- W; S2 m/ k: h7 ~3 h5 J; B
(2)完成配置工程。' r* ~' `1 S4 d, b+ L
备注:需要注意代码生成过程中的继承关系,如图所示:需要保留开发者自己编写的代码时,请根据配置设置,不然生成代码后会删除自己编写的代码(从这个方面也可以看出开发者备份自己的代码是多么的重要。)
9 I* |$ O3 K+ ^" ?% M) r4 p6 g1 K6 V5 b, |  M
efdb616174f54925b6eac31109f227b5.png   e' q' g0 r; X+ Q; d6 H- J1 X
​​
% y7 T9 W* s" U6 _" g 41c3f2716e4e4eda8f62fa3a1d871322.png 6 ^2 A' H2 z/ [5 `

) x9 g$ s8 k5 y5 |, `8 a, \; l(3)生成代码。! M' ^& y2 B6 w- ?
备注:使用Generate CODE生成工程代码前,请确保文件路径无中文,否则会生成项目失败。
0 F  x" r8 g2 c2 l2 C, p5 e
4 c" [2 m! G# p" t
8eaa7d0babea40ee93f158481a6ee471.png 1 Z& p/ Q2 _! [& D. k
​​: f% h) B: A3 i7 a; t
(4)工程代码生成成功。& I% I( r' o% A. s0 L! l' G$ ^& ]

7 k7 V  {/ t8 I6 B! N0 F
e8f46d59a1fb4af589feb613fdff17b4.png . ~4 b$ R1 n( [) B9 e" e/ k: P
9 S3 v0 V- Z- S3 S

4 W3 n/ X" d, h& @3 z 三、在KEIL 5中编写代码4 O# R. B: U$ o* D) w2 B
1、使用KEIL 5(MDK)打开项目工程文件
& r, K) j3 w; Y) z6 s
源码使用说明:使用前必须把项目工程复制到无中文路径的文件夹下使用。# ^0 U/ F9 [/ T5 G  B7 m

2 \. k# X1 J$ a$ U(1)找到刚才新建工程的存储路径,安装项目名称,打开项目工程.uvprojx。5 e7 w3 _* Y% v4 s7 V! N

1 R, p: e9 G; X" ?& e& {5 a# K
ec2f10465e0a49e9845c70b067c393ff.png
0 [& c* `: d( ^' e' N) [9 C( {+ c9 X( ?8 B% H
2、添加LED指示灯作为系统提示
. a$ T" d/ v# @" E添加每隔100ms,LED1、LED2、LED3、LED4闪烁一次的系统提示,用于提示程序运行正常。7 I( M. x8 _9 A5 k' B6 q

- ^: a' e* T8 C! D& ^
2af9ef3cfaab45988c810d94d801fc34.png
3 W8 }6 j, _1 a6 T& E% a5 {6 _4 Y/ G# z
3、添加HAL库UART  DMA 发送函数代码
, v2 C5 Z3 e9 a( R0 t(1)STM32 HAL函数库的串口DMA相关函数如下:
0 \' I, ?) V* \2 ^- \  K
  1. HAL_UART_Transmit();串口发送数据,使用超时管理机制
    $ S0 F. ?0 g5 S& F
  2. HAL_UART_Receive();串口接收数据,使用超时管理机制
    ; B8 ]8 o7 Y3 X0 \6 T  e- X
  3. HAL_UART_Transmit_IT();串口中断模式发送3 f# t4 ~  X6 k6 ^4 k1 a
  4. HAL_UART_Receive_IT();串口中断模式接收" w" ]0 {2 a2 k7 o  P, F, f4 D
  5. HAL_UART_Transmit_DMA();串口DMA模式发送
    6 h9 W) t' M1 T% E4 @9 u2 ]
  6. HAL_UART_Transmit_DMA();串口DMA模式接收
    . u! L' m% }$ N$ n( r1 f
  7. HAL_UART_DMAPause() 暂停串口DMA
    $ u8 H' p4 {/ ~) o3 Y
  8. HAL_UART_DMAResume(); 恢复串口DMA! S& n6 k1 S( W2 v/ U" T$ s
  9. HAL_UART_DMAStop(); 结束串口DMA
复制代码
+ |2 s$ k& F  {9 @( k' X
(2)main.c添加RS485发送函数相关代码:# C( I/ b6 E5 ~' C) Y2 I
/ H0 o" _7 @9 \! o$ }/ A, \
33126cad704048e48421455e369f78bf.png - P1 S* g" H% @/ X# i

7 F, o0 p! u. S, D: z
  1. /* USER CODE BEGIN 0 */5 G. h  k( V- v
  2. uart_rx_struct uart_rx_struct_t= {0};                               //串口接收数组
    . c- u; i1 }4 u$ k
  3. uart_rx_struct uart2_rx_struct_t= {0};                              //RS485串口接收数组
    , `! F( W2 c: S! c
  4. /*******************************************
    4 }6 d3 s" p5 Y3 _0 B
  5. *函数名:DMA_Usart_Send# Z  l3 V  o7 K/ H, T
  6. *功能说明: 串口发送功能函数
    # u& }  }5 @+ G% a; C7 F; I
  7. *形  参: buf,len
    0 U0 _2 q% N9 T
  8. *返 回 值: 无
    : J% e# i) E1 d8 o1 U2 y
  9. ********************************************/9 h# o4 w" N' e* }" n+ T

  10. 0 O  c) l, C2 u5 |7 z
  11. void DMA_Usart2_Send(uint8_t *buf,uint8_t len)/ u( L- P7 J  L8 p$ ]
  12. {* D$ @3 V; A. {3 k6 \" V6 z
  13.     HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);                 //设置485为发送状态
    0 f' Z; X! e2 w% g
  14.     if(HAL_UART_Transmit_DMA(&huart2, buf,len)!= HAL_OK)     //判断是否发送正常,如果出现异常则进入异常中断函敿
    / C, z, J7 n3 d' Y" ~- @" u& G) Q
  15.     {- M" M! Q( c( m4 s
  16.         Error_Handler();                                                                        //异常提醒
    $ T0 R6 ]7 R4 v" t! w/ G! o
  17.     }
    5 K3 P5 f2 X1 m: d
  18.     HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);    //设置485为接收状态3 r. t* i% X+ _! \
  19. }
    # h: w# e, ^' D( {

  20. 7 a" j# b. S& K  I. }
  21. /* USER CODE END 0 */
复制代码

( b$ @2 {5 t9 ]! [- E(3)main.c文件中添加main函数的处理,上电初始化打印一次log,然后等待接收,等串口收到数据后从原串口发出。
1 V3 g/ X, h* S, i; ]9 a8 o# }
- v- S) w  S' }  V3 g
cb23e78dcc0c4cedbdd965cd95a06c07.png
& Q# c: l1 t9 c* K
2 H2 y2 y3 Y* H6 V5 O. o4 n
af25c79e68fd48b8b0fb1e456645ff74.png % m, D# |6 |3 W; k/ X

; c; l% m7 `- [
0952de54d7b341ee97e81e22114d369e.png . ?0 G# B# \$ D# w: |

. Z; w; R$ Q) @3 [: ]- ?, n1 j% P8 Z& {' C2 c
  1. int main(void)2 T7 ~; f3 o9 F1 H* L. e
  2. {" m& H; U0 J" U9 n4 Q1 q
  3.     /* USER CODE BEGIN 1 */) Q% V/ Q# c" \; q) v$ D% m
  4.     uint8_t transmit_str[50]= {"hello world,this is uart dma function!\r\n"};. t; U. d$ o, }. x" _: I+ W
  5.     uint8_t rs485_str[50]= {"hello world,this is uart2 dma function!\r\n"};7 s% G  I6 a* C, B- Z8 q
  6.     /* USER CODE END 1 */
    ) A6 Q# n! D* l/ e
  7. 3 ^/ W) n0 A1 ?6 |! U! ?
  8.     /* MCU Configuration--------------------------------------------------------*/
    0 o/ e& u7 ~/ i" Q; H

  9. & L& H9 e  M' c2 ]: D+ R. I
  10.     /* Reset of all peripherals, Initializes the Flash interface and the Systick. */, M: R; ~8 {/ _2 }7 M8 t
  11.     HAL_Init();* `2 K( G& @) a8 T6 m  C

  12. " H1 W3 ]$ D) ?4 q" q& m
  13.     /* USER CODE BEGIN Init */
    4 ]6 n& u) ]. R# J  j

  14. 4 i# X( c( l6 D9 ]' q" e7 m1 o
  15.     /* USER CODE END Init */! ?2 ~" z0 A0 r5 p* ], y* e/ K
  16. / p) l' i  X4 R  b, V% c: {$ Z: L
  17.     /* Configure the system clock */! s1 ^- `/ q8 N  M6 S: w  _  Y
  18.     SystemClock_Config();3 N5 u8 `0 i& Q3 O4 z' ^- V! R, m
  19. : U. v5 F6 a4 R  d
  20.     /* USER CODE BEGIN SysInit */
    ) o( ~- i& t- X( K6 J
  21. 4 W5 G; \) L) b- y8 S4 m- b7 M
  22.     /* USER CODE END SysInit */# w4 a1 R8 {* s; |$ G

  23. " ]7 ?, t; ^! u* A2 c
  24.     /* Initialize all configured peripherals */5 |* D, ?! I2 i4 q
  25.     MX_GPIO_Init();
    ( k4 [4 k! t7 R* W2 }. a7 v
  26.     MX_DMA_Init();
    # C) X# Q- `& P! d; g
  27.     MX_USART1_UART_Init();# e8 B) A; k: X4 q8 N2 o9 ]+ c- [
  28.     MX_USART2_UART_Init();
    7 Y1 ]3 f+ j+ a! u. w8 E
  29.     /* USER CODE BEGIN 2 */
    5 @" [4 D1 b+ Q' e' p
  30.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮+ s* o: X% G/ y4 W
  31.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮
    ) J+ ~: i6 a( R
  32.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮9 `7 K  E8 G. B
  33.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮
    5 v/ S7 R" B& g8 t# I; G
  34.     HAL_UART_Transmit_DMA(&huart1, (uint8_t*)transmit_str, sizeof(transmit_str));
    5 o7 E: N% ~8 p: R6 ]8 p: M( R
  35.     DMA_Usart2_Send((uint8_t*)rs485_str, sizeof(rs485_str));                        //初始化log提示$ M6 e3 x. s: y9 ^! M9 U
  36.     HAL_Delay(5);
      S& P2 l5 V0 l* b0 g8 v, l1 x
  37.     HAL_UART_Receive_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, UART_RX_LEN);         // 启动DMA接收
    - [" Z5 p7 ?, W" u$ t
  38.     HAL_UART_Receive_DMA(&huart2, uart2_rx_struct_t.uart_rx_buf, UART_RX_LEN);        // 启动DMA接收) [$ u7 a4 X* |( V" R( w) T
  39. 0 k9 Q! H/ z" L, ^, F
  40.     __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);                                      // 使能空闲中断
    + T7 U2 H: b$ m5 Q5 J6 a, z  T
  41.     __HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);                                      // 使能空闲中断7 Z: N! X1 g3 w8 [" H6 c  T

  42. / z4 h) [) u0 c
  43.     /* USER CODE END 2 */
    : F. b7 R  i8 a$ F( ^# Z% e9 y

  44. 7 X' R/ |- W  K! }" L7 ]. N
  45.     /* Infinite loop */! e4 f& C' |2 R3 ^! L% ?) Q- ?
  46.     /* USER CODE BEGIN WHILE */) p# S% j& g; L/ z3 e7 r  V
  47.     while (1)
    6 S/ u# d' f" z' I3 d6 V  D: B
  48.     {
    / F8 e: A2 B9 ?$ o+ E  e0 v1 ^/ B
  49.         /* USER CODE END WHILE */
    & T7 ]4 B, E2 E, m% B

  50. & O7 Y3 c: Y1 h) W9 g
  51.         /* USER CODE BEGIN 3 */5 V/ p/ G! ~0 p+ }& ]$ T- F& x
  52.         HAL_Delay(100);. W/ S& w: P2 ^* A% b
  53.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);                                                                        //反转LED点亮熄灭切换
    & g) l2 B5 E; M/ Z6 G8 C: D
  54.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_1);                                                                        //反转LED点亮熄灭切换
    9 h* V, E$ a5 R7 R
  55.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_2);                                                                        //反转LED点亮熄灭切换
    ! S( C$ `& G, ]+ H; v
  56.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_3);                                                                        //反转LED点亮熄灭切换$ p1 G' E4 O2 ~. ^+ D
  57.         if(uart_rx_struct_t.uart_rx_flag & 0X80)                                //DMA接收完成
    0 W, f- [/ v* t; E: x. I
  58.         {. B) ~  P8 L+ C
  59.             HAL_UART_Transmit_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, uart_rx_struct_t.uart_len);    // 将接收到的数据发送回去7 g( b$ u( ]3 I2 @! ^# j
  60.             uart_rx_struct_t.uart_rx_flag = 0;
    % z2 p0 p3 c" L, w1 \/ X6 [) B( n
  61.         }, |9 B( `& @1 _5 Z
  62.         if(uart2_rx_struct_t.uart_rx_flag & 0X80)                                //RS485 串口DMA接收完成6 n* R0 y! h8 R! G8 h9 a$ W
  63.         {+ a7 i" V, i1 H0 m
  64.             DMA_Usart2_Send((uint8_t*)uart2_rx_struct_t.uart_rx_buf, uart2_rx_struct_t.uart_len);                        //rs485发送. h/ K2 Z5 B( w+ x
  65.             uart2_rx_struct_t.uart_rx_flag = 0;
    7 x" K2 H+ N: J; P6 P6 c* U
  66.         }
    * E0 b% B4 V" X) M6 v9 f- `1 Y
  67. ( O+ V: x# Z1 n* L  A% `

  68. , K1 N& |" A3 G7 t5 b- S
  69.     }8 K8 @1 n" w1 H1 X4 P  U; l
  70.     /* USER CODE END 3 */! R2 r: {& R% q
  71. }
复制代码

- b$ b% p$ a2 ^& H" ~(3)main.h相关变量声明/ _- ~3 [2 K1 j& [3 s

" c& d8 W7 P, |
c30d0d2d5b464dfa93affa21394898a3.png 9 ]0 M. h! ^% |/ S

$ r: B* ?. k- j- \3 t. E
  1. /* USER CODE BEGIN ET */0 R* S2 F0 M4 v5 j  m
  2. #define UART_RX_LEN 1024                // 一次最大接收的数据量
    # k& e2 \+ D) D3 p# ]# k, ^7 N; a
  3. typedef struct& L- p3 t' H7 i% A$ N4 [) z
  4. {! k5 i4 J* ?, t! p
  5.     uint8_t uart_rx_buf[UART_RX_LEN];  // DMA数据接收缓存数组7 U8 k, }) U9 i3 X- D
  6.     uint16_t uart_len;                 //DMA数据接收长度  L( Y0 l- ?! [0 v* r" W
  7.     uint8_t uart_rx_flag;              //接收完成标志位- g' P+ n& X  V, _$ ~
  8. }uart_rx_struct;
    0 X# h% u9 N9 Q1 D5 C& S% c+ z
  9. extern uart_rx_struct uart_rx_struct_t;  
    ! J" m. ^2 B" ~% I) v, k
  10. extern uart_rx_struct uart2_rx_struct_t;- f" m3 h& z' M
  11. /* USER CODE END ET */
复制代码

- X: e9 L* i; Y+ K4、添加HAL库UART  DMA 接收函数代码( d8 L; O1 h0 l) v# v; L% s
(1)DMA接收设置前铺垫知识点:( s  c2 @; t8 z" Z

) \5 X( }4 D# K! j3 u" p        STM32的IDLE的中断产生条件:在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断停止。
# d" p$ J; V0 I: @) E3 c2 \5 h7 Z! L( W% C2 ]2 \; f3 Y6 }: F
(2)stm32f1xx_it.c中添加添加DMA接收处理代码:0 V7 U& K( G% J' e; s
  1. void USART2_IRQHandler(void)# N' T/ _! M  _+ }% _* C
  2. {
    $ f9 `' t  c' D( {# r
  3.     /* USER CODE BEGIN USART2_IRQn 0 */* h# y" W& v2 ^* y! j3 M
  4.     if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) != RESET)       // 空闲中断标记被置使7 A. a2 g" V! C/ u
  5.     {4 y0 y3 N/ J$ G+ C- _, ?
  6.         __HAL_UART_CLEAR_IDLEFLAG(&huart2);                         // 清除中断标记% q0 E+ d, V; C
  7.         HAL_UART_DMAStop(&huart2);                                  // 停止DMA接收
    , k: @3 g& l5 h
  8.         uart2_rx_struct_t.uart_len = UART_RX_LEN - __HAL_DMA_GET_COUNTER(huart2.hdmarx);  // 总数据量减去未接收到的数据量为已经接收到的数据量
    + w5 J: e( x% }6 O/ _' T: a
  9.         uart2_rx_struct_t.uart_rx_buf[uart2_rx_struct_t.uart_len] = 0;                    // 添加结束笿
    / N4 t7 a0 b6 B
  10.         uart2_rx_struct_t.uart_rx_flag |= 0x80;                                       // 标记接收结束
    + ?5 `1 T9 S/ u6 K, U' m
  11.         HAL_UART_Receive_DMA(&huart2, uart2_rx_struct_t.uart_rx_buf, UART_RX_LEN);        // 启动DMA接收  b3 k* S* ^4 |6 `9 |. U( G$ F& [

  12. 0 R; R0 M, _  |+ E* k7 _
  13.     }
    * z0 P) d0 d" Z1 |7 x( r0 N0 r6 F9 [
  14.     /* USER CODE END USART2_IRQn 0 */; |+ N7 |1 X" w1 D! Z$ B
  15.     HAL_UART_IRQHandler(&huart2);
    5 T; F! {/ G& l+ j
  16.     /* USER CODE BEGIN USART2_IRQn 1 */
    ( z6 g0 p3 B5 _: K* R
  17. & V3 k4 r. b" A% R6 v
  18.     /* USER CODE END USART2_IRQn 1 */* ?, j  ]0 H- y6 d
  19. }
复制代码

( J6 K1 c7 N% }, F' b% i(3)至此,RS485串口DMA收发数据需要添加的代码已经完成。0 F1 ]# j, ~1 K$ F

- r1 T' X7 K3 h9 o/ G, [
( e- V! l( W' K4 G/ N- g
5、设置编程仿真下载模式
' [( Y% N+ B, i0 t  H; z# ](1)选择Options for target ...>>Debug>>J-Link/J-JTRACE Cortex,点击Settings>>选择Port(SW),可以看到搜索成功SW Device,表示芯片可用,可以下载。# c9 S; B; ~+ c$ M; r3 T
% S1 f, D8 b  r9 B) S  U; C
edefb6b9a2a14be3b1221ad6d5c7a8a2.png
9 J, |( m1 s6 p% b7 u​​# z5 A3 |- h. k  M
(2)点击编译,完成后提示“0 error(s),0 warning(s)”。
! p( S) W1 i' D: I) f2 i3 O1 p; p  b8 B& `( n% X
e0b7e3e353b345a7987fe5f821de2dda.png ; v0 G0 ?  I. W6 p9 Q5 }& ]* h
​​: Y6 a! t' ^9 X" Q* N
(3)点击Download(或者快捷键F8),即可下载程序。% ~: `/ D% f5 C: e* ~# q$ `
8 d4 n$ f& h# L: k
eb3f250f19e44862a7df80c2492fcd01.png % \% s; d# O( F( F5 J

: ~: B# A6 p7 U7 N1 ]6 w8 i8 _. `7 y8 Y(4) 如果下载程序后,没有看到LED1、LED2、LED3、LED4闪烁,可以按下述方式设置一下(Reset and run表示下载后自动复位和重启运行)。或者重新彻底断电再次上电(或按开发板的Reset按键复位MCU即可)。
/ K4 c. L% C  e0 y; ^
5 V3 c# X3 C9 R2 ^/ N" \5 q
9f8aa1a4e8f04041bcf5cb183facd100.png
. Y( f' j$ L- k- G' S3 Y4 }8 F* N. o! C: j
6、串口DMA收发实验效果展示

- _3 E2 S" T  L+ C        程序烧录到开发板后,即可看到LED1、LED2、LED3、LED4初始化后每隔100ms闪烁一次,并且打开串口助手后(串口参数:波特率115200、N、8、1),通过串口助手可以看到,开发板接收到发送的数据转发出来。
9 m  U4 V# I  n1 B
& }" a: U9 u+ j- y& [: }; H5 r
f63ffa52c1ea43439547f62c39130706.png 7 s7 n  ^  W3 s/ L

. a8 w4 R$ M) r/ P————————————————+ V  s$ s! j7 S, [0 @
版权声明:智能小屋ZYXC/ n& K4 L$ R* e: {& x

$ B4 E+ g! Y! A8 @2 d  c, y) c% G+ s
收藏 评论0 发布时间:2023-1-13 20:00

举报

0个回答

所属标签

相似分享

官网相关资源

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