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

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

[复制链接]
STMCU小助手 发布时间:2023-1-13 20:00
   一、开发板平台简介:3 s& o, C- ^2 p' V
1、开发板资源简介

7 S. j, t; t* C2 W- N" n(1)开发板主芯片型号:STM32L431RCT6(2)开发板主芯片封装:LQFP-64_10x10x05P
( D% M1 P" y& g  s; j(3)开发板主芯片内核:ARM® Cortex®-M41 b$ I, J. O" F
(4)开发板主芯片主频:80MHz" O. r* g- w/ P' z2 V$ `
(5)开发板主芯片Flash大小:256KB
  c6 ~  {& f# E6 d: p" r(6)开发板主芯片RAM大小:64KB
( r1 \5 I: r6 K4 y4 P  H- |- s& x( d$ @7 `( N
bb91345227434ee7a43a34bf3fe366e6.png 8 E$ x1 I" K$ F& Z! L0 v/ T% ~3 N
: K: z$ b4 l' Q
929c0cce04aa4115a8623703982bf3e1.png $ b7 G# D7 v; R1 ?3 u: X8 f' S
; @! l% n; ~3 v
; E5 `; e6 {! a
2、LED灯资源* h$ g! D4 S* p. x: U
(1) STM32L431RCT6开发板共5个LED灯资源,其中一个红色LED为系统指示灯,指示开发板供电系统是否正常,如供电系统正常,红色LED为上电常亮状态,硬件原理图如下图所示:
+ \  |0 _. H, n2 S$ g9 e2 O8 K
0f177691c5814f16a508bcfa747f87ac.png
, ]7 G, S  ^$ `; {
' B% K/ |" N) I6 l(2)其他四个LED灯为黄绿色可控LED,高电平点亮、低电平熄灭,计划用LED常亮验证看门狗的作用,硬件原理图如下图所示:5 y) a: }9 A( s# X4 ^  C# C$ `
+ X+ y& w9 E- e6 C4 N: o
e923ad767b8448b7ac37c4ed693724bd.png ) G8 m+ l- ?; b; M

+ W+ a1 L: H" Q3 v! h
& Y2 |+ _7 n  t1 }3 n4 n/ M" I​3、串口DMA收发工作原理* G3 C# A. H4 H6 V7 |
        串口全称为串行通讯接口,即数据在通信线上一次传输一位,按先后一定顺序传输。我们通常所说的单片机串口准确来说应该是串行异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART),使用TTL电平,串口需要RXD、TXD、GND三根线进行通信。0 m: _$ T4 J# `3 p
- s& \( D% m/ k! a# D7 U
    (1)最常用的RS485收发换向方法是程序换向,即由MCU的一个I/O端口控制RS485收发器件的收发使能引脚,在平时使RS485收发器件处于接收状态
( {! ~% ]5 E- Q+ B( F3 S. c5 a5 g/ g- C, ?5 |8 W
     (2)我们选用的STM32L431RCT6开发板串口2作为RS485通信的串口,PA1作为RS485串口收发的使能控制引脚。
9 a' m. M- I2 k; P+ e; ~# z0 v" R- z
     (3)RS485端口使用时,需要使用USB转485模块和开发板进行通信,使用方法为USB转485模块的A接开发板的A,USB转485模块的B接开发的B,GND可不接。+ u9 Z  }- ~( q$ v

, h1 R* |; q! z7 f  w$ R2 m. R+ f; s4 oRS485串口,硬件原理图如下所示:
0 q; G- h4 }& r  A; F
, K9 x% |4 g& v$ t" C+ D8 }
1f72998fadef42548ee482c9fe064c08.png . \$ J# n* ?" `- z) l" R  G# O

" S2 u/ N2 h9 \" _: g/ n0 B
182841b93d1e40b0913e3a54b22d0704.png ( g0 F- x$ z- a* f. O# N
6 n% g# L, n! N5 k+ F: u
DMA(Direct Memory Access) :直接存储器存取,是单片机的一个外设,它的主要功能是用来搬数据,但是不需要占用 CPU,即在传输数据的时候, CPU 可以干其他的事情,好像是多线程一样。数据传输支持从外设到存储器或者存储器到存储器,这里的存储器可以是 SRAM 或者是 FLASH。
4 }8 Y/ s8 g) I. f
: A/ u! e7 ^, ^) `0 uDMA 控制器包含了 DMA1 和 DMA2,其中 DMA1 有 7 个通道, DMA2 有 5 个通道,这里的通道可以理解为传输数据的一种管道。要注意的是 DMA2 只存在于大容量的单片机中。: B+ V+ r# j6 V2 j; O1 f, W
# ~4 z% z2 S5 P% i7 r
354955ecc6b140049ec57af71fe199f1.png
0 f5 U8 t; f( p) ?3 D. a, m- g+ Z0 m. y  e; A( D6 u/ S9 l7 W& ^
  二、串口DMA收发实验过程
- t0 o. b3 G0 `0 q2 c1、新建STM32CubeMX基础工程

- J/ l+ C6 \9 d2 p+ m4 }. c(1)打开STM32CubeMX,点击“File”-->"New Project"
% J1 P( [" X- _, e6 m6 f9 C: R
$ u6 n. w+ N1 }$ Q) p* r( W
2399170347904e959c855fefd5877f84.png , c. v* {! a- e5 h6 a# K1 X
0 ^; t. G4 F/ s! m- h8 x7 ^
(2)等待打开主芯片选项界面(大约1分钟时间)。
% D0 Z+ J6 G/ j" w
9 B' S2 @8 _' w% `! E' M
d74d2fdc60c9440483e2b7cf8d928e7f.png 1 J0 b* [1 S+ u3 m. ]9 B5 f7 P. o
" P$ E/ Q8 Z: y: F& c3 j
(3)昨天搜索框中输入(或选择)所需的主芯片型号(因为我们用的是STM32L431RCT6开发板,所以此处选择STM32L431RC),然后在右下角选择STM32L431RCTx(因为开发板主芯片是STM32L431RCT6),左键双击即可打开新建的项目。) L( \( j7 V. A
9 R% c" m0 |( h/ m. {

- O, _' n, C/ Q9 h& X% }) s( p 7b80345238d74bea82ce70e1a348f7b4.png
: s, N( L9 ?8 [! v) @8 M7 y$ a

- x4 f! V8 `$ S(4)选择时钟源。
5 [2 f6 b4 q3 _6 ~8 B2 f        因为开发板上有8M外部时钟,硬件原理图如下所示,所以此处选择使用外部高速时钟(HSE)。/ l% Y+ F$ \- d  s6 [
/ `7 x9 e5 q8 w' I4 o" c
3f65707eca104663a3dede6d25dfa961.png " R# J+ y0 m+ T$ ^* p) P8 j6 n2 y3 ?

7 U, \$ S$ G! n1 u0 e7 m; u0 H( q        因为我们没有用到外部低速时钟(LSE),此处不做处理,如下图所示。
* _9 F' T8 K4 A# f5 i/ |
. r" v+ w: M8 I, m5 J) D
72119b971f62410fa8344f7f9fb9f389.png
7 n: C7 ^0 Z. [, w; h3 J

! H8 y1 v  T5 }, q  P  w2、配置GPIO控制LED6 ]3 |8 U  C0 S% R5 @1 e# P( \" f  [
(1)查开发板原理图得,LED1、LED2、LED3、LED4的控制引脚分别为:, T  d1 E5 q5 g- h  C' J
LED1——PC02 Y" z/ r# o! d) l
LED2——PC16 f0 q  f& F: C$ _2 B
LED3——PC2
8 b/ L8 I% N$ ]( @$ V: eLED4——PC3
& L, i* x# W/ o. V* p) q
3 u; i0 h6 @% s8 t(2)配置LED的控制引脚为输出,输出频率、输出方式默认即可。" G0 A( p' H1 Q# @, F
鼠标左键点击PC0,选择“GPIO_Output”,表示设置该引脚为输出模式。
- z2 @) S# f+ W5 I% u0 g鼠标左键点击PC1,选择“GPIO_Output”,表示设置该引脚为输出模式。1 q0 o9 j, f' ]8 z
鼠标左键点击PC2,选择“GPIO_Output”,表示设置该引脚为输出模式。
; ?/ Y; W3 Z+ u! I; l- x$ R鼠标左键点击PC3,选择“GPIO_Output”,表示设置该引脚为输出模式。/ w* x2 ~% }; [5 P
( O7 ?; D5 c8 @3 n
492907c1e71149819adbaee4516a2af4.png
  f4 L4 @+ g# H: Q7 ^7 y  o: J# v4 ]% m: H6 r/ A
c75d3f10ba2e427d9c1a10fad9bf5471.png
+ L6 v1 L/ a7 ?7 e; K" y
3 S& E; }$ j5 h
(3)也根据自己的需求配置GPIO的参数,如输出方式、输出频率、上拉下拉等。因为GPIO控制LED的要求比较低,此处采用默认参数即可,不用修改。  [7 x0 ]! F  d% @
( f+ B& e5 [! S' y# I2 X
38ff4b80e1c5495ba3076a5158fd91fa.png
: r6 a6 ?% C8 c* x4 ^8 s4 t" N& E* a& q7 O
​​3、配置PA2、PA3为串口
6 e8 K( s1 ^1 A2 r7 s+ B! F6 J7 V(1)查原理图得知,串口2使用STM32L431RCT6引脚为PA2-USART2_TX,PA3-USART2_RX,引脚设置如下:
* ^6 E" V2 o3 M8 U' }
; {) _4 D: x1 K
9bd645a9032647d280107cc82b5a0f67.png 4 H! F* V/ R! p" W8 X

8 Y% B8 M& O% e/ j$ Z, \. k串口参数默认即可:波特率115200-N-8-1,并使能收发控制引脚。+ g# w" ~1 ~+ s8 z8 T

7 R9 a; y' u; S' a. Z
74f5d7878df343ae83c9af5ed79c6a7c.png
. x  T4 z- [- O' Z$ |

3 o" e8 Z9 G7 c2 ^, X# Z7 a( N(2)设置NVIC settings 使能接收中断。
. C* e" f( w. g+ v+ T/ d# S
4 }; M; m1 }" b/ s. w2 {! |( P
fde3c5c1ac9d4896b40dc5f5e15c3e61.png 6 T: J' p/ R1 K8 D# w
6 S1 Y: F/ P& K4 h+ e
3、串口DMA设置
, Y1 w& H+ v6 U% d& y% g) L$ v4 j% E( f$ O) E# i
6d26b13dd9d34039a2b426ca47680f8c.png ( k- i: R9 I" l0 @
1 E, J* f1 ]: O+ D; r
(1)根据DMA1通道预览可以得出,我们用的串口2的TX、RX分别为通道6、通道7:5 F1 _8 k9 @" _8 }/ ?
点击DMASettings 点击 Add 添加通道
: K8 i& X0 b+ Z8 I* `选择USART_RX USART_TX 传输速率设置为中速
6 A2 F, f* ?) ^8 g% EDMA传输模式为正常模式,即发送一次就结束。" z* ^; O$ g& J% ]8 N) h4 b2 L: f
DMA内存地址自增,每次增加一个Byte(字节)
" q, o# Z3 x+ j9 F5 _. |9 {$ v
# ]6 v9 p! w# H( r; W& K
55bd687bfb1c4640847f6cba6ea373b9.png ( }6 U3 h: M- g8 i: j5 h  ~

6 {0 t- W! f; U  z& M* C (2)DMA相关参数解析, n) {: w$ o2 F
Dirction : DMA传输方向有四类9 O. @1 s& E4 ?) w4 @4 S
外设到内存 Peripheral To Memory6 r/ u) @& W( W4 ^# o
内存到外设 Memory To Peripheral# q$ t& T( g2 s! S
内存到内存 Memory To Memory9 u7 S5 U. q0 o8 K5 C. u% M2 `
外设到外设 Peripheral To Peripheral
& G, T3 N. X' M) T* l
, d: i* F$ l, ?! d/ H* s
Priority: DMA通信传输速度有四类
6 |( @: C! p3 g( H# h0 q3 ]  P最高优先级 Very Hight
2 y* }+ P+ J# l" h/ k: e" {高优先级 Hight
! P5 D/ ?0 w* ]/ `6 `! H3 {: B中等优先级 Medium
9 e9 q: j- ]7 c8 ?% \低优先级;Low
0 O" {$ \* c* `3 b3 I/ ~+ c; K+ f; a) C4 O6 V" q
Mode:DMA传输模式有两类# h9 {0 G$ a) Z% X" z1 @5 ^

1 p+ E. Y$ y& b7 y6 c
9021c11fed3e4c1885477e062b846258.png
% p3 O9 }; ~0 I+ H5 Q6 M% b6 V; R- D7 D* l4 g$ k: B
Normal正常模式:当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次。# Y$ U- d- l8 Z" Y
Circle循环模式:传输完成后又重新开始继续传输,不断循环永不停止。
0 A* {& t& T3 y1 x# p/ Y( b. |9 g3 ?! o; ^* H& C
Increment Address-DMA指针递增设置:9 l; X! k6 Z- `6 }& B3 Q% @, K, Y

) [) Z1 N# @. K2 f9 @
2b1a952d6514444e9dbb019a9ae88c42.png
0 ?) h0 H: l. v" r! L. U7 R+ {/ v2 K$ |) X) @

, j; V+ n9 e3 t" B( g3 }4、配置项目工程参数0 i/ u( s# ?7 `. X4 ?3 J; r
(1)配置时钟树,用于系统内部时钟,以及各个外设时钟等。此处选择外部8M晶振作为主时钟频率,内部最大倍频80MHz。; a. M8 p9 @& s5 {& `" c, K+ R( c

/ P" K, F2 B5 x6 `! T
f3ecedd9323f4463b69539906b3c1199.png   N! H; `8 I# e/ v6 f4 \; W

$ ?5 H2 g0 D4 {: o$ A( `/ E7 _(2)完成配置工程。
$ ~* P0 ^& x! ^* b& L8 s备注:需要注意代码生成过程中的继承关系,如图所示:需要保留开发者自己编写的代码时,请根据配置设置,不然生成代码后会删除自己编写的代码(从这个方面也可以看出开发者备份自己的代码是多么的重要。)
/ P* K! W# {' Z$ f# h
7 P6 E- H1 v2 `0 ]3 O, c
efdb616174f54925b6eac31109f227b5.png
! }/ r0 E/ c% E9 F/ V: @) H6 p​​5 ]& c7 [6 \$ i5 i+ y2 S
41c3f2716e4e4eda8f62fa3a1d871322.png - c: S' Y1 v. h3 [

1 w* }1 C0 C; ]+ k7 w(3)生成代码。
2 E+ d0 [/ A; P; B9 D备注:使用Generate CODE生成工程代码前,请确保文件路径无中文,否则会生成项目失败。
5 i4 k' M  R/ S+ ?! v' u0 C+ M9 e9 c5 F4 V/ f
8eaa7d0babea40ee93f158481a6ee471.png
+ H5 p' v2 x# @$ {​​
: g0 g: ], e( u- B(4)工程代码生成成功。
7 u' S) X3 @! d) k
6 P; {# ^# R* g0 G- x- A
e8f46d59a1fb4af589feb613fdff17b4.png
1 f* s, U0 K& N# W9 c
% x) {7 A8 h$ v' l0 `: c& L( M" i- \% n2 _3 g. o9 b3 U% b
三、在KEIL 5中编写代码  \6 }0 K7 m+ l) X! O' ]$ O# q+ Q# l9 F1 B
1、使用KEIL 5(MDK)打开项目工程文件
0 S/ U8 U$ S8 d
源码使用说明:使用前必须把项目工程复制到无中文路径的文件夹下使用。
$ K9 h8 c4 y. {+ U8 _3 ~) o1 }8 x1 `1 j6 m
(1)找到刚才新建工程的存储路径,安装项目名称,打开项目工程.uvprojx。
0 Y: [* s  B* c" z; W
) T1 c6 X" t* ?2 M9 b* q
ec2f10465e0a49e9845c70b067c393ff.png + Q/ k; \2 l) ^& l

- x7 e, y5 l' U/ s+ h. w( ]& I2、添加LED指示灯作为系统提示2 q, C$ ~( ?. U) q
添加每隔100ms,LED1、LED2、LED3、LED4闪烁一次的系统提示,用于提示程序运行正常。
9 |9 B& c: P5 E" [0 q; [! H) c; p6 i1 Y  v/ Q" k1 v2 N
2af9ef3cfaab45988c810d94d801fc34.png
% T( r8 W1 y" Q+ `$ F! F
5 l/ G/ s3 R/ O- v( o3、添加HAL库UART  DMA 发送函数代码8 ]+ C& G! H+ ^2 ^2 @
(1)STM32 HAL函数库的串口DMA相关函数如下:
" W$ d* P0 e/ U9 w
  1. HAL_UART_Transmit();串口发送数据,使用超时管理机制
    ! `* E& h; z. ]% y6 m; a
  2. HAL_UART_Receive();串口接收数据,使用超时管理机制
    , g2 r- s# B( ]4 Y, B4 e. z2 K
  3. HAL_UART_Transmit_IT();串口中断模式发送& s! ^- t5 J6 |8 \1 l$ O
  4. HAL_UART_Receive_IT();串口中断模式接收
    6 w( k, m! x: @  Z* B$ O/ T
  5. HAL_UART_Transmit_DMA();串口DMA模式发送9 ]" _* }2 b! O+ `/ W2 d
  6. HAL_UART_Transmit_DMA();串口DMA模式接收/ O& |( l) O. y: \1 k; R
  7. HAL_UART_DMAPause() 暂停串口DMA7 G  Y( B7 F* U5 W' c/ T5 z
  8. HAL_UART_DMAResume(); 恢复串口DMA
    4 g. D6 P. z+ O) Y; ?% e
  9. HAL_UART_DMAStop(); 结束串口DMA
复制代码

& b. }. J) v) B(2)main.c添加RS485发送函数相关代码:1 j0 ^8 H# M/ }. b+ C& L7 a/ V

8 ?6 s3 C4 q5 u' p5 C
33126cad704048e48421455e369f78bf.png % ^1 N& c& {  P- N) N& M
% r. _+ E1 J& R/ N% ?. C
  1. /* USER CODE BEGIN 0 */4 ?, Q2 @" W# Z3 M2 r
  2. uart_rx_struct uart_rx_struct_t= {0};                               //串口接收数组7 p4 U- |+ N8 L5 d# x  `
  3. uart_rx_struct uart2_rx_struct_t= {0};                              //RS485串口接收数组! t5 I: @$ w7 E
  4. /*******************************************
    5 E0 O' n$ F9 M# u: a$ v
  5. *函数名:DMA_Usart_Send4 X5 `# ]) Q  i% b" n
  6. *功能说明: 串口发送功能函数
    9 i; z2 D6 B1 G# o$ ^6 i
  7. *形  参: buf,len
    8 Q: S0 U2 |. u) D9 {0 B% V2 o+ E5 @
  8. *返 回 值: 无
    1 s' P/ d" l9 n/ j
  9. ********************************************/
    + q& U! W% `0 N* ?1 i- `+ b
  10. " t$ Y7 `" s- t
  11. void DMA_Usart2_Send(uint8_t *buf,uint8_t len)/ B" {+ F$ ^8 t+ n" ^# @0 r% q
  12. {
    8 i5 r& r* s4 y( i
  13.     HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);                 //设置485为发送状态
    2 B; N( y# D* P
  14.     if(HAL_UART_Transmit_DMA(&huart2, buf,len)!= HAL_OK)     //判断是否发送正常,如果出现异常则进入异常中断函敿
    1 X; q8 w9 |7 A9 E
  15.     {
    - o. h+ o1 B) @: ?
  16.         Error_Handler();                                                                        //异常提醒. L1 f1 u) e: t+ P
  17.     }* |- ]  ?1 t1 U4 ^! h4 z+ @
  18.     HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);    //设置485为接收状态
    ) |) R5 |  l4 X  d$ E
  19. }
    # d( N0 q( m) y: S2 R! r

  20.   V  y8 {; y4 ~8 x* K
  21. /* USER CODE END 0 */
复制代码

- E2 E- f  f( a4 m- x, e  R(3)main.c文件中添加main函数的处理,上电初始化打印一次log,然后等待接收,等串口收到数据后从原串口发出。/ ?/ }8 i* o$ f+ H/ ?% ^5 }

+ \1 R# c6 ^. F) u& Q
cb23e78dcc0c4cedbdd965cd95a06c07.png
$ `& f2 w. p0 }7 a- a0 ^8 w( @! D( B; d1 [+ ^- K: z
af25c79e68fd48b8b0fb1e456645ff74.png 8 u  p8 F9 M/ W

) W! x6 S$ g$ d3 s
0952de54d7b341ee97e81e22114d369e.png ' v( C( l/ v8 `4 }( f: A

+ s& A% ~4 U3 b3 L$ _$ \7 Z5 N7 }6 h. K# k
  1. int main(void)
    " D  W0 e* [! [0 A8 U- c) Y
  2. {
    2 y: C9 j) T7 K
  3.     /* USER CODE BEGIN 1 */
    5 ?5 j* |* j! \# t& b+ j. j3 \
  4.     uint8_t transmit_str[50]= {"hello world,this is uart dma function!\r\n"};5 \  m* t5 `% g" B: ]5 w6 v+ E
  5.     uint8_t rs485_str[50]= {"hello world,this is uart2 dma function!\r\n"};
    + E9 k8 O0 E! E  ]7 m" L7 a8 |7 u
  6.     /* USER CODE END 1 *// }0 b0 N/ I4 n% m" J% E/ k
  7. 8 L& y/ i6 a, b; }+ x
  8.     /* MCU Configuration--------------------------------------------------------*/
    ! R3 \( ]0 V% I
  9. 3 U6 F) n1 ?; `. Z, f/ V
  10.     /* Reset of all peripherals, Initializes the Flash interface and the Systick. */( N! e) S' R' n2 ^
  11.     HAL_Init();
    9 j' N1 E7 d& x5 T. Y
  12. 1 H( Q+ O5 F7 f$ N1 w/ a
  13.     /* USER CODE BEGIN Init */! w: D$ j6 r& {* U) I: n# W
  14. 9 |& @- ]1 P& @5 |
  15.     /* USER CODE END Init */
    - ?: F9 v( i" [, s/ q$ o1 c

  16. ! t0 t! y! a! d8 _0 y' x
  17.     /* Configure the system clock *// V: S* c5 z3 p; s
  18.     SystemClock_Config();
    # N- ?# _8 ^: E% P/ {: x, A2 V

  19. ( y5 [1 }$ B& C' p* M! f% R; D
  20.     /* USER CODE BEGIN SysInit */
    3 ^3 l1 i% H! W$ ~

  21. 3 I. X0 M% c7 u. l! f
  22.     /* USER CODE END SysInit */. Q; E- o" E/ b6 l9 \0 e

  23. " F: \, ~1 ^% B& U0 f
  24.     /* Initialize all configured peripherals */
    % a  @% j' P' X2 _5 [
  25.     MX_GPIO_Init();
    " l5 |5 v6 G3 t9 I* w
  26.     MX_DMA_Init();
    3 f$ L" [, R' s+ m
  27.     MX_USART1_UART_Init();  [: o3 M7 k! P$ n" f8 I! |  h
  28.     MX_USART2_UART_Init();
    6 t* L) q# p) w& M5 H
  29.     /* USER CODE BEGIN 2 *// u$ }' O+ t. g& G9 J' v
  30.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮0 b  @; F# W, K( C0 O7 T
  31.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮2 p/ ]2 Z% X8 [$ q
  32.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮
    - a! t: N4 D7 R, w1 @7 T
  33.     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_SET);                                                                //初始化LED灯,默认点亮1 {& I5 u2 h8 e+ m+ q) S6 b
  34.     HAL_UART_Transmit_DMA(&huart1, (uint8_t*)transmit_str, sizeof(transmit_str));
    3 S& y+ I4 e- {6 L# E3 p- b
  35.     DMA_Usart2_Send((uint8_t*)rs485_str, sizeof(rs485_str));                        //初始化log提示/ b2 l8 @" ~' h, M% m; u" Y* e
  36.     HAL_Delay(5);
    . e& J4 C0 r4 ^7 ?5 {- M2 ?% B$ ]
  37.     HAL_UART_Receive_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, UART_RX_LEN);         // 启动DMA接收
    9 O$ V1 y5 \8 Q$ H
  38.     HAL_UART_Receive_DMA(&huart2, uart2_rx_struct_t.uart_rx_buf, UART_RX_LEN);        // 启动DMA接收
    9 [8 H* E# `% Z

  39. & L: ?' N) r, h& k1 D
  40.     __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);                                      // 使能空闲中断
    ! s  b0 B7 D% f0 J, s
  41.     __HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);                                      // 使能空闲中断% a  R( z) T. h; o
  42. 7 A. G! g6 F( X6 g4 \
  43.     /* USER CODE END 2 */& C/ B9 u' |& u1 ^! s0 ]8 P) N

  44. 4 a) v) z) |! P1 c' B
  45.     /* Infinite loop */
    ! s* A  g2 p; S! J7 t5 F$ X; C
  46.     /* USER CODE BEGIN WHILE */
    ' T; C$ [# a* X. o8 w+ k
  47.     while (1)2 D1 i2 d9 C, U9 l) T0 b9 x% D
  48.     {
    6 @3 Z5 H% b# D) m7 e& x
  49.         /* USER CODE END WHILE */( M' m5 l. ^- d4 ]) |3 E7 G: H' z

  50. # i6 K  w- t6 I. R2 K+ T
  51.         /* USER CODE BEGIN 3 */
    % `% _9 J! M2 }& W: W4 C& J& q
  52.         HAL_Delay(100);/ \+ g/ V' e, p
  53.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);                                                                        //反转LED点亮熄灭切换
    % @6 y. }4 a' p, Y! g. m. D' Y. O4 V
  54.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_1);                                                                        //反转LED点亮熄灭切换
    ( c# W) L8 |3 O
  55.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_2);                                                                        //反转LED点亮熄灭切换' d! H- R. a) d7 x5 `! g# Q
  56.         HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_3);                                                                        //反转LED点亮熄灭切换5 `$ W6 p4 F6 @- \) H  L7 H
  57.         if(uart_rx_struct_t.uart_rx_flag & 0X80)                                //DMA接收完成: S+ S' s5 t$ Z' h
  58.         {" M2 R( f% d0 ^2 w$ C  c
  59.             HAL_UART_Transmit_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, uart_rx_struct_t.uart_len);    // 将接收到的数据发送回去
    ) D7 y2 ^! i$ }9 Z2 v7 @& Q9 _+ J
  60.             uart_rx_struct_t.uart_rx_flag = 0;/ ?7 o7 f: x. s4 X% Y  p5 w* M
  61.         }
    # K4 x( n1 W& N7 M5 T$ Z
  62.         if(uart2_rx_struct_t.uart_rx_flag & 0X80)                                //RS485 串口DMA接收完成. ~3 z5 P' N5 L* ?
  63.         {7 S! X5 U! z$ v' U' |5 W3 N
  64.             DMA_Usart2_Send((uint8_t*)uart2_rx_struct_t.uart_rx_buf, uart2_rx_struct_t.uart_len);                        //rs485发送% z  I! @7 D3 W9 P& s% @  P
  65.             uart2_rx_struct_t.uart_rx_flag = 0;
    ' @: s, v. a! ?) N3 {' U' a+ N
  66.         }
    5 M/ k. v1 p# |

  67. ! Q+ C6 d# \" j4 I
  68. % e; G- ~& R* ~4 j  j( U
  69.     }
    ( [, C7 M3 u/ t0 \
  70.     /* USER CODE END 3 */
    7 H' g+ z2 K3 U2 B* e1 I) N" a
  71. }
复制代码

$ I& L' _$ K$ n(3)main.h相关变量声明) n/ B, x# ?  k& L  w% _
1 ]! b2 O+ }2 _5 v2 B
c30d0d2d5b464dfa93affa21394898a3.png
( u; t  A7 e2 S- ~9 e. U1 [. Y: ~' X) S. Z! M0 W+ F; C7 t% `, {
  1. /* USER CODE BEGIN ET */- N% N4 F$ A1 [/ D5 t
  2. #define UART_RX_LEN 1024                // 一次最大接收的数据量8 x% V0 Z7 R1 H) ~, g; V; j
  3. typedef struct
    8 O  ?- A$ D; ]  F
  4. {
    9 m( B. p0 Y$ D" s7 r
  5.     uint8_t uart_rx_buf[UART_RX_LEN];  // DMA数据接收缓存数组) e: x! K& H* h$ g3 ]
  6.     uint16_t uart_len;                 //DMA数据接收长度
    9 X( w9 L- B! s0 P
  7.     uint8_t uart_rx_flag;              //接收完成标志位+ _1 v. {$ R" E* f) A( D# ^
  8. }uart_rx_struct;& b1 k* }# I1 L. |3 k
  9. extern uart_rx_struct uart_rx_struct_t;  5 M' U5 [* v) T: o2 w
  10. extern uart_rx_struct uart2_rx_struct_t;
    % W& l1 M- R9 v" [. @. t
  11. /* USER CODE END ET */
复制代码

  q& V* n% B6 X- a; _# `4、添加HAL库UART  DMA 接收函数代码; n4 K& Z5 }* o
(1)DMA接收设置前铺垫知识点:% e* e9 b1 Y7 x) F) W
% x5 T0 f' c  E8 s9 y) |9 I
        STM32的IDLE的中断产生条件:在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断停止。- w1 v4 k* |  [% F  G" G7 n

8 c& v9 Q) S% ~+ G: R* p! b(2)stm32f1xx_it.c中添加添加DMA接收处理代码:: E$ p7 q5 X! R4 e2 E
  1. void USART2_IRQHandler(void)0 [, u) V9 [7 ?! S( o  `
  2. {7 X* n" f: j7 Z' k6 c
  3.     /* USER CODE BEGIN USART2_IRQn 0 */( V3 W9 ]- y- ~  s. y; y& \
  4.     if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) != RESET)       // 空闲中断标记被置使
    & ^6 I- f9 h( p% ?2 M! ]. d' O9 ~
  5.     {
    ! ]9 ?3 U& |# k7 C
  6.         __HAL_UART_CLEAR_IDLEFLAG(&huart2);                         // 清除中断标记6 E2 i5 [! H5 u4 ^, V& T1 Z7 w; g
  7.         HAL_UART_DMAStop(&huart2);                                  // 停止DMA接收. z8 b# F- R* i1 I% Z9 @
  8.         uart2_rx_struct_t.uart_len = UART_RX_LEN - __HAL_DMA_GET_COUNTER(huart2.hdmarx);  // 总数据量减去未接收到的数据量为已经接收到的数据量
    3 N: v8 ]7 q6 C  Y
  9.         uart2_rx_struct_t.uart_rx_buf[uart2_rx_struct_t.uart_len] = 0;                    // 添加结束笿/ j3 Z+ B. v3 G0 E9 ?
  10.         uart2_rx_struct_t.uart_rx_flag |= 0x80;                                       // 标记接收结束
    ) H; B7 b8 Z$ U' D7 w
  11.         HAL_UART_Receive_DMA(&huart2, uart2_rx_struct_t.uart_rx_buf, UART_RX_LEN);        // 启动DMA接收- J; B1 p! M/ [

  12. ) B# r1 I. C* v) B
  13.     }/ A% _" E# J1 G9 U
  14.     /* USER CODE END USART2_IRQn 0 */
    " D( f, Y& Z" T+ `6 \1 \' g2 L, i+ g
  15.     HAL_UART_IRQHandler(&huart2);
    7 L: w3 V! N8 I
  16.     /* USER CODE BEGIN USART2_IRQn 1 */2 o' P7 @, Q" |7 O& [5 z- n

  17. & D8 V% ?+ A. B% w* h
  18.     /* USER CODE END USART2_IRQn 1 */" K1 A4 `, u# h7 s
  19. }
复制代码

) ~; t9 X& n5 s6 p% q( K; m2 {(3)至此,RS485串口DMA收发数据需要添加的代码已经完成。3 c* V2 x' v- [0 Z( E

+ k/ p  j2 f! ?6 `  N2 h) `

9 z3 v: |& F8 Z+ U3 ]5、设置编程仿真下载模式
2 A/ A! {3 q- O  P) ~1 a2 I(1)选择Options for target ...>>Debug>>J-Link/J-JTRACE Cortex,点击Settings>>选择Port(SW),可以看到搜索成功SW Device,表示芯片可用,可以下载。! H; [1 Q' c# @& W" N! K  u
! q# G0 T; X& K5 \6 d$ c& u
edefb6b9a2a14be3b1221ad6d5c7a8a2.png ' H8 M+ M7 p) S, a) c# ~
​​7 j; N2 j8 L& O  ?  t& o) }
(2)点击编译,完成后提示“0 error(s),0 warning(s)”。* h% g& n- l: o) g; y$ W
" r/ E& L1 G: s( a2 Y
e0b7e3e353b345a7987fe5f821de2dda.png
+ O; l0 z  x) R! Y​​
, h* O, l- B3 N) w( [; ~8 ](3)点击Download(或者快捷键F8),即可下载程序。
, k5 u3 N- Q& d! g- B
1 \( h/ T& x+ L" a! j
eb3f250f19e44862a7df80c2492fcd01.png
8 c) u3 M0 C( _; L8 ~​8 _9 J6 @/ d  f+ f
(4) 如果下载程序后,没有看到LED1、LED2、LED3、LED4闪烁,可以按下述方式设置一下(Reset and run表示下载后自动复位和重启运行)。或者重新彻底断电再次上电(或按开发板的Reset按键复位MCU即可)。# w5 N" \5 s% d% b# f; `0 x! o

8 Q9 ]. \; G/ ?4 A
9f8aa1a4e8f04041bcf5cb183facd100.png
3 h4 f0 k! f3 l& w$ o; U ​! {1 h2 d' C% `& u- G) \/ A6 z- L0 L
6、串口DMA收发实验效果展示

* c9 O7 g, v& l. T& v        程序烧录到开发板后,即可看到LED1、LED2、LED3、LED4初始化后每隔100ms闪烁一次,并且打开串口助手后(串口参数:波特率115200、N、8、1),通过串口助手可以看到,开发板接收到发送的数据转发出来。7 u! Q: e* c! Q0 |2 s

4 E& ]# _% x& a( J5 y2 C" ~1 }
f63ffa52c1ea43439547f62c39130706.png
* w% y7 a4 Z) g- w
4 c8 x( v- {/ d# ^————————————————
6 l  i4 C/ G* K版权声明:智能小屋ZYXC  ~. G8 O6 t. G7 d5 N+ H
+ c; U- m& k6 O8 j

5 O" n/ o1 {  f5 o9 ^
赞 收藏 评论0 发布时间:2023-1-13 20:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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