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

【实测教程】STM32CubeMX-STM32L4之研究串口通信(DMA)

[复制链接]
STMCU小助手 发布时间:2023-1-15 00:07
一、开发板平台简介:! u* ~8 ~. e3 W7 {& J3 W
1、开发板资源简介

# \) r$ L; C+ f- H(1)开发板主芯片型号:STM32L431RCT6
  K& v3 M, w5 q+ K0 [(2)开发板主芯片封装:LQFP-64_10x10x05P4 t, D& G8 ?" Y+ N9 A
(3)开发板主芯片内核:ARM® Cortex®-M4
4 r; Z7 J+ o9 |9 I* Q- ^- @(4)开发板主芯片主频:80MHz8 x( C  q4 d. R) ~
(5)开发板主芯片Flash大小:256KB: }: }2 t3 o+ u8 l( n8 o
(6)开发板主芯片RAM大小:64KB' l* G0 U0 j' H. W" U5 X
(7)其他外设:请参考芯片手册
" ^, w9 Q7 ~( D" h. ^. t" D8 C5 t( j- o/ r8 y
bb91345227434ee7a43a34bf3fe366e6.png $ [7 q; `) H% B- e2 ]# ]

/ q8 B, f4 x  ^  \
929c0cce04aa4115a8623703982bf3e1.png , i7 H2 Q. N3 Y; G) H+ b8 D7 h
" ?  E) l7 A- y9 ^& I' _
2、串口简介

" J7 S! H9 p( v" I         串口全称为串行通讯接口,即数据在通信线上一次传输一位,按先后一定顺序传输。我们通常所说的单片机串口准确来说应该是串行异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART),使用TTL电平,串口需要RXD、TXD、GND三根线进行通信。
/ f: _* e4 p! @# ^7 S$ G8 m! u5 u0 l7 s. [0 \/ N7 B
        (1)我们选用的STM32L431RCT6开发板串口1已通过USB转TLL串口芯片CH340G引出,使用时,只需要用公对公USB线连接电脑即可(注意也得需要安装CH340G驱动),后期验证试验也使用该串口1进行。
4 D3 Z  K# \$ P# G" f8 x- F9 q% G- R. z: ]
        (2)开发板上的其他串口已通过排针引出,为TTL电平,通信的时候需要注意选择对应的电平模块,如USB转TTL串口模块等。) [2 W" j% t3 b0 L5 |% y  m% x

$ _9 _+ e. B; K5 V7 C* d

' e% f3 [8 L9 i) i) V  二、新建工程
& Q; ~# z  A4 z, L0 L1、新建STM32CubeMX基础工程
) u+ N4 ^/ |8 X: M$ D3 }  U8 b  s, a
(1)打开STM32CubeMX,点击“File”-->"New Project"
4 n9 R( A% y7 K  X$ i! k: D5 O$ k3 Y/ [2 K: q5 U
2399170347904e959c855fefd5877f84.png
  a, \. A) c- S5 Y( N

* z$ G3 m8 h/ G9 D(2)等待打开主芯片选项界面(大约1分钟时间)。
4 H2 O+ ^4 M* {1 c
6 c/ s" V  N9 _- q4 T# R9 Z: a6 w1 F
d74d2fdc60c9440483e2b7cf8d928e7f.png + O2 L" X1 B0 }: }
2 @% {* d& _8 y/ n* |9 m6 C

# v/ d6 V4 @7 V. _(3)昨天搜索框中输入(或选择)所需的主芯片型号(因为我们用的是STM32L431RCT6开发板,所以此处现在STM32L431RC),然后在右下角选择STM32L431RCTx(因为开发板主芯片是STM32L431RCT6),左键双击即可打开新建的项目。! K6 G- i+ Z! f
) {6 o& O8 O1 i' Y  g: j3 J; ^
7b80345238d74bea82ce70e1a348f7b4.png
0 M' R* E% t  t7 r% i4 F2 \: o# _  F
(4)选择时钟源。
# f9 ]. t5 t0 G+ j(1)因为开发板上有8M外部时钟,此处选择外部高速时钟(HSE)。
* y3 t( x! v3 o2 B+ h(2)因为我们没有用到外部低速时钟(LSE),此处不做处理。
7 P- \5 T- [- d9 Z/ J8 T/ y9 o; {* z0 [
72119b971f62410fa8344f7f9fb9f389.png 4 @0 x# ~1 o: A! \5 ]) U

# |1 W; e' o9 K2、配置GPIO控制LED

1 e* z+ y7 H+ t, l; U备注:LED灯用来指示系统是否正常工作。1 j% b4 Y- o0 t  z1 n  w
(1)查STM32L431RCT6开发板原理图得LED1控制引脚为PC0,则配置GPIO的引脚PC0。
0 q- J& d* p3 U( U, B! P3 p. y鼠标左键点击PC0,选择“GPIO_Output”,表示设置该引脚为输出模式。
3 d, S5 z! X3 K/ f" X5 g" g! N# F& J+ {# Y, J* k: N* b( O9 Z
492907c1e71149819adbaee4516a2af4.png + ^7 _$ k" g$ }) t% X0 P
! A3 l7 U- |* Z% l! ^+ W
(2)根据自己的需求配置GPIO的参数,如输出方式、输出频率、上拉下拉等。因为GPIO控制LED的要求比较低,此处采用默认参数即可,不用修改。
. n( Q1 S" k% p0 M/ h4 q) y5 j4 k5 V' z, C
38ff4b80e1c5495ba3076a5158fd91fa.png - C! d+ r  x' I0 p' i9 \4 Q) k3 s

' i7 T, _4 H; D, T( G1 J0 ~' s1 v3、设置串口1参数: B4 O  `9 ?* R% t# r% K
1、查原理图得知,串口0使用STM32L431RCT6引脚为PA9-USART1_TX,PA10-USART1_RX,引脚设置如下:' U( F0 U9 j1 ~! d9 L: f
$ C1 {. m( v- i, P6 p4 w
497b8ee0243e446784e64a3c31e8a26f.png 2 K# [2 s$ C# F# u( M! Y! c

7 ^( p" q" j0 o" p  v; e, c (1)序号1用来设置串口收发引脚的选择。
1 |2 ^$ N' N, b  p8 C5 g( n
& L2 b  L  G+ O5 p' k% \/ ?% [
(2)序号2-3-4-5-6设置串口参数,如波特率115200、8位、NONE无奇偶校验等。5 E$ Y/ J- ^) ?; b) y
& W* b1 ]8 V* [% N1 }: D
2、设置NVIC settings 使能接收中断
0 e& {7 x; v1 W! g. h" [- M# p6 X/ I1 O/ R1 a# ?" ~: x9 g
f9d7783b08304465815834f4d2095571.png
3 n2 t. p) q) p2 I- y' L2 ~/ Q; M* j. Q( b5 z
4、串口DMA设置

) B  p% v4 u' i9 Y$ t+ b& ?* C% h) N& Z/ A. N
6d26b13dd9d34039a2b426ca47680f8c.png
9 ^" U/ l, B. J3 \3 y5 i; ~+ n9 P! r& M- g7 v' w
(1)根据DMA1通道预览可以得出,我们用的串口1的TX、RX分别为通道4、通道5:3 f! f6 B) q* M
点击DMASettings 点击 Add 添加通道# Z' U6 L4 `9 `% a9 H/ E
选择USART_RX USART_TX 传输速率设置为中速$ V% N) z( e3 u3 y
DMA传输模式为正常模式,即发送一次就结束。5 t& ]/ O4 ^0 s, \% w4 S  n( W
DMA内存地址自增,每次增加一个Byte(字节)
( F7 V0 p" K0 e4 U: K( L
' X0 X6 Y( P* q; t/ z" w3 X* n
976712e0494a4482bf65c69fc09fcabd.png 6 y) e- i  f& E& N& c; H) O. [
6 y" ^0 I; z+ v% x
. t# T" }! Z$ u# T
(2)DMA相关参数解析
% l$ P, n5 c. ]4 Z2 K8 p. u
- s  z- L4 [( I% V( ~7 t% r  iDirction : DMA传输方向有四类2 R3 W6 }7 o2 q" N. Z8 R+ H& G' U( S
外设到内存 Peripheral To Memory4 {% M: q# s& I! m) f, A% y
内存到外设 Memory To Peripheral
. O  [+ C  q+ L1 \4 P内存到内存 Memory To Memory
4 c( z# ^9 _# A. P/ V$ F外设到外设 Peripheral To Peripheral- C: L# ~1 k% n
Priority: DMA通信传输速度有四类
- N2 r/ I  s( W8 C最高优先级 Very Hight
3 N, c+ a) Z$ i高优先级 Hight
" Z) s7 ]+ C+ x: R# a中等优先级 Medium
2 l+ c6 D$ e/ i6 {0 q/ g$ P2 g0 Z低优先级;Low
+ C4 o  R, S. j1 R# l
" K* U7 p( P9 R8 s% J
Mode:DMA传输模式有两类
. Y# @4 y% X$ ?5 C0 J1 s( j6 u: }; _
9021c11fed3e4c1885477e062b846258.png & [9 W# l# Z: ^, G# S+ p, {9 _% H4 g

  o* A" ?( X( J) K
" Z2 W4 T9 r/ e+ {6 h7 T5 O
Normal正常模式:当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次。2 Y/ P; y  q( c! C4 s4 \( [; b: I
Circle循环模式:传输完成后又重新开始继续传输,不断循环永不停止。: K+ z6 b& ^6 @+ E# D

# W* @4 Q( d: ?; l$ e) g; N
Increment Address-DMA指针递增设置:
% g: ?, E, s2 v, I# x3 o9 L! w5 z# B5 w1 t" d- S) F) J7 r) p. w
2b1a952d6514444e9dbb019a9ae88c42.png - k' ^/ i" }% y0 @
& F" ~0 D/ m8 H

5 ~6 A3 f+ y2 q8 c& B9 k0 O" z5 ]6 ~ 5、配置项目工程参数
, r6 s2 y( N% P+ h(1)配置时钟树,用于系统内部时钟,以及各个外设时钟等。此处选择外部8M晶振作为主时钟频率,内部最大倍频80MHz。, c/ j/ @# B/ M7 y: s

7 V) t9 ~7 w4 G4 Y7 D$ t
2ce1933c10484d819234682f4abc0228.png ; `1 d, ^* S/ u$ U9 e: |  D
# ~& a$ Y8 ]5 o4 H1 U. C8 I6 Q
(2)完成配置工程。5 r, o: H4 v' v, C6 |  F/ Y  ~  F
备注:需要注意代码生成过程中的继承关系,如图所示:需要保留开发者自己编写的代码时,请根据配置设置,不然生成代码后会删除自己编写的代码(从这个方面也可以看出开发者备份自己的代码是多么的重要。)
  S% b$ X# W5 f% t8 D. j5 R: ?+ x6 d& E! U# K: P: g7 l
efdb616174f54925b6eac31109f227b5.png 0 N' I, O" f+ H5 v4 E
9 z+ O; I* L6 ?, C8 v, J
41c3f2716e4e4eda8f62fa3a1d871322.png
. ]' k" W: g* ?8 p  r+ k% n* \) M8 p( \, @
(3)生成代码。% E- d7 [( g  L5 ]( Y" i" O8 K
' b6 V, @3 m6 }3 n0 r3 f
8eaa7d0babea40ee93f158481a6ee471.png & d: i3 R) q' n& Q; w9 o
( l6 ^4 O$ Q$ a- H0 _
三、在KEIL 5中编写代码
' ]  F3 ]) d# |; G  C1、使用KEIL 5(MDK)打开项目工程文件

6 `9 F0 c- G  D) x$ c(1)找到刚才新建工程的存储路径,安装项目名称,打开项目工程。
$ E. Y1 E6 E  W" `) y- Z  [! W+ Y8 N( c8 S, z/ a
9837b01954cc4d3ba3e25073f31b30b5.png
# w6 H/ ?5 k1 C0 p2 W7 P/ K9 |. {$ s/ L/ t8 y; h
2、添加LED指示灯作为系统提示" r# }& a* K' s# ^
添加每隔500ms,LED1闪烁一次的系统提示,用于提示程序运行正常。) n! a& d0 _9 i; F! v
( U; A) h3 u( E1 L8 I/ e
6ab72ceaeb7a41af833842fe5ba6f34d.png
- x! N. x, i% K; \! u( Z3 }9 k% f. b" P1 ?+ N, j& `
3、添加HAL库UART  DMA 发送函数代码1 t' L/ S) @+ e
(1)STM32 HAL函数库的串口DMA相关函数如下:# [% j1 d- o0 A: J0 I
  1. HAL_UART_Transmit();串口发送数据,使用超时管理机制0 C  c, j, G: u3 @5 X
  2. HAL_UART_Receive();串口接收数据,使用超时管理机制
    $ h* g; `  g$ u5 d8 l
  3. HAL_UART_Transmit_IT();串口中断模式发送
    8 C9 Z: e' C5 k7 j+ \
  4. HAL_UART_Receive_IT();串口中断模式接收
    * M* g+ g  w9 E3 R8 h# l3 x- N7 ^# B
  5. HAL_UART_Transmit_DMA();串口DMA模式发送
    : V. d3 P' d/ X/ E4 K' \
  6. HAL_UART_Transmit_DMA();串口DMA模式接收8 B' V( f, X/ M$ h
  7. HAL_UART_DMAPause() 暂停串口DMA
    . I5 a' n* u; N0 i: S' _
  8. HAL_UART_DMAResume(); 恢复串口DMA
    8 E, v. Y2 R2 p3 k: O$ ~' _8 ]7 ?! V
  9. HAL_UART_DMAStop(); 结束串口DMA
复制代码

4 P1 G: [2 J5 o1 ~9 u. J3 s(2)添加串口DMA发送log代码:2 z7 Z8 [4 E$ \! N+ H. l
  1. /* USER CODE BEGIN WHILE */
    / @7 s; W9 Z/ Q* s( o5 s5 x
  2.   while (1)
    " B) c0 X1 ]! p, @# h3 c7 o
  3.   {  K6 g0 U; v6 B8 r9 Z4 T/ _" n$ v
  4.     /* USER CODE END WHILE */8 r4 t8 |6 b2 X/ J8 B' r

  5. 2 z+ i% e- d: [+ X" m, r9 \
  6.     /* USER CODE BEGIN 3 */  K# Y: ~! f  P  E& o
  7.             HAL_Delay(500);
    - W0 n- K$ _. D. Q) n( K8 e
  8.                 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);//控制LED1闪烁; Z2 U9 y' y$ q8 L8 R  l' S
  9.                 HAL_UART_Transmit_DMA(&huart1, (uint8_t *)"hello world,this is usart dma send and receive...\r\n", sizeof("hello world,this is usart dma send and receive...\r\n"));//发送提示  
    3 o2 w$ T) H$ V! @0 K
  10.         }8 @# H) C2 g1 E1 Y2 n: l
  11.   /* USER CODE END 3 */
复制代码
) v  F; ^& O2 h. {, T( w
4、添加HAL库UART  DMA 接收函数代码
/ E4 n3 _4 @+ b, i0 R* J: [
(1)DMA接收设置前铺垫知识点:  l6 H0 s. L/ d: e
        STM32的IDLE的中断产生条件:在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断停止。' W4 H1 F$ }* C
8 Z* `3 s& k/ M
(2)初始化中断接收配置:  `2 E8 b) I- @2 n
uart.c添加代码如下:
9 o. s- J% A1 z# P

  1. . S& D+ q8 z) y! d1 i
  2. /* USER CODE BEGIN 0 */; ^8 I% r" g( c0 d" S: |
  3. 3 y% L5 K. l1 s
  4. volatile uint8_t rx_len=0;                        //接收一帧数据的长度
    ) ]0 E. ]7 I+ b4 a: v* m
  5. volatile uint8_t recv_end_flag;            //接收一帧数据结束的标志位: w  {% n. z% q1 i6 o
  6. uint8_t rx_buffer[100]={0};                        //接收一帧数据的数组大小
    6 E, w4 Y) a, B! q
  7. /* USER CODE END 0 */
复制代码
  1. /* USART1 init function */
    ! _5 w5 {( Q# X2 Y; P/ x

  2. 8 c6 I8 F- z! U1 Q2 Q& Z0 }
  3. void MX_USART1_UART_Init(void)& D7 S. K' a+ r" p6 s9 o
  4. {
    + t0 n/ R$ K7 n  y; q/ k. y

  5. # P" e+ d9 E! A4 G+ q
  6.   huart1.Instance = USART1;' J+ s2 o- t8 b# \6 D) T' X
  7.   huart1.Init.BaudRate = 115200;
    % j5 n5 J# g( O) b& M6 W
  8.   huart1.Init.WordLength = UART_WORDLENGTH_8B;9 z3 N& {5 l& Z( a
  9.   huart1.Init.StopBits = UART_STOPBITS_1;
    # L- X$ x6 O) x+ p8 Z+ O3 n
  10.   huart1.Init.Parity = UART_PARITY_NONE;
    ) i9 q% n' g9 W" |; @
  11.   huart1.Init.Mode = UART_MODE_TX_RX;) @- K7 B9 W& j  d# f
  12.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;/ E! Y8 a$ l7 S3 j: _  i; F
  13.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;7 g$ L  [' \# N, n
  14.   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;- ~; T! [& y( ^2 K$ b- @
  15.   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    8 S+ Q& K( I( i) N+ y
  16.   if (HAL_UART_Init(&huart1) != HAL_OK)" S; }3 Z9 w4 i* x
  17.   {
    / D, W$ l/ j  F( X
  18.     Error_Handler();) B% a: l: m' j; R' }9 I
  19.   }2 ]6 q; O  w: K* z: U% D/ k
  20.         /* USER CODE BEGIN 2 */2 L3 V6 H0 ~9 [
  21.        
    6 A1 M* ~% M, C/ @$ i
  22.                 __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);                     //使能IDLE中断7 R; I, S4 y. f7 Q5 D
  23.                 HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);            //DMA接收函数
    7 Y2 J2 r& M# h" J& Q) K- ?

  24. $ C* w: \6 V" w
  25.         /* USER CODE END 2 */
    ; @& `* ?# s! M* e& A$ z
  26.         2 i, W+ C7 ]7 J; \
  27. ' t) n# Z+ _% f- l! K8 |5 t% u: `8 ]
  28. }
复制代码
1 b, P. w$ _& ~$ A# \( q
uart.h添加代码如下:% |* Z, U5 B  k  d: Y9 R2 h
  1. /* USER CODE BEGIN Private defines */
    # Z3 a9 l* k- A! x
  2. extern UART_HandleTypeDef huart1;9 U0 ?, [1 g! u( K7 `5 {5 Y' ?3 B, |
  3. extern DMA_HandleTypeDef hdma_usart1_rx;( q& i3 d6 M0 n* C
  4. extern DMA_HandleTypeDef hdma_usart1_tx;- x, h3 S- Y( r8 l, x

  5. 9 ~# }5 d  n3 j
  6. #define BUFFER_SIZE  100  ! }8 t7 C' f! B, U
  7. extern  volatile uint8_t rx_len ;                                  //接收数据的长度* D0 o9 q" t& C% r# Y) _
  8. extern volatile uint8_t recv_end_flag;                     //接收数据完成标志位
    8 \' a9 h7 m7 f; H4 e
  9. extern uint8_t rx_buffer[100];                                  //接收数据存放数组
    , e$ B$ X. M( m9 R3 _- J

  10. ( ]4 l) f/ T: @
  11. /* USER CODE END Private defines */
复制代码
2 F  c$ J4 u, T) k8 N
main.c添加代码如下:
* P2 b7 @; h" N: k* p0 s# O* r* t! c
  1. /* Private includes ----------------------------------------------------------*/# N9 W: Y: d: A3 r" i' o: s4 _
  2. /* USER CODE BEGIN Includes */0 C5 Y: s5 U" a" n( W
  3. #include<string.h>                        //添加字符串头文件% ~' R( q( @9 h5 @2 o
  4. /* USER CODE END Includes */
    8 O8 Q. j% I+ W/ M
  5. /* USER CODE BEGIN 0 */3 b) v8 Z. P/ y7 o" j7 g0 J
  6. /*******************************************1 f# \/ g; x7 |
  7. *函数名:DMA_Usart_Send
    " b5 E* B$ t' H' h9 K* r  b% X
  8. *功能说明: 串口发送功能函数
    + C: ~. E" K( K; j6 l' Q* Q* c
  9. *形  参: buf,len
    ( r9 D& r: S7 J5 b* o0 I
  10. *返 回 值: 无  B3 v' h: i/ V5 K7 z0 q
  11. ********************************************/  R# ]* s+ w# r  G' O0 |
  12. void DMA_Usart_Send(uint8_t *buf,uint8_t len)       
    & O0 d/ p. `. ?* o
  13. {
    1 l3 x$ G* w$ D; q4 f8 ~
  14. if(HAL_UART_Transmit_DMA(&huart1, buf,len)!= HAL_OK) //判断是否发送正常,如果出现异常则进入异常中断函数% j; n, J+ `) n
  15.   {$ q7 H' t! F: R/ m- y
  16.                         Error_Handler();                                                                                                                                //异常提醒: p0 m# \6 f; j% u2 b& P
  17.   }
    / Z! Q6 x; S9 ]: N( O" K) ?
  18. }( i% c* M" Q% I7 v6 E) h
  19. /*******************************************2 N8 o, ]0 F/ o
  20. * 函 数 名: DMA_Usart1_Read
    - \$ _' U; ]( {7 D4 F7 y
  21. * 功能说明: 串口接收功能函数
    7 N8 [1 O- G) o9 y
  22. * 形  参: Data,len3 b. F6 e& l8 `1 |, @' R+ f6 j" W
  23. * 返 回 值: 无
    * K8 X% o& v, J$ W& Y
  24. ********************************************/. h6 \1 ?/ c& G) p
  25. void DMA_Usart1_Read(uint8_t *Data,uint8_t len)7 K+ v: ?- V& m' ?" s
  26. {
    % m5 [+ }( ]* S
  27.                 HAL_UART_Receive_DMA(&huart1,Data,len);                                 //重新打开DMA接收
    9 J" \1 c5 Q/ Z& m+ [! H
  28. }: [, J2 g( Z( v. r( C
  29. /* USER CODE END 0 */
复制代码

# r/ S( \/ w; y2 |$ i' Fmain.c  while(1)循环中添加代码如下:
4 m. P3 m9 `( C$ ]0 d3 |6 M* i
  1. /* Infinite loop */
    % c* n6 `$ e3 Q. e% t- H
  2.   /* USER CODE BEGIN WHILE */7 r! v$ R6 n9 w2 h
  3.   while (1)
    & V( H/ j/ O: \4 z/ _
  4.   {
    9 W/ w2 v- I4 q, f: h3 H
  5.     /* USER CODE END WHILE */
    & |2 Z% y. s  K+ E

  6. & d: N6 @8 p' ?& I1 m
  7.     /* USER CODE BEGIN 3 */
    9 r( G1 T+ c+ x3 f- w5 z
  8.                        
    " C( i) O9 j5 T
  9.         if(recv_end_flag == 1)                          //接收完成标志,如果串口有数据接收,则执行该部分# R9 l0 i4 E6 Q: n0 E. o
  10.         {
    ; X- w5 u2 F. m6 l2 o
  11.                 DMA_Usart_Send(rx_buffer, rx_len);
    % G, S% ^$ ~. e0 D) v7 f
  12.                 HAL_Delay(200);- }! b8 ~" q: ]1 o: d/ m
  13.                 DMA_Usart_Send((uint8_t *)"\r\n", sizeof((uint8_t *)"\r\n"));        9 I4 V# k, W1 h2 x( }, g
  14.                 rx_len = 0;                                                 //清除计数
    * Y( k' h' y$ `* c6 H$ L; z6 z4 w
  15.                 recv_end_flag = 0;                                //清除接收结束标志位
    & d- z' E; H; L1 C0 W  P/ S
  16.                 memset(rx_buffer,0,rx_len);2 _/ f, B, l, a4 R' _, N
  17.         }
    ) {( T; Y) H1 H1 W8 E7 j
  18.         else                                                                //如果外部没有数据,则执行该部分1 L: `% P; H+ A& q9 I8 d
  19.         {. h" v$ \: ~4 A  d) B3 Q
  20.                 HAL_UART_Transmit_DMA(&huart1, (uint8_t *)"hello world,this is usart dma send and receive...\r\n", sizeof("hello world,this is usart dma send and receive...\r\n"));
    ' F; H! ~9 ]. v
  21.                 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);                //控制LED1闪烁. s# r% V' w5 E7 ^, W: |
  22.                 HAL_Delay(500);0 O# R& B7 I5 d5 K
  23.         }" I7 h* @6 P: F% B/ ]
  24.         HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);       //重新打开DMA接收                               
    6 Y9 O; q# }9 f& ^+ g9 ~2 Y
  25.   }' L% t/ s  P/ a& D: G. h5 ]1 g
  26.   /* USER CODE END 3 */
复制代码
/ W) ^6 a2 ^: Q6 V
stm32f1xx_it.c中添加代码如下:2 J$ ^: P: E; F+ ~
  1. /* Private typedef -----------------------------------------------------------*/
    5 Q' ^2 P$ R) c
  2. /* USER CODE BEGIN TD */
    " V; h# C# w7 \7 a7 ?: s; o
  3. #include "usart.h"
      C: ]6 x0 y" N7 N
  4. /* USER CODE END TD */
    1 M1 h# M# W+ U4 H8 Z# a" |

  5. ' d: d* k1 E9 W& _( @8 K7 g, ]
  6. /**6 K8 _. R" T3 h! x. w0 w, S4 ^0 N
  7.   * @brief This function handles USART1 global interrupt.5 G7 t% J# Z7 A( x
  8.   */4 a' ^1 M  P0 ]
  9. void USART1_IRQHandler(void)
    5 R) _3 q3 M1 a. f! ^" Y. H; D) v6 z" B
  10. {% Y$ @5 `( I( |  G6 m
  11.   /* USER CODE BEGIN USART1_IRQn 0 */
    ( j% E- X1 h2 U
  12.         uint32_t tmp_flag = 0;
    1 E3 c$ S9 M4 I) h! I, n' r1 I% U
  13.         uint32_t temp;
    6 h% F( a4 w6 _- g" y7 O0 n/ _7 S
  14.         tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位
    ( ~$ ~0 L+ j# R' Z6 [" y4 T) X
  15.         if((tmp_flag != RESET))                                //idle标志被置位3 w' ]  j3 S1 X. ~
  16.         {
    : l8 H: ?# a8 i  D1 q
  17.                 __HAL_UART_CLEAR_IDLEFLAG(&huart1);                //清除标志位
    1 b& A" d; A0 j. ]6 q
  18.                 HAL_UART_DMAStop(&huart1);     
    ; f6 \4 `# \# W
  19.                 temp  =  __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);   // 获取DMA中未传输的数据个数   
    : U- p( w9 x& ?
  20.                 rx_len =  BUFFER_SIZE - temp;    //总计数减去未传输的数据个数,得到已经接收的数据个数
    ! @; V5 O4 K" c8 u+ D. v! U
  21.                 recv_end_flag = 1;                                       // 接受完成标志位置1        7 j- d9 R  }! F7 P; _+ G
  22.          }/ V" E7 n" l5 W* P; M
  23.   /* USER CODE END USART1_IRQn 0 */
    7 ~1 b9 v2 s/ o2 V  U7 o8 O
  24.   HAL_UART_IRQHandler(&huart1);1 u! x/ d" h( T
  25.   /* USER CODE BEGIN USART1_IRQn 1 */
    % V* |# U) b: U6 ]/ m  r$ B
  26. ! f) i8 q7 f) h
  27.   /* USER CODE END USART1_IRQn 1 */) g+ R$ k9 Y3 z8 p- o4 D8 P
  28. }
复制代码

; y  K. G* D" W(3)至此,串口DMA收发数据需要添加的代码已经完成。
9 e4 K7 u& g; ?: b, N. f" q4 \
# v3 K: y  ^9 e7 S/ [- t8 V
5、设置编程仿真下载模式  ^5 d0 h; U2 R, k6 b* e
(1)选择Options for target ...>>Debug>>J-Link/J-JTRACE Cortex,点击Settings>>选择Port(SW),可以看到搜索成功SW Device,表示芯片可用,可以下载。4 a# b: T, N/ |

/ v2 _$ m' y  E: j( K5 B" C1 \
edefb6b9a2a14be3b1221ad6d5c7a8a2.png 9 S& Q4 D) R6 v' F+ W+ ?

- F! `6 u. b' s+ I" f, f(2)点击编译,完成后提示“0 error(s),0 warning(s)”。
5 [; g; v4 A) I3 m( y, Z
! g% s2 k' x; H3 h
f0ed816a3ed14487bf9e857c317fc99b.png 4 j/ E, B+ j7 S3 D; H* i, }
( o) h, x" u8 r. w! u
(3)点击Download(或者快捷键F8),即可下载程序。
3 C2 ?$ w  u- h* ~  ^5 b
! L3 F0 h/ h1 n4 C; u
ba221842d5db40808aa129dd83c593d0.png
7 l8 j2 f5 H. H
$ Y+ V/ z0 f5 ]. s; V1 F$ o4 |2 q(3) 如果下载程序后,没有看到LED1灯闪烁,可以按下述方式设置一下(Reset and run表示下载后自动复位和重启运行)。或者重新彻底断电再次上电(或按开发板的Reset按键复位MCU即可)。+ g$ {$ [; d9 X: b+ q

# T  Y3 H. m& C! r7 h' }$ D
9f8aa1a4e8f04041bcf5cb183facd100.png 6 G# `- m# U6 G
, a; Y' T. b4 J0 x8 J$ g: D& ^
4、查看串口发送函数打印log效果
" [, K* B" I0 |4 `7 s4 G# i$ J(1)设置串口助手参数为:115200、NONE、8、 1(和代码中串口初始化参数一致)。
& O3 r5 n( Y) o- }0 }& U4 V3 p% F
9 p  |7 ?# m" `3 w, |. V(2)设置成功后,就可以看到串口打印的效果。如果串口助手没有发送给MCU的数据,则MCU每隔500ms闪烁LED1指示灯一次,且串口输出一个log。
- v' d. F; a7 {1 ?, e. l5 ~3 t( ?3 M* g' A, Y) r* c) Y  Y# D
(3)如果串口助手往MCU发送数据,MCU把接收到的数据发送到串口助手进行打印显示。
& l! l5 I, }+ W6 W  N. o7 u5 v& d. U5 f
16cd1063057845399adc6f45e25a20c7.png
, M# P8 `% ]9 J6 l! }5 }- `: ~" X+ E  l. g0 q
————————————————
8 f, M6 n" h2 z版权声明:智能小屋ZYXC
9 R$ x" i9 F5 U* j( {  I+ H, X& y# [& |  B& b

/ K& x, f. H/ S2 D  t
赞 收藏 评论0 发布时间:2023-1-15 00:07

举报

0个回答

所属标签

相似技术帖

官网相关资源

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