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

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

[复制链接]
STMCU小助手 发布时间:2023-1-13 20:00
   一、开发板平台简介:
& s8 b9 P; u6 B  }1、开发板资源简介
8 k1 h5 E& q8 ]  Z. u" o
(1)开发板主芯片型号:STM32L431RCT6(2)开发板主芯片封装:LQFP-64_10x10x05P
8 b  F4 H6 ^/ ?/ w(3)开发板主芯片内核:ARM® Cortex®-M4
" T1 x' d8 W% F/ Z6 a; J(4)开发板主芯片主频:80MHz9 g% h' y6 m% F  {* Q3 ^$ x
(5)开发板主芯片Flash大小:256KB
9 v2 E) \( j# y! n1 e(6)开发板主芯片RAM大小:64KB: _; R$ h) ?4 ]

/ R8 ~- ^, N, v, ?' d! k6 T
bb91345227434ee7a43a34bf3fe366e6.png 8 v$ C/ Y2 @+ H$ `: p* ~+ P5 T
8 v' }1 W7 ]; x3 `
929c0cce04aa4115a8623703982bf3e1.png
- V% g3 y  K0 L, B
- p* _8 L2 d" p7 O$ ]$ Q% C" `/ ?" W, |0 f5 Z
2、LED灯资源
, Z& k+ J0 ^0 V' q$ v2 ](1) STM32L431RCT6开发板共5个LED灯资源,其中一个红色LED为系统指示灯,指示开发板供电系统是否正常,如供电系统正常,红色LED为上电常亮状态,硬件原理图如下图所示:2 R0 n! w7 I5 y) w4 g
) ?  U3 ]: E: t9 I- ~/ `
0f177691c5814f16a508bcfa747f87ac.png
0 ?& R  t. d- ~0 P
0 R  N' l  H3 D+ y( p8 R$ |(2)其他四个LED灯为黄绿色可控LED,高电平点亮、低电平熄灭,计划用LED常亮验证看门狗的作用,硬件原理图如下图所示:
6 F# x  r. A. v  A# n& N( `
' A! s# s( t" I$ m: B
e923ad767b8448b7ac37c4ed693724bd.png # Z  d' t: c1 P% O& B

# Y( t8 e1 e3 b/ {- `# o! e$ J4 O, M8 Q
5 v% P& G) {4 }' s1 z. M​3、串口DMA收发工作原理
6 T" y; H4 i4 o7 A        串口全称为串行通讯接口,即数据在通信线上一次传输一位,按先后一定顺序传输。我们通常所说的单片机串口准确来说应该是串行异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART),使用TTL电平,串口需要RXD、TXD、GND三根线进行通信。0 H/ p1 l  J, g: o* r0 Q
- T- }' N4 y8 s6 V& v# c; Y
    (1)最常用的RS485收发换向方法是程序换向,即由MCU的一个I/O端口控制RS485收发器件的收发使能引脚,在平时使RS485收发器件处于接收状态' F' W$ @; ?2 i$ K

4 B1 S6 R) C! Z/ {7 f5 t/ f) c     (2)我们选用的STM32L431RCT6开发板串口2作为RS485通信的串口,PA1作为RS485串口收发的使能控制引脚。6 o) A+ \) M0 y
4 @) @; w, v3 t4 X0 h
     (3)RS485端口使用时,需要使用USB转485模块和开发板进行通信,使用方法为USB转485模块的A接开发板的A,USB转485模块的B接开发的B,GND可不接。7 W9 \% @4 y2 h' r2 ^! w3 ^
7 _0 Y; Y3 d  O1 T
RS485串口,硬件原理图如下所示:
4 j+ n) J* l$ Y, e1 u* z+ S2 }5 Y0 f
0 h! M7 _" k: S$ q1 l6 M3 r7 d
1f72998fadef42548ee482c9fe064c08.png 6 g! S* W' p; s7 P
9 P7 @9 a- M6 ^) G* B# W6 E& C
182841b93d1e40b0913e3a54b22d0704.png
, h6 h, q0 S" `( g% T& `' [! s
) S/ l+ X7 X+ _+ c/ B$ H* K
DMA(Direct Memory Access) :直接存储器存取,是单片机的一个外设,它的主要功能是用来搬数据,但是不需要占用 CPU,即在传输数据的时候, CPU 可以干其他的事情,好像是多线程一样。数据传输支持从外设到存储器或者存储器到存储器,这里的存储器可以是 SRAM 或者是 FLASH。
3 g7 l" I) v' n5 @! Y6 G. s
/ V0 {' U5 F  c& p: bDMA 控制器包含了 DMA1 和 DMA2,其中 DMA1 有 7 个通道, DMA2 有 5 个通道,这里的通道可以理解为传输数据的一种管道。要注意的是 DMA2 只存在于大容量的单片机中。8 C& s3 Q6 k2 w% P3 T* M0 f- \
6 `; W6 h. g1 T
354955ecc6b140049ec57af71fe199f1.png
& D+ \' x% v+ t2 X# T) d! n* _% L" y, I  X. c
  二、串口DMA收发实验过程9 k& ]+ m9 q, h3 ]: y
1、新建STM32CubeMX基础工程
$ ]+ r* i% B8 l- ?: P4 E
(1)打开STM32CubeMX,点击“File”-->"New Project"
3 L2 W/ O9 b, C7 j" }4 A0 ]
! }0 A& P# H% L8 |
2399170347904e959c855fefd5877f84.png 5 R( f9 o* o$ n0 T; ~

# I3 W- @  r; t6 D! G1 {* p5 Z2 E(2)等待打开主芯片选项界面(大约1分钟时间)。
! ^  e! a+ R/ J* t. X
7 v7 n. Y% F  C: L
d74d2fdc60c9440483e2b7cf8d928e7f.png 5 w3 T9 t+ [% H9 e

6 O2 E2 o# V' q! J! Y(3)昨天搜索框中输入(或选择)所需的主芯片型号(因为我们用的是STM32L431RCT6开发板,所以此处选择STM32L431RC),然后在右下角选择STM32L431RCTx(因为开发板主芯片是STM32L431RCT6),左键双击即可打开新建的项目。7 v/ d& j8 [! F" W/ E

5 [$ q5 o0 s" O6 C9 e9 `- b) c

" s$ f" T( a$ S/ |  F 7b80345238d74bea82ce70e1a348f7b4.png ) ]* x8 L/ F# v- l  @. k& H- o

, X/ v$ b. X/ m: y(4)选择时钟源。1 _; ]; Q# o! R- e# y: v& m
        因为开发板上有8M外部时钟,硬件原理图如下所示,所以此处选择使用外部高速时钟(HSE)。4 d6 a2 a7 Q. S

0 o9 X1 a& Y7 J: U0 Z
3f65707eca104663a3dede6d25dfa961.png / |" w9 E8 k  b: Z- t/ {8 j- z

3 b2 c, F, h. J% }3 z        因为我们没有用到外部低速时钟(LSE),此处不做处理,如下图所示。
/ z+ {; f+ V0 a. D1 J/ `' L3 D. d7 ^5 H1 w
72119b971f62410fa8344f7f9fb9f389.png 1 f+ A7 {! Y! h' D, F+ j

& w3 `6 ^6 E0 J2、配置GPIO控制LED
0 Z0 b/ u, V1 n% `, `3 Q(1)查开发板原理图得,LED1、LED2、LED3、LED4的控制引脚分别为:: e3 V1 _4 h. o  d
LED1——PC0
! b* \: c! q9 @" ~+ c$ W' mLED2——PC1; k, o0 U+ j# m# ^( w2 \
LED3——PC2+ _7 C0 P5 x) E: O4 _- F( D2 |
LED4——PC3$ V- `( [( w8 X$ O9 A6 L4 u8 V

2 C2 E/ @" f- _! L7 `: ^) D(2)配置LED的控制引脚为输出,输出频率、输出方式默认即可。
; ?" d. G6 {8 G$ o- _+ _9 o- K/ J8 q鼠标左键点击PC0,选择“GPIO_Output”,表示设置该引脚为输出模式。! c; U5 \8 j% B- @9 i8 T
鼠标左键点击PC1,选择“GPIO_Output”,表示设置该引脚为输出模式。
2 ^# Q/ m5 D8 Y/ t: o( z, K鼠标左键点击PC2,选择“GPIO_Output”,表示设置该引脚为输出模式。
8 P2 U% K# g4 h: S鼠标左键点击PC3,选择“GPIO_Output”,表示设置该引脚为输出模式。% K$ B* {; P3 ^1 L

. \! j$ Y& ?4 @3 ~9 R; l, _! v  b( L2 v
492907c1e71149819adbaee4516a2af4.png
# a9 v& w* D1 b6 [: r1 z( k1 e
# N* M* S+ w: R8 X
c75d3f10ba2e427d9c1a10fad9bf5471.png 0 N6 P( q, o% \  m2 t4 @" w: V

7 ]6 G3 u% A0 `, A6 m% Y( D(3)也根据自己的需求配置GPIO的参数,如输出方式、输出频率、上拉下拉等。因为GPIO控制LED的要求比较低,此处采用默认参数即可,不用修改。
* k6 K+ e8 ?; q; z, I+ R: t8 D$ p; L$ @6 Q
38ff4b80e1c5495ba3076a5158fd91fa.png
9 n$ t# A2 D" x* i7 X
- W' q  h4 h/ V( x& v6 G​​3、配置PA2、PA3为串口
; x  K$ G' l# u' {' D; z: l, t(1)查原理图得知,串口2使用STM32L431RCT6引脚为PA2-USART2_TX,PA3-USART2_RX,引脚设置如下:: n: t' z0 x3 N

9 |; n' V! {" k3 r
9bd645a9032647d280107cc82b5a0f67.png ' L+ Q+ M* B2 m8 x* C, I/ O
* k5 d9 ]% h/ G& A
串口参数默认即可:波特率115200-N-8-1,并使能收发控制引脚。4 K8 w' y2 |2 \) l4 x- q6 I7 [+ P( V

2 y  |( V+ O4 ~3 z
74f5d7878df343ae83c9af5ed79c6a7c.png . B* x+ s' b/ {9 R
$ s. n) p" M4 \
(2)设置NVIC settings 使能接收中断。0 Y& d% _$ t3 n( T' v. c8 a+ B1 [
" m% k4 n- @' N
fde3c5c1ac9d4896b40dc5f5e15c3e61.png
/ V8 e/ ]- N, ~/ \
/ a/ v, B+ Z3 W$ G9 \( f
3、串口DMA设置 + X. B6 J: F3 D, x1 F
1 j: ~) p4 j! a0 ~
6d26b13dd9d34039a2b426ca47680f8c.png ; A6 a' ^& f1 @) q3 I7 G
. `( T3 ?5 l+ x. c2 v
(1)根据DMA1通道预览可以得出,我们用的串口2的TX、RX分别为通道6、通道7:
% w3 R8 i5 R! h8 |1 V6 S2 o$ e0 e点击DMASettings 点击 Add 添加通道5 C1 D% ?* T; w: W8 D
选择USART_RX USART_TX 传输速率设置为中速
0 _$ p) r: f. SDMA传输模式为正常模式,即发送一次就结束。5 {) r+ z0 J/ y! t5 N. R& f5 p
DMA内存地址自增,每次增加一个Byte(字节): n6 Q1 d- V  {' K
, \1 O: |. g( v4 ~& ?0 {. [! s
55bd687bfb1c4640847f6cba6ea373b9.png
5 |% Y3 L$ ]- z% R
2 V4 y; y( m1 a. m (2)DMA相关参数解析
1 T  M8 z+ J; Y' J6 m5 f, HDirction : DMA传输方向有四类
* R- m: ~7 I9 [+ t  d外设到内存 Peripheral To Memory' p( U; w  Z7 k  B; E1 `- q
内存到外设 Memory To Peripheral
/ O. t5 {; ~# J7 _& n% g3 {6 O内存到内存 Memory To Memory. @" V, \- I) i7 b; H- ~
外设到外设 Peripheral To Peripheral
- o5 j, c; B5 h* @% [% O! f, M- s3 `) O( @: W% {+ U
Priority: DMA通信传输速度有四类5 V3 ?" a9 v9 n2 |$ [. j& {& _8 S
最高优先级 Very Hight
/ |8 N0 h9 h3 Q9 J( h$ k高优先级 Hight
* x, Y+ L4 f5 l/ S6 z8 o中等优先级 Medium
, N; D6 O  ~5 E! |+ Y低优先级;Low
% U/ U: f3 z& k( Q' y
2 z! c# S4 y7 I' G7 ~
Mode:DMA传输模式有两类
' q  E' E/ Q# ^5 q( S4 a# Q8 p# ]+ P' k
9021c11fed3e4c1885477e062b846258.png 6 g& h2 x* x5 c& R, J: W
" v- x9 K7 Y4 s/ a  K; h  y- x
Normal正常模式:当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次。, T& K' y7 ?, ~
Circle循环模式:传输完成后又重新开始继续传输,不断循环永不停止。- j! \9 U& }8 A) h

$ G: f9 n* L  L. B5 T6 `0 P* w
Increment Address-DMA指针递增设置:
  Z: F3 o% |3 M2 n( v, d7 q. I# t' h4 r8 H% s- _
2b1a952d6514444e9dbb019a9ae88c42.png 0 x7 P" _9 ~+ n8 B
+ i% p7 C/ N# D  t* V

5 {* H! W. v/ U  B1 I  a& x4、配置项目工程参数9 A" Y+ Q7 d+ F* }3 D
(1)配置时钟树,用于系统内部时钟,以及各个外设时钟等。此处选择外部8M晶振作为主时钟频率,内部最大倍频80MHz。3 Z5 C0 T9 R/ y" V

! T6 A, T- u- X; C
f3ecedd9323f4463b69539906b3c1199.png % l/ v5 b; \* _$ h) Z8 q

8 P% a. r9 d" Y  t6 ?1 g# ~1 j(2)完成配置工程。- ^( l$ g7 h: l7 E' R! W+ W. \
备注:需要注意代码生成过程中的继承关系,如图所示:需要保留开发者自己编写的代码时,请根据配置设置,不然生成代码后会删除自己编写的代码(从这个方面也可以看出开发者备份自己的代码是多么的重要。)
3 Q+ h& E' F: f, l- C9 |4 z$ l' X+ H# v* Y; a1 z4 |1 H& ~/ I
efdb616174f54925b6eac31109f227b5.png 9 P/ h& u: i. F/ R, ]) _+ U8 `
​​2 e! g4 h# H9 Z& P& w
41c3f2716e4e4eda8f62fa3a1d871322.png
7 R# {; Q; Z9 F8 W

, [. j/ E/ P' x1 |# p(3)生成代码。, Q- e" ]" |/ _- O
备注:使用Generate CODE生成工程代码前,请确保文件路径无中文,否则会生成项目失败。  j5 C( O" J: b: C% E
6 R. o7 c+ g, p0 v: ]( x
8eaa7d0babea40ee93f158481a6ee471.png
3 M! q( s# R1 H​​) m1 |' U! k1 \7 W
(4)工程代码生成成功。/ N, t1 u) n3 Z, C$ o' X3 k
$ P6 w6 V# O# A7 l; v
e8f46d59a1fb4af589feb613fdff17b4.png
$ i0 K" u# Y5 s. a; f* W: Y$ p% z3 {' X. a6 z; g

, M4 B; H' P4 H/ N) o  H 三、在KEIL 5中编写代码- }- O2 [9 s0 u7 U' [
1、使用KEIL 5(MDK)打开项目工程文件

( ?' z" B. e3 R+ m源码使用说明:使用前必须把项目工程复制到无中文路径的文件夹下使用。& W# s) D% _8 w$ G; Z, [* o- X4 q1 r

% Q6 j4 C% N  D5 ~; c(1)找到刚才新建工程的存储路径,安装项目名称,打开项目工程.uvprojx。7 K+ I; D: C* [& t% S/ ^# e

6 E; m; \! G  }
ec2f10465e0a49e9845c70b067c393ff.png
9 r8 M1 ?7 C$ g  m1 C' d) R* B* t$ F
2、添加LED指示灯作为系统提示
/ W" Z6 j, s( x! Y添加每隔100ms,LED1、LED2、LED3、LED4闪烁一次的系统提示,用于提示程序运行正常。
7 ^& B* g; [% ^- h7 |- w! z8 a
& W, r9 n( f( S9 x+ d
2af9ef3cfaab45988c810d94d801fc34.png ) X4 M4 ~3 s! y# L2 A
9 s. ^# L0 W' [) z: L, S
3、添加HAL库UART  DMA 发送函数代码
5 ~3 L5 t( j' A$ x5 n9 v$ x2 W) b(1)STM32 HAL函数库的串口DMA相关函数如下:' t% q9 Q( t( k0 T5 {! l/ P3 r4 u
  1. HAL_UART_Transmit();串口发送数据,使用超时管理机制6 e) ^; y% v$ Q0 x
  2. HAL_UART_Receive();串口接收数据,使用超时管理机制
      q  _! K$ O! a( E" }9 Y- G
  3. HAL_UART_Transmit_IT();串口中断模式发送
    ! p% |- |; U( A1 g" v9 _; @
  4. HAL_UART_Receive_IT();串口中断模式接收
    " E% B% N2 {# G7 ~3 ~
  5. HAL_UART_Transmit_DMA();串口DMA模式发送
    $ x% Z6 }0 A8 [# M8 h
  6. HAL_UART_Transmit_DMA();串口DMA模式接收
    5 h' Z+ o' f: f# ^- l
  7. HAL_UART_DMAPause() 暂停串口DMA
    4 J6 _7 `9 T. |! Y: x$ G0 X
  8. HAL_UART_DMAResume(); 恢复串口DMA# F- s5 ~5 g9 {' p
  9. HAL_UART_DMAStop(); 结束串口DMA
复制代码

. S7 `6 q2 Z* w. N(2)main.c添加RS485发送函数相关代码:
/ f+ |0 L$ _6 ]+ J" x+ h$ t9 ^6 @! _) l' j9 l" I' C4 V
33126cad704048e48421455e369f78bf.png
' h- p; a! a; P3 O6 h; T% ^- Q# P. z. I- z. R9 U# E! f% }% F
  1. /* USER CODE BEGIN 0 */
    0 X/ g  w# q$ X* l) x
  2. uart_rx_struct uart_rx_struct_t= {0};                               //串口接收数组5 k" \; i# X" f  Y4 Z9 u  `+ ]
  3. uart_rx_struct uart2_rx_struct_t= {0};                              //RS485串口接收数组  o* I. g; Y, E; P4 j- P
  4. /*******************************************
    - w( Q$ p2 `7 w& F
  5. *函数名:DMA_Usart_Send- {/ c9 \" w9 R) y, {" B
  6. *功能说明: 串口发送功能函数' |2 f9 Q5 X+ A+ C! s! ?& T' F+ X
  7. *形  参: buf,len
    - G: u1 U( f# U1 _) u' T
  8. *返 回 值: 无
    $ f, Z4 }  h; P7 _
  9. ********************************************/
    + L3 Q- `- I) ?+ J4 `" B6 ]

  10. 5 S: V6 q4 _% l
  11. void DMA_Usart2_Send(uint8_t *buf,uint8_t len)
    " L  ~! j# {7 y" E, ~. M
  12. {
    : _7 D, s  V7 b
  13.     HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);                 //设置485为发送状态% f5 d/ t1 c( h( g' U7 N% \
  14.     if(HAL_UART_Transmit_DMA(&huart2, buf,len)!= HAL_OK)     //判断是否发送正常,如果出现异常则进入异常中断函敿
    & q( B2 t5 w5 C5 @: ^: W; t1 P
  15.     {$ b$ l$ U( a( `) e% a2 O/ u5 W
  16.         Error_Handler();                                                                        //异常提醒2 B  A0 u1 R% J4 \* M. \7 L
  17.     }2 m, ^, W0 B4 O' F1 Y# T; u5 ^
  18.     HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);    //设置485为接收状态
    4 w5 }: v! ]8 b0 R$ _- D
  19. }
    # y. S% K$ }" Y& @6 h# U# |5 v4 J' e

  20. - W+ u! m8 ~4 W- V/ C' I4 V- j
  21. /* USER CODE END 0 */
复制代码

- b) I3 ?& E$ q: f+ M1 T# d(3)main.c文件中添加main函数的处理,上电初始化打印一次log,然后等待接收,等串口收到数据后从原串口发出。
- r3 a8 t" x  k+ T- g1 W- c
$ S. j5 n" N1 H' n4 r
cb23e78dcc0c4cedbdd965cd95a06c07.png   L7 X8 {# u5 \6 F2 T3 O
$ C. [6 K+ Z0 {% Z: n* V
af25c79e68fd48b8b0fb1e456645ff74.png
! N: C2 R4 |* T1 W* t0 }* X/ }8 K+ M* Y) A1 A
0952de54d7b341ee97e81e22114d369e.png - I( q) q, @4 @, L

6 V/ g! R0 [4 q1 S! ~
5 b4 x1 y0 s. m3 ?7 `
  1. int main(void)
    + y5 L% @( d$ Q4 [- @
  2. {( i. a4 N2 h) E$ J6 ?
  3.     /* USER CODE BEGIN 1 */) ]* s. a; O4 o
  4.     uint8_t transmit_str[50]= {"hello world,this is uart dma function!\r\n"};
    ( j( P( Z8 J& Z6 R
  5.     uint8_t rs485_str[50]= {"hello world,this is uart2 dma function!\r\n"};' o8 o0 ]# T: W& s9 A" d- j
  6.     /* USER CODE END 1 */( G! |7 m8 t  s

  7. . {0 b, Y- H# e2 M& \" O' @, G
  8.     /* MCU Configuration--------------------------------------------------------*/1 x, s) H3 l6 ?  o8 }

  9. / F8 B% c4 J8 @" C
  10.     /* Reset of all peripherals, Initializes the Flash interface and the Systick. */9 V- F# |$ F/ G- B- N8 e
  11.     HAL_Init();
    * s# b% S! ~0 Y! V

  12.   l$ T6 t2 G- {3 t, \+ i# X
  13.     /* USER CODE BEGIN Init */! ^  I/ ^8 V; B# H. g# i* G( `! D

  14. 4 z' `# F( r3 P" d
  15.     /* USER CODE END Init */
    # }( J2 z9 o8 ], R0 j% e- l

  16. . ?5 B) ]8 R- _4 {* ~
  17.     /* Configure the system clock */
    + P4 c& T% S6 T  F. c# J0 P
  18.     SystemClock_Config();2 z8 s( ]& f8 l

  19. : E7 Q8 C; A$ i5 Y. b
  20.     /* USER CODE BEGIN SysInit */
    1 m# |5 f6 w) N" x1 j/ f

  21.   d$ H% v0 c  e) |( E: ?
  22.     /* USER CODE END SysInit */
    9 }  b8 l, b. H+ H' j! ]2 U

  23. 1 ?, Z6 J+ `2 `+ q& C+ J+ Q
  24.     /* Initialize all configured peripherals *// r6 I# d2 Q) g0 o9 x7 I( R
  25.     MX_GPIO_Init();7 Z9 B, W0 p- T" o. w9 a
  26.     MX_DMA_Init();
    $ f5 j6 n# C- m; n4 \/ s- X
  27.     MX_USART1_UART_Init();
    - S9 k% Y+ @9 z" \1 M4 c. f
  28.     MX_USART2_UART_Init();
    5 @0 h( p% Q5 H# N8 F, @9 n
  29.     /* USER CODE BEGIN 2 */
    + s, W$ R6 p/ P8 |
  30.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮
    6 z+ g8 }# q2 Q. [0 i" ^0 R' ]
  31.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮
    $ l/ F! x% t6 Q( e
  32.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮, X0 i! u6 C+ D% K
  33.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮
    0 c+ m" J' P$ @
  34.     HAL_UART_Transmit_DMA(&huart1, (uint8_t*)transmit_str, sizeof(transmit_str));
    5 C6 P# S" c* ?
  35.     DMA_Usart2_Send((uint8_t*)rs485_str, sizeof(rs485_str));                        //初始化log提示
    " ~2 X' X, I+ L6 E) H& P
  36.     HAL_Delay(5);
    % H7 K2 j9 l; M- _. g
  37.     HAL_UART_Receive_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, UART_RX_LEN);         // 启动DMA接收+ I. f; i: v' S8 p; D
  38.     HAL_UART_Receive_DMA(&huart2, uart2_rx_struct_t.uart_rx_buf, UART_RX_LEN);        // 启动DMA接收
    2 {3 W4 z8 u; `. E& K2 l) o: E
  39. ' N% G9 x, C1 B9 k
  40.     __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);                                      // 使能空闲中断
    5 m' j/ r" }2 q* K
  41.     __HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);                                      // 使能空闲中断. M. f) E& N. n+ S/ Q

  42. $ u# ^# o8 m0 M- K/ U2 z% A( P7 M
  43.     /* USER CODE END 2 */5 n6 |% u: d/ V2 O0 k! w4 e

  44. ) R! K+ ^) j8 i" y7 A( n/ G1 L
  45.     /* Infinite loop */
    2 @# U( c; x  ~5 H* N/ [' f# H1 O
  46.     /* USER CODE BEGIN WHILE */
    $ w( o# K  S: f* X
  47.     while (1)
    9 m# P  @/ Z5 |  E4 U
  48.     {0 S8 {  L! g0 r4 ~; j2 y& f  N
  49.         /* USER CODE END WHILE */
    0 ]6 F3 m7 H4 R2 z& g

  50. * c+ G4 O) S  U
  51.         /* USER CODE BEGIN 3 */
    ! d" R5 r1 [6 J
  52.         HAL_Delay(100);: X7 U+ S" Y  v+ k- i* \4 x
  53.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);                                                                        //反转LED点亮熄灭切换$ ^: G( b1 G; }
  54.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_1);                                                                        //反转LED点亮熄灭切换
    # l4 n; j) u0 Y9 Q* s5 t
  55.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_2);                                                                        //反转LED点亮熄灭切换$ ^; I/ e" a( X2 m4 k1 L! O: ?
  56.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_3);                                                                        //反转LED点亮熄灭切换: u* M2 u: V9 r, d7 n) h
  57.         if(uart_rx_struct_t.uart_rx_flag & 0X80)                                //DMA接收完成9 g# \- w" e% z  s9 _; H0 X
  58.         {
    0 X2 x( ?, _1 i
  59.             HAL_UART_Transmit_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, uart_rx_struct_t.uart_len);    // 将接收到的数据发送回去, c" q7 P+ H4 b3 O1 h' k* }
  60.             uart_rx_struct_t.uart_rx_flag = 0;1 J  u. y; A1 Z
  61.         }
    1 x9 n& h% N6 Z2 y1 T& |
  62.         if(uart2_rx_struct_t.uart_rx_flag & 0X80)                                //RS485 串口DMA接收完成
    0 o- a- C) x" _1 Y2 r* t# V  ^' N
  63.         {
    8 u2 |5 k) C9 X. l
  64.             DMA_Usart2_Send((uint8_t*)uart2_rx_struct_t.uart_rx_buf, uart2_rx_struct_t.uart_len);                        //rs485发送
    ; g3 K; l$ H; T7 F' x
  65.             uart2_rx_struct_t.uart_rx_flag = 0;  Z. C& }) Q) p& |- Z; K8 l
  66.         }6 _) W8 D2 r3 I0 |6 Z3 w2 L0 l
  67. % M0 v+ X9 }% z' e; p

  68. " x' s' P6 P6 \) d8 T
  69.     }6 u0 H! c- G: I5 \( l9 G& k( \
  70.     /* USER CODE END 3 */# s4 R* ^9 Y8 |6 u1 S" i1 K
  71. }
复制代码

6 G% @1 ^( e2 b(3)main.h相关变量声明- P! ]1 `4 B! ^# y2 Z9 X# w5 D" y

& r2 h/ O$ m/ G* H7 l: g
c30d0d2d5b464dfa93affa21394898a3.png
# M6 N6 u0 b1 Y+ q0 Z& U$ M3 ?" Z- H+ y: k3 Z
  1. /* USER CODE BEGIN ET */0 u) K- U  w5 h# J
  2. #define UART_RX_LEN 1024                // 一次最大接收的数据量
    1 h$ b# B$ Z+ C: H
  3. typedef struct% D2 i& g! ~( f& K* {2 g- x' ]9 X
  4. {! Q8 g2 F5 B$ U* C  T
  5.     uint8_t uart_rx_buf[UART_RX_LEN];  // DMA数据接收缓存数组8 d2 ^; H: B7 _6 k" S# w& J1 I
  6.     uint16_t uart_len;                 //DMA数据接收长度
    / ^0 B/ V" }8 y! |7 i
  7.     uint8_t uart_rx_flag;              //接收完成标志位. e5 u4 z4 u, U
  8. }uart_rx_struct;% P5 l) W% Q% v8 m
  9. extern uart_rx_struct uart_rx_struct_t;  
    % h* ~  r0 n) G
  10. extern uart_rx_struct uart2_rx_struct_t;; q  r) w5 {6 l# Z3 z' {
  11. /* USER CODE END ET */
复制代码
6 R+ }$ t" Z' o
4、添加HAL库UART  DMA 接收函数代码! H/ p2 ~3 s) u2 s
(1)DMA接收设置前铺垫知识点:
$ p2 q) |$ R5 G+ {* U
* l# q+ {1 x/ k8 ~: ~5 g        STM32的IDLE的中断产生条件:在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断停止。
$ ?; s2 S, U2 A' ]- B* D8 Q
) m% q- G/ k- B3 J( l  m' K(2)stm32f1xx_it.c中添加添加DMA接收处理代码:2 t7 }% f& Y, y
  1. void USART2_IRQHandler(void)2 P: h5 v1 t0 Q
  2. {
    4 X+ u$ E# S$ c9 p; \  m" ]
  3.     /* USER CODE BEGIN USART2_IRQn 0 */
    - i& h' S% b; L5 f$ m* R2 N- w
  4.     if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) != RESET)       // 空闲中断标记被置使
    + N) e/ B# |2 I" b
  5.     {
    4 s4 S* m  V& k; D% r+ D/ o
  6.         __HAL_UART_CLEAR_IDLEFLAG(&huart2);                         // 清除中断标记  P" X8 m; T, d! a' v( S
  7.         HAL_UART_DMAStop(&huart2);                                  // 停止DMA接收
    " M/ o% R8 _8 L) J! E  G" `
  8.         uart2_rx_struct_t.uart_len = UART_RX_LEN - __HAL_DMA_GET_COUNTER(huart2.hdmarx);  // 总数据量减去未接收到的数据量为已经接收到的数据量) n7 z3 P8 B1 J- i' k2 q
  9.         uart2_rx_struct_t.uart_rx_buf[uart2_rx_struct_t.uart_len] = 0;                    // 添加结束笿
    5 e# @6 B8 Z* f% I9 q
  10.         uart2_rx_struct_t.uart_rx_flag |= 0x80;                                       // 标记接收结束( j* Z+ n; y, G. K& A4 u; @: ^
  11.         HAL_UART_Receive_DMA(&huart2, uart2_rx_struct_t.uart_rx_buf, UART_RX_LEN);        // 启动DMA接收/ w* d) s5 C$ g. f% h
  12. + }* L7 [9 z/ p  [! \) W
  13.     }
    5 [* v( `7 a. v  {' O$ }* p
  14.     /* USER CODE END USART2_IRQn 0 */# x8 I7 g0 }9 R  Z& q
  15.     HAL_UART_IRQHandler(&huart2);! D% D  K% R' ~" V4 o% B
  16.     /* USER CODE BEGIN USART2_IRQn 1 */
    6 y, g; d% b6 r8 W; t

  17. ' m: g/ c: Y3 Y- l9 ~7 N- z
  18.     /* USER CODE END USART2_IRQn 1 */" C6 f# H/ t. O3 R: n+ E
  19. }
复制代码
4 D+ f# j; L' r' s# B3 N- B
(3)至此,RS485串口DMA收发数据需要添加的代码已经完成。
6 k4 f  a- N+ D
& t7 m6 ]+ Y7 ]1 ^, e
' |! q+ W* L; U6 j4 `  P
5、设置编程仿真下载模式
/ I; M2 F& e$ O+ ?& x: G0 E$ u(1)选择Options for target ...>>Debug>>J-Link/J-JTRACE Cortex,点击Settings>>选择Port(SW),可以看到搜索成功SW Device,表示芯片可用,可以下载。
7 u6 O  p/ f* G! Y7 u. a
$ [8 m7 U" U! F! ^$ Y8 O8 v" c
edefb6b9a2a14be3b1221ad6d5c7a8a2.png
$ r& ?, O& }* ]2 R5 Q​​
. J$ F8 S# B( D7 p( p- B8 f7 ?(2)点击编译,完成后提示“0 error(s),0 warning(s)”。4 R: r+ b1 Q- g& \  Y* B
8 o5 y3 `3 V6 V& ^2 M, h. Z& \
e0b7e3e353b345a7987fe5f821de2dda.png ( N9 D" u8 C/ }5 u" D
​​
$ |4 h/ R/ l# O* D7 I(3)点击Download(或者快捷键F8),即可下载程序。
$ H! }) K  v7 F7 \" i) q6 O+ }  h; I
eb3f250f19e44862a7df80c2492fcd01.png
3 W! V4 K# s  q' y​% ~- b' i5 [4 z# n& I
(4) 如果下载程序后,没有看到LED1、LED2、LED3、LED4闪烁,可以按下述方式设置一下(Reset and run表示下载后自动复位和重启运行)。或者重新彻底断电再次上电(或按开发板的Reset按键复位MCU即可)。
) o$ r3 P4 \( p$ ~6 u: P) ?/ L& w, d! M  v: N' W
9f8aa1a4e8f04041bcf5cb183facd100.png
  S( k% W" N0 ^ ​
) c1 w2 a/ @0 N8 Y6 i6、串口DMA收发实验效果展示

  b3 L! c  @- X) i) _        程序烧录到开发板后,即可看到LED1、LED2、LED3、LED4初始化后每隔100ms闪烁一次,并且打开串口助手后(串口参数:波特率115200、N、8、1),通过串口助手可以看到,开发板接收到发送的数据转发出来。
$ l4 T+ Y! D1 a& U7 ]: h+ Y- A
2 q; b( e" {' S3 U
f63ffa52c1ea43439547f62c39130706.png ! x4 n& o+ Q8 J) J, f- ?" m6 L
1 q$ Q6 q5 e* T4 M$ ~
————————————————# ?) a) t0 U+ m7 \, O
版权声明:智能小屋ZYXC
( r5 X5 x5 a. d9 q0 t
# U# z2 B" g9 l4 q; Z
6 E% o0 P: O2 ^3 K, t, j
赞 收藏 评论0 发布时间:2023-1-13 20:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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