一、开发板平台简介:
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: ~
7 @$ b/ p, ]: V* A2 P* r- y# s: _/ v, P1 d* [ k4 M( g7 ?
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 ^
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+ \
. 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
& j; U1 O+ K. S% k% i
6 |0 |) j0 L3 u) P4 h+ u, Y1 i* d
) 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
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
! w Q6 d+ l0 g- s
/ ^1 d5 j; i3 ^
(2)等待打开主芯片选项界面(大约1分钟时间)。
3 @; u2 Z- S$ M" k# Y! ~ ?& R5 z4 a& ?% y
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
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
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
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
6 z/ ~% x: x- `2 k2 n& U* l5 I
9 m1 X1 `: [) u0 f- y
+ _! 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
8 [3 T, j/ Z0 Q' }
; J/ K$ p( K+ Z1 }. O3、配置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
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
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
( 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
% 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
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
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 \
8 Y; w( N& Y3 w8 n1 e |7 Y
& \- Z* j# r: S, Z# _/ V2 a2 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
. 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
: a. {3 a( I$ M8 p# F4 d& ~
7 R0 g, _0 L# M' P& c5 h
/ 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
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' `
; 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
, ]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
. 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- HAL_UART_Transmit();串口发送数据,使用超时管理机制% C G$ ^! P" a8 `) ]7 G
- HAL_UART_Receive();串口接收数据,使用超时管理机制
0 j1 B6 w+ z. k: @4 ?; C. l. i! Y - HAL_UART_Transmit_IT();串口中断模式发送3 A5 D! m6 s! _* J
- HAL_UART_Receive_IT();串口中断模式接收
; B* `2 f: N! a0 e& U1 H4 Q; T2 K8 x - HAL_UART_Transmit_DMA();串口DMA模式发送
2 i2 Y% I! H' l$ X& L! [ - HAL_UART_Transmit_DMA();串口DMA模式接收# D$ H( y5 h, u+ q! p
- HAL_UART_DMAPause() 暂停串口DMA
6 X7 T7 V3 Z& q" B! \8 l7 I$ i0 } - HAL_UART_DMAResume(); 恢复串口DMA! p% {2 b8 n- i' q0 X; Q# M
- 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
" d) [& ]/ `) _! q1 \$ R: w1 ]5 Y2 ~/ |6 p7 s/ m4 C9 O% ^# Q ] {
- /* USER CODE BEGIN 0 */
0 Y# \ w. J, N - uart_rx_struct uart_rx_struct_t= {0}; //串口接收数组
4 @& \4 N* M c9 v9 D - uart_rx_struct uart2_rx_struct_t= {0}; //RS485串口接收数组" s B9 [% B/ D3 w0 E; @
- /*******************************************
/ Z- J( f& C; `6 U - *函数名:DMA_Usart_Send
$ V% E# V! C& V, g* j, h) t - *功能说明: 串口发送功能函数
' y) e3 y& u5 k( _0 r' O# `0 P - *形 参: buf,len
]- b7 c- _0 B6 b; P% b3 c; L - *返 回 值: 无
1 Q. P, L2 j: d0 u0 Y - ********************************************/" q6 b4 U0 X" `% u
- : q' E2 Z$ N O# y' _6 v. @
- void DMA_Usart2_Send(uint8_t *buf,uint8_t len)
2 v p# l: n( e) C& C - {
) z9 e8 u1 g& W# K0 o' |3 o: m - HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET); //设置485为发送状态
; K6 E/ ~4 ~# |7 g - if(HAL_UART_Transmit_DMA(&huart2, buf,len)!= HAL_OK) //判断是否发送正常,如果出现异常则进入异常中断函敿, x @8 n4 f$ d) _/ I
- {; I9 _. l1 J: B
- Error_Handler(); //异常提醒
) |# j! F. P5 @7 ~" {( \& b - }/ O$ S, g# K4 Q$ T2 g$ _7 L2 j1 r
- HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET); //设置485为接收状态. C$ Y) {! ?, c# W
- }
* I5 ?& M! \8 W! [9 E7 K# J4 T - 2 c& R$ W/ ?" H! P6 v7 _
- /* 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
- K# t) e# p6 U8 [
4 s7 D$ E: ~* O: ?
7 |+ W- g& p9 l& q8 m, w
5 u4 i; W/ G$ ^; ^1 U R% o+ s
, 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
- int main(void)# X3 C$ q6 Z5 q9 g: L
- {* j: K- M Q" s2 s# Y* y
- /* USER CODE BEGIN 1 */
% L/ [2 r, x, F+ `0 L - uint8_t transmit_str[50]= {"hello world,this is uart dma function!\r\n"};
: N0 w% P9 i/ r! N$ |8 { - uint8_t rs485_str[50]= {"hello world,this is uart2 dma function!\r\n"};
$ @5 _% Z+ r5 c W* {4 f - /* USER CODE END 1 */. D) e4 Q F; o9 ~& Z' H+ s# P9 J2 t
- ) b: G9 o5 K1 ~, I1 E
- /* MCU Configuration--------------------------------------------------------*/" t( Z( ?, Q; z
- & d6 w+ M2 w/ o9 L; K2 e
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
3 Z& W9 w: u6 s! B- ~2 r - HAL_Init();
9 ~& {4 h: v' F; L. p7 c1 i& E/ Z- _ - 7 I) ]) |" E; D& R" ]! V
- /* USER CODE BEGIN Init */
9 ^; X) t. O1 M! \8 ~, K5 c9 P -
" x( G0 Q/ Z1 S' E9 @& P7 a5 Q - /* USER CODE END Init */
* p" F" s5 U1 Z -
+ x4 ~. Q0 C* |8 a5 A1 w* ~0 W7 R2 X - /* Configure the system clock */2 D2 V& V* G5 X% F" t
- SystemClock_Config();, K6 }& J9 j3 U" D$ Y
-
) @, }5 \6 f/ z; G* E. f - /* USER CODE BEGIN SysInit */+ x! \4 W% P2 a! z3 M
-
! h$ g2 x# p6 h/ u8 F( \2 a6 E - /* USER CODE END SysInit */, {$ R$ R2 s5 O
-
$ M6 u0 ^$ Q" G4 y8 {# R( C - /* Initialize all configured peripherals */7 F7 @+ `. q; I/ X3 r) ~7 A
- MX_GPIO_Init();( t) h9 U& \2 D+ ?/ E3 }
- MX_DMA_Init();
, O+ [6 P& D$ {/ _# Q. a1 a/ Z" b0 t - MX_USART1_UART_Init();& K w) `4 B) `' A. Y, }
- MX_USART2_UART_Init();- S& `7 l! `+ a: G V9 C% C
- /* USER CODE BEGIN 2 */! [) w- e& P5 d5 e/ y
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET); //初始化LED灯,默认点亮; C3 n( v7 |9 ?9 N0 u4 S; a
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET); //初始化LED灯,默认点亮( l4 H# S' N/ I- ^3 x6 S2 G$ P% T
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET); //初始化LED灯,默认点亮 H+ _$ M& `' F: }
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_SET); //初始化LED灯,默认点亮
6 W( X; A5 s; n- o( z6 O4 U8 x) } - HAL_UART_Transmit_DMA(&huart1, (uint8_t*)transmit_str, sizeof(transmit_str));
* Y1 X/ J+ A, [# _6 ^6 p5 U - DMA_Usart2_Send((uint8_t*)rs485_str, sizeof(rs485_str)); //初始化log提示
# G) ^9 }" E# c' {6 W* S4 o R. m+ v( I - HAL_Delay(5);
) R9 l3 b* w! Q; e, z. {! [! ?2 a/ h - HAL_UART_Receive_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, UART_RX_LEN); // 启动DMA接收
& k% F- _5 h% o1 c - HAL_UART_Receive_DMA(&huart2, uart2_rx_struct_t.uart_rx_buf, UART_RX_LEN); // 启动DMA接收/ w$ m+ x. M# V9 U K
- . ?* L* I- j3 g0 _6 f0 p5 M3 e
- __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); // 使能空闲中断/ X" c( d1 Z- Y
- __HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE); // 使能空闲中断 I$ r4 K0 V# U! z. T( b! w
-
( Q( i% q7 c9 C2 Y5 g# V - /* USER CODE END 2 */# ^+ W" T' K( V6 w1 l2 R: E
- : o( A/ M' i( U) v3 R. Z
- /* Infinite loop */5 m! k( L) p$ K; e3 t% r3 j
- /* USER CODE BEGIN WHILE */9 e* @& M1 S9 s
- while (1)
5 F+ b9 ~+ j7 v( m - {; |* n) O# S; r1 {
- /* USER CODE END WHILE */. Q0 X# S# }6 D& l5 A
- - F" c: O6 j- T& l5 Y* A- c1 X+ \
- /* USER CODE BEGIN 3 */7 |) V3 K9 G4 ~: ^/ g. Y; o# ?
- HAL_Delay(100);9 `& M+ L1 n& Q
- HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0); //反转LED点亮熄灭切换' ~9 B/ z% K" n) d- _
- HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_1); //反转LED点亮熄灭切换! g* {: u% [; R9 E5 _5 ^
- HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_2); //反转LED点亮熄灭切换
: x a- a+ S" j - HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_3); //反转LED点亮熄灭切换
) Q W' G; V' k2 ]' J. U - if(uart_rx_struct_t.uart_rx_flag & 0X80) //DMA接收完成9 V" u% a8 O& k& Z5 A
- {
+ f2 e) ?" G# a* H+ y' | - HAL_UART_Transmit_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, uart_rx_struct_t.uart_len); // 将接收到的数据发送回去8 a" M! d5 S- [. _
- uart_rx_struct_t.uart_rx_flag = 0;
3 h% }- [$ \6 J5 a! }6 C" S& k - }
$ Y# u% P! Q' t2 g( S; G; \; L- M. C - if(uart2_rx_struct_t.uart_rx_flag & 0X80) //RS485 串口DMA接收完成+ z3 Y6 w0 S3 w9 o
- {
0 }8 y0 |0 V% c) a6 P3 _4 i - 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 - uart2_rx_struct_t.uart_rx_flag = 0;7 N5 `4 p( p D& U8 r6 q+ N( U7 _
- }) j# Z4 Y: R& V" M: v
- 5 q3 X: G/ {) S* Z- V; V
- ! _* Y% L% t; T# U$ Z# P
- }
$ R$ b, A/ V+ s; p7 G1 v - /* USER CODE END 3 */
; y. t5 H4 R- a3 A6 W( B - }
复制代码 _2 k$ ?! d2 _0 D- O: \
(3)main.h相关变量声明8 a9 s* e7 g( x1 _
; o' j$ j. S, ?% o
7 W5 {0 U7 m' s, Z1 y
; T' Y2 p( `0 k* k& I1 w5 S* v- /* USER CODE BEGIN ET */ v, [% f" J+ r( n3 w0 {
- #define UART_RX_LEN 1024 // 一次最大接收的数据量8 W: _2 [5 B- K& t( j6 p
- typedef struct
( w8 L' c3 Y3 B) Q0 W D2 [& K0 J - {% x( s# R2 E) n/ o% R; I& s5 i
- uint8_t uart_rx_buf[UART_RX_LEN]; // DMA数据接收缓存数组9 S, d2 d# U6 q4 e8 ~% M
- uint16_t uart_len; //DMA数据接收长度/ m1 Z9 {/ M, T+ H
- uint8_t uart_rx_flag; //接收完成标志位+ I: G& C( w! O7 i/ Y3 f
- }uart_rx_struct;
8 D2 F1 H3 c; o' g2 l' P. s - extern uart_rx_struct uart_rx_struct_t;
4 Z# s7 k* S* v( W. J& a' x - extern uart_rx_struct uart2_rx_struct_t;, {; j$ I* n' S" y
- /* 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 ?- void USART2_IRQHandler(void)
0 G8 e5 \. |7 q) d* M) F - {
, \$ K. }* g% A2 E2 P1 S+ X - /* USER CODE BEGIN USART2_IRQn 0 */
/ f3 e& i3 z( L1 t: t - if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) != RESET) // 空闲中断标记被置使8 m$ @4 }7 I; E
- {
$ y- z1 ^7 S8 X1 G - __HAL_UART_CLEAR_IDLEFLAG(&huart2); // 清除中断标记
% r, w" r# w6 d+ m0 l! j7 A - HAL_UART_DMAStop(&huart2); // 停止DMA接收6 e+ m( ]9 N c2 }$ F+ B2 o& v4 R
- uart2_rx_struct_t.uart_len = UART_RX_LEN - __HAL_DMA_GET_COUNTER(huart2.hdmarx); // 总数据量减去未接收到的数据量为已经接收到的数据量
2 \9 C; P8 J4 ?' o$ K - uart2_rx_struct_t.uart_rx_buf[uart2_rx_struct_t.uart_len] = 0; // 添加结束笿8 g) H( n. i, q7 z2 f! v/ ^. r
- uart2_rx_struct_t.uart_rx_flag |= 0x80; // 标记接收结束4 P; d6 T x* E) n" S
- HAL_UART_Receive_DMA(&huart2, uart2_rx_struct_t.uart_rx_buf, UART_RX_LEN); // 启动DMA接收3 |) ^6 t, p# \. X6 e, H) M
-
& r. t- x; Q( L+ S+ F' m% _1 o - }
9 `1 d) b- q; m; V* u4 ]/ Q" R - /* USER CODE END USART2_IRQn 0 */9 g9 D* T5 ]/ w6 M
- HAL_UART_IRQHandler(&huart2);
. J- l ^. s0 A/ g5 L, K# ^ - /* USER CODE BEGIN USART2_IRQn 1 */0 v' U8 R- o8 K7 t
- ( {$ W$ G( |' F; o
- /* USER CODE END USART2_IRQn 1 */, _, A3 Q' y4 S5 }0 E, w0 b6 k
- }
复制代码 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
' 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
! W: N0 {) q9 t: v# b5 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
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
. 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
\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
|