一、开发板平台简介:
5 V, q- W0 b3 M3 }8 g9 B# U1、开发板资源简介- ~! q% y ?% E3 a( K) \. [" r
(1)开发板主芯片型号:STM32L431RCT6
8 z, O# s4 [, x6 i7 R(2)开发板主芯片封装:LQFP-64_10x10x05P( A/ \7 v2 t* N c( |8 x* U" R2 [
(3)开发板主芯片内核:ARM® Cortex®-M4+ k. P3 a5 v& K6 W; ` A6 e ?; s* s
(4)开发板主芯片主频:80MHz1 b7 ^& E: X3 j$ x* X; d, q* R |
(5)开发板主芯片Flash大小:256KB0 S: W6 C' i+ x8 l- x
(6)开发板主芯片RAM大小:64KB
9 m) m& C$ [" h; F2 E/ J. J# d+ x: z! ?) H) J5 O/ L e. v Q
# {6 c# ]& q5 a ]- ]) a7 u
- D& E: Z/ R# ~1 s8 I3 F% Y
! w& P- A$ n/ b- P- G1 ?7 g
/ U& \* b3 W l7 O) X5 M" p. i4 w2、LED灯资源
2 V6 I( g: ~. r4 ^; q9 \( `(1) STM32L431RCT6开发板共5个LED灯资源,其中一个红色LED为系统指示灯,指示开发板供电系统是否正常,如供电系统正常,红色LED为上电常亮状态,硬件原理图如下图所示:
4 V# Q+ m. A7 K' t
4 k! c8 L& ]: w6 e6 q
! Q% t ]& e+ v. {/ @, k v9 N$ W# ^8 ~2 q/ N
4 h9 R+ T4 g: e& R3 j& C4 v7 V
(2)其他四个LED灯为黄绿色可控LED,高电平点亮、低电平熄灭,计划用LED常亮验证看门狗的作用,硬件原理图如下图所示:
( k4 r* l6 k- O: k7 {! x
( d; B; f; ?+ g- |# C* {
1 B* I: W. s( d0 d K6 Y) E
( Q6 V! h7 u- p) t W5 D3 Y3、串口DMA收发工作原理
4 b$ S$ x% H/ j7 A+ K5 m 串口全称为串行通讯接口,即数据在通信线上一次传输一位,按先后一定顺序传输。我们通常所说的单片机串口准确来说应该是串行异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART),使用TTL电平,串口需要RXD、TXD、GND三根线进行通信。( Q3 s% T2 M& @) v2 |
8 E* H0 `+ o9 l: B$ H# o
(1)我们选用的STM32L431RCT6开发板串口1已通过USB转TLL串口芯片CH340G引出,使用时,只需要用公对公USB线连接电脑即可(注意也得需要安装CH340G驱动),后期验证试验也可使用该串口作为debug串口。
" r( C) t" _9 z! B( _7 r- v4 d8 R7 g1 w( m- [( n" h4 \6 F0 \
(2)开发板上的其他串口已通过排针引出,为TTL电平,通信的时候需要注意选择对应的电平模块,如USB转TTL串口模块等。
8 C/ [ m0 r* F! P( `5 G2 F* g" b+ o8 s/ Q5 e" z/ C
TTL转CH340串口,硬件原理图如下所示:3 Z8 u/ _. R; a3 c! u. C3 g. c
2 ?, R6 [+ v0 Z+ V7 `
. G+ ?+ U, s% @& ^ b& A
! ^8 W; Y/ c3 JDMA(Direct Memory Access) :直接存储器存取,是单片机的一个外设,它的主要功能是用来搬数据,但是不需要占用 CPU,即在传输数据的时候, CPU 可以干其他的事情,好像是多线程一样。数据传输支持从外设到存储器或者存储器到存储器,这里的存储器可以是 SRAM 或者是 FLASH。
- ^# W; V2 _& A0 ]5 n% R/ I
# X9 o1 g2 q3 I0 m0 XDMA 控制器包含了 DMA1 和 DMA2,其中 DMA1 有 7 个通道, DMA2 有 5 个通道,这里的通道可以理解为传输数据的一种管道。要注意的是 DMA2 只存在于大容量的单片机中。
! E/ l `" V& }, r" f
: W( _7 O \9 B2 o* P
- P, b# V# K k+ k: S+ d0 `1 p4 B7 K: m# w( K
二、串口DMA收发实验过程
8 a C2 u2 r3 {0 s1 i6 L; b- G: ?1、新建STM32CubeMX基础工程
& W1 u+ Y7 h" f0 J* X(1)打开STM32CubeMX,点击“File”-->"New Project"4 ^2 Y% ]* z5 j5 z. a
/ ]5 p) I4 H+ D7 P
$ K% V" m1 Q. s# k+ C- i4 i1 \
; v. v u, N2 R(2)等待打开主芯片选项界面(大约1分钟时间)。
9 J! C/ M, j7 o7 C' U, `+ {9 \
) o0 a, F' v" L0 p i
' m, }# ^5 u9 m7 y: T$ z( x! i# z( r& n5 g8 J
(3)昨天搜索框中输入(或选择)所需的主芯片型号(因为我们用的是STM32L431RCT6开发板,所以此处选择STM32L431RC),然后在右下角选择STM32L431RCTx(因为开发板主芯片是STM32L431RCT6),左键双击即可打开新建的项目。
, \" {: T; u9 Z I8 @& m% C B D7 p6 L) c% n1 C& _6 @3 b3 K
9 X+ t( O; N8 q1 ]5 I! h& o$ b5 H; [/ P% J2 \; e' I d3 [
(4)选择时钟源。4 _4 H; O. U0 \
7 F# R2 w3 U R/ V6 H* |6 h% W. P$ Q
因为开发板上有8M外部时钟,硬件原理图如下所示,所以此处选择使用外部高速时钟(HSE)。$ E- ~0 ?. b" ^4 e# Q
/ J _ e7 T; N" S0 Z+ i
" |; w+ f+ `- F; \, L5 M, u& h/ x
1 n* {: r8 F5 W' d: c9 I
# t. P3 i. H8 |" x! G 因为我们没有用到外部低速时钟(LSE),此处不做处理,如下图所示。
7 m( M, j! Q: n4 s! m& ]2 Z8 Z A, H! P) t# N8 |0 W o
2 F2 {& S' e/ G0 L; H8 x2 W4 H/ c5 H" ?! J
2、配置GPIO控制LED& c! U8 A* ~7 \2 J1 g9 e4 v/ F
(1)查开发板原理图得,LED1、LED2、LED3、LED4的控制引脚分别为:
0 K* |. b% X( {0 ~5 _9 U0 aLED1——PC0. x. r( V, r3 F u% Z/ V
LED2——PC1
% {5 q; K# T7 K T. O- SLED3——PC2
. A, A X( \. F8 D" t/ N( H2 G% VLED4——PC3' T; S R) N- W6 g I, _# n$ l
! }( y& ?; ]: |! y8 h6 g* F2 j
(2)配置LED的控制引脚为输出,输出频率、输出方式默认即可。
2 g9 w# i% g r2 @
% K7 T$ A! Y6 X( R; b鼠标左键点击PC0,选择“GPIO_Output”,表示设置该引脚为输出模式
( h; a" r8 ~# ?9 p$ ^5 [3 |鼠标左键点击PC1,选择“GPIO_Output”,表示设置该引脚为输出模式。
Z6 n& S- G$ O0 }% |' _- v9 m. [+ ]鼠标左键点击PC2,选择“GPIO_Output”,表示设置该引脚为输出模式。
2 ^: ?4 i3 N9 z' J5 F8 d鼠标左键点击PC3,选择“GPIO_Output”,表示设置该引脚为输出模式。 K0 j! |4 x7 w: ^* E6 e
) w8 o- S4 r' S" n& E, f4 ?4 S
% R. j3 E9 A+ a
1 [0 v; H# ?4 T" K8 z4 p% G
; n; b5 n0 b- i0 M0 J# a
7 x' l G# G; `4 X/ D% p4 ]. ^$ j(3)也根据自己的需求配置GPIO的参数,如输出方式、输出频率、上拉下拉等。因为GPIO控制LED的要求比较低,此处采用默认参数即可,不用修改。
6 H" O5 x4 w$ ` o8 n; i: ~1 r: r& u# J6 {% d. _2 \
: e# V6 C1 L: O2 ]2 t/ r+ f/ M2 Z
5 T* N! d9 b; x& T8 b
3、配置PA9、PA10为串口
# @/ l% g7 n6 N8 K(1)查原理图得知,串口1使用STM32L431RCT6引脚为PA9-USART1_TX,PA10-USART1_RX,引脚设置如下:, s) M2 X; g) U" g: K+ O
8 R* S/ |2 L) Z% I0 A8 \4 ^
, s: K2 m! v& J- L
7 f* @* G5 H- `4 B/ t
序号1用来设置串口收发引脚的选择。: e- L/ j; E0 J1 n; Z+ H; f
序号2-3-4-5-6设置串口参数,如波特率115200、8位、NONE无奇偶校验等。% h( |( c/ G" g9 {: G; Z
7 z" S: B1 G: R7 {5 d5 p8 C% Q0 o(2)设置NVIC settings 使能接收中断
U% `* E% H* N+ }! y" W2 y( C$ Y' \$ X. ?$ A
9 ~4 a" F0 v+ f+ ]3 x
5 q" V( P. _. @8 W5 H4 z: m3、串口DMA设置 9 | P! V, N6 I9 f4 P
7 Z- H5 A, X4 B
# W! Y+ a' W }7 I- |9 R/ Z0 T
2 W' e7 Q" ^8 N1 g& y(1)根据DMA1通道预览可以得出,我们用的串口1的TX、RX分别为通道4、通道5:
T* l, `4 g9 S" u/ o" Q, l t点击DMASettings 点击 Add 添加通道$ s# |7 L9 s7 W, E
选择USART_RX USART_TX 传输速率设置为中速
# K1 Q: }8 R: \ iDMA传输模式为正常模式,即发送一次就结束。. i1 f7 C4 L! D
DMA内存地址自增,每次增加一个Byte(字节) V r7 V5 _0 i4 l4 k6 T
& d! M5 T! G9 {# H, N5 B6 a% g
+ y! `; G6 g% H, b* ?, Y; D
$ G& P* J3 O0 y4 |% g5 `
(2)DMA相关参数解析
0 s# @. z9 \3 F3 i1 _ V4 T" qDirction : DMA传输方向有四类; l% q+ s; G5 R$ ^+ @
外设到内存 Peripheral To Memory
2 W, |+ N9 J2 b R `) `4 N内存到外设 Memory To Peripheral
# O$ u' r7 F8 d! Z! _+ B内存到内存 Memory To Memory6 a( _; M7 W; }
外设到外设 Peripheral To Peripheral
0 p' U/ V2 x3 i5 Y& {7 J; `9 w! S6 ]8 I% \; b- y1 p; _* \
Priority: DMA通信传输速度有四类
) j' v4 u& w5 N v最高优先级 Very Hight' B7 c/ ^" J* `
高优先级 Hight
3 v) N" W! P: i& k# \& }8 F中等优先级 Medium2 F+ b& o3 ~: p. K2 h* ]7 I# Q
低优先级;Low
; [7 h3 F6 [' g3 F- q
9 O) ^, r. y. u% P @/ nMode:DMA传输模式有两类3 W1 O# N5 c) t5 ?
9 o3 m7 N; J4 T/ J
" J) V2 w, d% `3 Y1 g' s
& `- U. q0 ]3 d: B: p$ fNormal正常模式:当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次。/ t" `. ~) r, V% L$ T1 v' z0 g
Circle循环模式:传输完成后又重新开始继续传输,不断循环永不停止。0 b/ o# M* {7 K) R
0 o5 x% s6 P1 m0 JIncrement Address-DMA指针递增设置:& B. {) v4 V8 d: y7 _) E
$ O' N$ @0 O- s: y; D
0 Z. | @& Y" W! p4 A4 D
9 i5 f( w9 T0 g9 k8 {* @) x+ f
& t* O% I4 u" s
4、配置项目工程参数
- S" H ?$ e# [5 ]" W(1)配置时钟树,用于系统内部时钟,以及各个外设时钟等。此处选择外部8M晶振作为主时钟频率,内部最大倍频80MHz。, G; k: r& g/ K$ C
5 s ]- }" V* Q8 D
6 I; c2 L8 _: N$ Y" p
! e" G' ~( p+ j9 p3 P
(2)完成配置工程。" [% z5 ?% J; T s& f, ^
备注:需要注意代码生成过程中的继承关系,如图所示:需要保留开发者自己编写的代码时,请根据配置设置,不然生成代码后会删除自己编写的代码(从这个方面也可以看出开发者备份自己的代码是多么的重要。)( t! a/ V7 X2 i* ~/ V
f! E. @' v7 o$ J& Q0 S/ g- B) ?
2 `8 L! Y9 i! ^6 B9 ]& ^% z8 O2 j. @
. e9 }: v# M3 B. U! J# t: J
+ G9 p. M/ ?3 ~, r
; M. t) z( ^7 V. k" Y4 y
(3)生成代码。
! h& Y; L7 {& n$ ]5 [9 j( S
" Z, a" R" D; Z3 s1 j4 T% Q备注:使用Generate CODE生成工程代码前,请确保文件路径无中文,否则会生成项目失败。
# d. v2 `2 \9 V, u5 ?
. ]& o$ o$ x# p
+ v; v1 r7 \- e( c7 e# ^" y, \5 l$ d1 a
* D, ^, x1 O' N4 Z9 e, M
(4)工程代码生成成功。
2 }/ e4 Q: I( r% G& y6 I6 l; g* h1 \ v: q
; {+ S+ E; u9 F# B' ~. e5 i& Z; r- n) r1 d
三、在KEIL 5中编写代码
7 s; ~ _' l% c$ M1、使用KEIL 5(MDK)打开项目工程文件
0 }+ u( p/ L% a, y$ S源码使用说明:使用前必须把项目工程复制到无中文路径的文件夹下使用。9 l6 f9 n8 Y& d! l
(1)找到刚才新建工程的存储路径,安装项目名称,打开项目工程.uvprojx。
4 i( a) _. S7 u1 P3 F4 s) F; h, {0 o' H
! f) C$ _, v2 V4 A4 d
8 |0 |6 m" [9 u3 U) b. S' {
2、添加LED指示灯作为系统提示
- y) T2 v, q: e& L' A添加每隔100ms,LED1、LED2、LED3、LED4闪烁一次的系统提示,用于提示程序运行正常。+ d& B5 G' V( N! H1 P. X5 Z
$ g) v4 E# W" V/ ]* R0 z
( k0 v4 k: D7 v. n/ ~
) \* ]% I3 v! R" s) C+ a8 P
3、添加HAL库UART DMA 发送函数代码# O' x; x3 z; n$ I. @- @( [! k/ |
(1)STM32 HAL函数库的串口DMA相关函数如下:! b( U7 J5 W8 R; z! m
- HAL_UART_Transmit();串口发送数据,使用超时管理机制1 { h/ G1 \3 L/ T4 s5 \4 ^+ E1 { x
- HAL_UART_Receive();串口接收数据,使用超时管理机制" k/ r' I! X" Y0 t" b/ h
- HAL_UART_Transmit_IT();串口中断模式发送8 _+ f; K0 O8 k" P- y* V0 V
- HAL_UART_Receive_IT();串口中断模式接收9 L9 l. i: Z* V7 h o% }5 D0 j
- HAL_UART_Transmit_DMA();串口DMA模式发送
! i! X6 T' ]$ A/ s/ R+ _! N2 k# D - HAL_UART_Transmit_DMA();串口DMA模式接收
. x$ D" L2 P! l9 V& N; U; Q - HAL_UART_DMAPause() 暂停串口DMA
3 c0 o( M4 X9 E/ g2 l1 r! A - HAL_UART_DMAResume(); 恢复串口DMA
. O6 K0 S% M% z3 I8 r - HAL_UART_DMAStop(); 结束串口DMA
复制代码 9 j/ I& y+ B1 F
(2)main.c添加串口DMA发送函数相关代码:
a7 ?; ^8 K2 H" Y% o$ b. n- /* Private user code ---------------------------------------------------------*/
# n4 ?8 x+ n& x6 |, m - /* USER CODE BEGIN 0 */
0 q1 B8 M( |% h: H. q3 r; } - uart_rx_struct uart_rx_struct_t={0}; //串口接收数组
1 J( L2 g: u6 Z$ F9 }: m - /* USER CODE END 0 */
复制代码- int main(void)
% h" j# Y) q) Q i8 Q4 b# y - {. V2 Y! y! O* Q9 O% X, n% E: \
- /* USER CODE BEGIN 1 */ J6 d; @* X! `3 W; f H) j% B
- uint8_t transmit_str[50]= {"hello world,this is uart dma function!\r\n"};
1 d8 W( X# ^+ m0 @, L - /* USER CODE END 1 */
* z0 I0 e4 l- Y3 J6 } - & P4 W/ m) E; {# ^% a* A6 J
- /* MCU Configuration--------------------------------------------------------*/' E8 A7 S; Q4 k1 J8 H! F
- * U4 f+ t+ F. k9 q8 Z$ f
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
- }; d. P D' Z - HAL_Init();& S* {0 _" N9 o2 A; v3 P7 y- S- o
-
: v! k+ T: C8 {3 {, ? - /* USER CODE BEGIN Init */: u! k% W) O* A9 M
-
# l9 w0 W0 J( Q - /* USER CODE END Init */
7 D5 m; u+ k! [, y3 ~- O -
j" c* X4 Q0 V; B+ t- x( ~ - /* Configure the system clock */: O# l3 j% I) v2 f; ~7 S: o5 {
- SystemClock_Config();5 x6 n7 }: h x
- . ~2 S$ o; c0 Y/ S0 [* N
- /* USER CODE BEGIN SysInit */
% k6 b! I3 ]/ L! l6 h) f& G - , j6 O% q# g9 s5 h, ?
- /* USER CODE END SysInit */, _$ t, p( S- J: n0 `
- " u8 ^2 J% M9 w, |! Z
- /* Initialize all configured peripherals */, I- P: B ?. C0 {& M
- MX_GPIO_Init();
" V) S# [+ J8 |, G, _9 F9 r/ Q- s R - MX_DMA_Init();6 j; K# i: H# ^
- MX_USART1_UART_Init();$ [: U Q |/ v8 l! }5 T) [
- /* USER CODE BEGIN 2 */
! o3 a0 n( y. Y - HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET); //初始化LED灯,默认点亮
& E3 }: [4 V7 `! E; [ - HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET); //初始化LED灯,默认点亮 k& ? Y; M; e& a; ^
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET); //初始化LED灯,默认点亮: t% X- k5 q" [* X& ^, k5 J: a* J
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_SET); //初始化LED灯,默认点亮
& _5 u& \9 R( x+ h8 X: B - HAL_UART_Transmit_DMA(&huart1, (uint8_t*)transmit_str, sizeof(transmit_str)); //
G+ Z& c9 h0 L( Z# f" f2 g* Z3 e - HAL_Delay(5);
6 `$ ~6 U& J% n/ o - HAL_UART_Receive_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, UART_RX_LEN); // 启动DMA接收
& S$ q2 k) N' D$ ?# M - __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); // 使能空闲中断; A# C- a1 n; m+ Y+ f) y
- O/ n$ w/ m6 B1 i+ J( W
- /* USER CODE END 2 */- H: E' B0 K5 ^" H% T R: [/ c
-
0 h6 n4 [6 F0 v' t - /* Infinite loop */ \6 q+ h; r2 h+ b7 A& C& U
- /* USER CODE BEGIN WHILE */
. q0 S) M" @- _7 }; K @5 y: r - while (1)
1 g# h: v6 e9 [) |( h8 B: j( k7 {4 p; Y - {# [( y9 `4 P4 _) h, a$ k; G3 w8 D
- /* USER CODE END WHILE */. L3 P+ ~* C7 ]3 u
- - C' {% w h3 G! W6 F% U
- /* USER CODE BEGIN 3 */
) e' k9 B/ F& g3 p$ F - HAL_Delay(100);5 r1 g- f6 v7 L( }
- HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0); //反转LED点亮熄灭切换* y6 E* _' T% E: Z
- HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_1); //反转LED点亮熄灭切换9 S+ ?) @# g* [& I) l
- HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_2); //反转LED点亮熄灭切换
6 o2 ]! x8 H; |3 O& ^ - HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_3); //反转LED点亮熄灭切换
0 i7 p2 u5 Z& N7 g! f' m1 E - if(uart_rx_struct_t.uart_rx_flag & 0X80) //DMA接收完成, G3 B/ V% G# Q" ?4 G, j
- {/ B6 q$ X9 t( G- |1 b% b5 q% G
- HAL_UART_Transmit_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, uart_rx_struct_t.uart_len); // 将接收到的数据发送回去
: p/ w: v3 V) T/ _7 ?* r - uart_rx_struct_t.uart_rx_flag = 0;
3 k8 t6 D2 P. k2 K3 O8 F - }
; G9 ~5 O6 `- s- x" t S) s -
( b, }8 G' {( p. Y4 o - }2 o) K a) C- O1 I! b: N5 n" Z
- /* USER CODE END 3 */
2 U# d4 W$ {9 \" t - }
复制代码
. o2 J: j7 f1 |& \* s(3)main.h相关变量声明
( O. R% Q4 M3 J7 Z& C; ~% m3 n. y- /* USER CODE BEGIN ET */$ ]4 \. C4 n. F8 _
- #define UART_RX_LEN 1024 // 一次最大接收的数据量- n# A) }( r5 t, k
- typedef struct6 i# n V( x1 m( I
- {/ E& y5 u! q% q/ l8 D/ u
- uint8_t uart_rx_buf[UART_RX_LEN]; // DMA数据接收缓存数组
; X; f& b9 t9 E+ d- S - uint16_t uart_len; //DMA数据接收长度
$ c8 }; `- w1 C1 K l# c B - uint8_t uart_rx_flag; //接收完成标志位4 ?8 P6 R' i! D! X
- }uart_rx_struct;5 d; f* R; e) h2 b1 z+ Z' V
- extern uart_rx_struct uart_rx_struct_t;
* p; m) {" ]4 ?/ j -
! @$ ~: U3 Z M @( B, W - /* USER CODE END ET */
复制代码
) D# }% U' b6 g( d2 z4 a5 X1 r4、添加HAL库UART DMA 接收函数代码5 x1 i- S# S5 `: a
(1)DMA接收设置前铺垫知识点:
( h5 a7 e% i1 O STM32的IDLE的中断产生条件:在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断停止。4 @1 ~5 ^3 m! o+ M4 j
L3 {; V: i2 y q, w; X
(2)添加DMA接收处理代码: ^7 R6 }5 X6 u3 ]" D6 u& T
! y0 z" s! i& p# x, q1 _& g% M6 jstm32f1xx_it.c中添加代码如下:& g7 M, G3 @9 o r, s/ w
- void USART1_IRQHandler(void)' M) l9 m5 C7 X7 ^( g* I- U
- {
0 [' i9 Q9 T6 y- m; x! ` - /* USER CODE BEGIN USART1_IRQn 0 */
3 f5 _& R; [8 e& I0 g* b - if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) != RESET) // 空闲中断标记被置位3 T E- y( m J
- {
9 U; L! N2 u9 X - __HAL_UART_CLEAR_IDLEFLAG(&huart1); // 清除中断标记
5 m1 R3 l( f. E5 t+ b - HAL_UART_DMAStop(&huart1); // 停止DMA接收( ]& K2 t2 y! J' i
- uart_rx_struct_t.uart_len = UART_RX_LEN - __HAL_DMA_GET_COUNTER(huart1.hdmarx); // 总数据量减去未接收到的数据量为已经接收到的数据量. [; ^! u; y: A6 W& K/ y
- uart_rx_struct_t.uart_rx_buf[uart_rx_struct_t.uart_len] = 0; // 添加结束符! C9 k8 B2 j; X- K
- uart_rx_struct_t.uart_rx_flag |= 0x80; // 标记接收结束: t7 N8 |+ l( n' A0 ?7 [, _8 s& U( G d8 z9 q
- HAL_UART_Receive_DMA(&huart1, uart_rx_struct_t.uart_rx_buf, UART_RX_LEN); // 重新启动DMA接收8 e! s, U+ E$ r# |: ~: Q6 v
- }+ W9 B4 G2 b& W
- /* USER CODE END USART1_IRQn 0 */
) e! a8 {" g2 V+ q$ L" b0 s - HAL_UART_IRQHandler(&huart1);
; @0 f6 n2 F- u: R# T6 ~) ^! ]5 X - /* USER CODE BEGIN USART1_IRQn 1 */
' s; ~# ` L# B) X9 Q3 s -
1 w5 E$ Y( | s: p - /* USER CODE END USART1_IRQn 1 */. u% F9 E# L1 V. V6 {* O8 Z( c
- }
复制代码 6 R5 a$ x. K# J3 A7 m$ s
(3)至此,串口DMA收发数据需要添加的代码已经完成。
0 W- X$ ? f3 i# b
( C, g0 y9 ^3 [0 h5、设置编程仿真下载模式2 i r# M9 @8 o+ {, p/ q
(1)选择Options for target ...>>Debug>>J-Link/J-JTRACE Cortex,点击Settings>>选择Port(SW),可以看到搜索成功SW Device,表示芯片可用,可以下载。* e! I" g' F1 |( I
! {5 Q7 ~% ^. b& X9 [
& Q/ v) E+ N& S
; t8 F ^! {, ]/ m(2)点击编译,完成后提示“0 error(s),0 warning(s)”。
7 q3 s$ A c+ m* i: y
. w W# P# G0 k' b$ `& M3 d$ [( D& j+ u
" c. |0 r9 J- Y3 ?7 S
, ]7 Z3 ^& e8 g(3)点击Download(或者快捷键F8),即可下载程序。/ S2 M# W! K- O: Z3 D
5 n: R1 T/ l/ u4 B" }( e
}* R+ s5 Q; q& \ n3 n
2 J8 j9 w% w5 b9 x5 m) c, c
# L7 q+ F4 W- G. w5 C% C(4) 如果下载程序后,没有看到LED1、LED2、LED3、LED4闪烁,可以按下述方式设置一下(Reset and run表示下载后自动复位和重启运行)。或者重新彻底断电再次上电(或按开发板的Reset按键复位MCU即可)。4 F; I u/ L+ U* r2 `0 W" Z
* K- L1 e' r3 S7 ]
# Z) V# l9 B: `1 H! S8 ]
& M6 [2 p* ~+ D) J4 }- r) L( [6、串口DMA收发实验效果展示
, w7 G( G1 D& E3 F- C8 P, e 程序烧录到开发板后,即可看到LED1、LED2、LED3、LED4初始化后每隔100ms闪烁一次,并且打开串口助手后(串口参数:波特率115200、N、8、1),通过串口助手可以看到,开发板接收到发送的数据转发出来。; u& M( @! L' Q4 |1 c4 ]
! x* _4 b4 s2 e) b
! i% B( [8 Z l* ~ ]" O
5 U& i3 R9 |5 W9 S0 G4 @8 q————————————————; c% M' O P9 V7 B8 Z
版权声明:智能小屋ZYXC( S4 a- y1 G7 L1 t* x
5 B! F9 z% N. j3 p9 ~5 A
# g; h, g1 [+ H3 Q& X. ?
|