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

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

[复制链接]
STMCU小助手 发布时间:2023-1-15 00:07
一、开发板平台简介:7 g: d- Y  ]8 B4 b, X/ [. L4 L
1、开发板资源简介

- Q  T; [  H0 W3 U. x! n" |(1)开发板主芯片型号:STM32L431RCT6+ ]% u. F, @, ^  l0 D
(2)开发板主芯片封装:LQFP-64_10x10x05P6 a- g. f, {, k$ y9 I( F
(3)开发板主芯片内核:ARM® Cortex®-M4
2 q( }! \1 z* ]. [$ g( H(4)开发板主芯片主频:80MHz
. a6 ]! z' L' b! q& G(5)开发板主芯片Flash大小:256KB
- U- J8 P1 H$ Y/ h3 r" N(6)开发板主芯片RAM大小:64KB
' o2 N" I: @6 m3 u4 T) z) m (7)其他外设:请参考芯片手册
3 ~' K  E2 \4 u) D6 s1 P1 Z: {0 W" n$ e" t' O4 y" ^
bb91345227434ee7a43a34bf3fe366e6.png * k, p$ G1 X! T1 a$ m5 R: Z

% C$ x* B# y: S- J' ^5 v
929c0cce04aa4115a8623703982bf3e1.png ) y' g' ]; g. B8 b: Z: w

1 ~4 V8 k: M3 f7 A" v+ q2、串口简介
5 [; j1 F+ r5 `+ e0 W0 E
         串口全称为串行通讯接口,即数据在通信线上一次传输一位,按先后一定顺序传输。我们通常所说的单片机串口准确来说应该是串行异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART),使用TTL电平,串口需要RXD、TXD、GND三根线进行通信。) U6 q! M+ u$ ^* p; `' M/ A' n1 \
) G9 ~% J$ f1 c' y' Z. X
        (1)我们选用的STM32L431RCT6开发板串口1已通过USB转TLL串口芯片CH340G引出,使用时,只需要用公对公USB线连接电脑即可(注意也得需要安装CH340G驱动),后期验证试验也使用该串口1进行。
& F& p% d4 _# M  ]
* @1 d* V# [- N4 Z, L/ O        (2)开发板上的其他串口已通过排针引出,为TTL电平,通信的时候需要注意选择对应的电平模块,如USB转TTL串口模块等。
1 n: z0 ]' F+ I( k: t. r/ x( W) L9 e% Z9 v) ~' ^' L

% w- O: D, c0 H( r+ Q4 M7 x  二、新建工程- i2 T( z4 S+ T* e3 [. i5 B. U
1、新建STM32CubeMX基础工程

* v7 q& d5 u3 H) W: u5 ^(1)打开STM32CubeMX,点击“File”-->"New Project"' p; n. p9 f7 |1 A

, J. a6 i$ \2 `
2399170347904e959c855fefd5877f84.png
5 I4 B9 O# B5 ?) R: I; b
& F; C, J! t5 W3 ~# ]* l* g- v7 T
(2)等待打开主芯片选项界面(大约1分钟时间)。
' W3 [8 m- H" p- n
  ?) o) I) p- }+ ?3 X- w( F* A
d74d2fdc60c9440483e2b7cf8d928e7f.png $ \  t- h9 p; t$ F) S' |
' Y) M/ K# y: I( W2 V; E

! L4 i$ @0 p# {* {- _6 p(3)昨天搜索框中输入(或选择)所需的主芯片型号(因为我们用的是STM32L431RCT6开发板,所以此处现在STM32L431RC),然后在右下角选择STM32L431RCTx(因为开发板主芯片是STM32L431RCT6),左键双击即可打开新建的项目。7 M; s( C. O2 [2 y8 I( r
0 V/ ?& }1 ]: Y& c
7b80345238d74bea82ce70e1a348f7b4.png % |  I% }2 w2 r8 q9 m
, q5 Y2 F1 s& Y6 d5 ^5 z- z
(4)选择时钟源。
" x6 [, u. i, F3 q(1)因为开发板上有8M外部时钟,此处选择外部高速时钟(HSE)。. O, P6 W: Z1 g
(2)因为我们没有用到外部低速时钟(LSE),此处不做处理。, P# @5 W  |# c1 ]2 M3 ?) B5 c

+ k7 E! f6 ^, A, C4 n$ M% i
72119b971f62410fa8344f7f9fb9f389.png
, _' T5 ?/ z5 M/ `$ ^1 u7 n6 m

! g; c( u; U! ^+ s  A- M: U2、配置GPIO控制LED

; B" s) @! Z7 B0 |2 O! R备注:LED灯用来指示系统是否正常工作。2 X+ ^4 p8 X: h, x; E( s
(1)查STM32L431RCT6开发板原理图得LED1控制引脚为PC0,则配置GPIO的引脚PC0。
0 B! _9 e9 D  z" e0 X鼠标左键点击PC0,选择“GPIO_Output”,表示设置该引脚为输出模式。
7 e" U* `; V& F4 |& \0 n+ e0 m0 k
. X" D! G0 w7 Z$ t
492907c1e71149819adbaee4516a2af4.png
( z7 |$ a+ D+ K0 S9 {% M* P5 ^
. a4 H- J, V  U) U8 S(2)根据自己的需求配置GPIO的参数,如输出方式、输出频率、上拉下拉等。因为GPIO控制LED的要求比较低,此处采用默认参数即可,不用修改。( j* r" W: B. ]/ f$ s
0 a7 Y3 @  U0 O& T- U9 V
38ff4b80e1c5495ba3076a5158fd91fa.png
2 c+ }% ^$ n' @3 c4 y, D$ Y) y
9 K9 W: u6 c" e# ?3、设置串口1参数
& h+ a. s  D; r/ [4 v5 I& R1、查原理图得知,串口0使用STM32L431RCT6引脚为PA9-USART1_TX,PA10-USART1_RX,引脚设置如下:! S0 m# L9 K0 M6 W# v5 \

) \- c& }" ]+ s6 x5 J+ g3 N
497b8ee0243e446784e64a3c31e8a26f.png 8 T% T& M: ]8 d. a5 g& L

! Z4 L# g: U- a (1)序号1用来设置串口收发引脚的选择。& G  j. s. i! s9 v4 c' q' L
3 _! |) W3 p$ u9 P
(2)序号2-3-4-5-6设置串口参数,如波特率115200、8位、NONE无奇偶校验等。
# H: m, I2 Q) ?

6 {: ^5 u$ W+ K2、设置NVIC settings 使能接收中断) v, g, E# w% ?% q. a$ V6 {$ K6 Q
, j7 b( J9 M8 s$ m! m
f9d7783b08304465815834f4d2095571.png
9 l. V6 j, p* v7 g8 p2 y; g8 X9 q- C1 i/ n4 r$ [: Q
4、串口DMA设置
% t3 w4 c! {8 ~& r! i# [0 W' M
0 K+ G* b' _3 E0 B
6d26b13dd9d34039a2b426ca47680f8c.png
4 V& V# A9 p- \6 {8 ^" {9 |6 w! ~  o0 Q3 o3 |, L3 T: W
(1)根据DMA1通道预览可以得出,我们用的串口1的TX、RX分别为通道4、通道5:
9 r% m0 C9 \( s( c, F5 q; [( P$ k点击DMASettings 点击 Add 添加通道
  @8 ^1 U, C6 r1 P+ }5 K选择USART_RX USART_TX 传输速率设置为中速9 p8 W& b; d2 ~/ P7 F
DMA传输模式为正常模式,即发送一次就结束。* k, ]2 L0 i8 K" a! D5 q
DMA内存地址自增,每次增加一个Byte(字节)+ Y$ W8 g! s4 B' @4 v6 z1 \  u& M8 m

8 Z( v7 H- }# U* [. ~3 ~
976712e0494a4482bf65c69fc09fcabd.png
6 S! X, d* i4 p
: S4 A8 {# \) y0 e: q. H
( i' M: o: u# Z- \
(2)DMA相关参数解析
- \  u" S: B$ x2 W* |" `* |6 Y) l
' d* S! @8 N( v# N4 K; XDirction : DMA传输方向有四类
3 h% b: h4 I( i2 P" b外设到内存 Peripheral To Memory
- X6 H( \& y5 g+ t9 D3 h$ }0 U8 S2 u) a内存到外设 Memory To Peripheral9 w  \) ~8 D, z- U1 |/ g8 P( i8 y' O
内存到内存 Memory To Memory3 O2 m; u/ _, y# O8 f
外设到外设 Peripheral To Peripheral4 |# f$ A' u, G% `6 L% E8 k
Priority: DMA通信传输速度有四类
/ Y4 ]% d7 [0 K9 \8 l$ v4 n最高优先级 Very Hight
# A5 |: B! Z, C* n, }% j; ?高优先级 Hight
* i, N' ~9 Y. A3 O6 q) Q中等优先级 Medium" H& V4 Y/ n/ \5 m/ E
低优先级;Low6 p& d% }6 N2 S8 `: c- j( L; m
. `1 |8 \  o- G' h7 s: n
Mode:DMA传输模式有两类0 O) |9 _) W* T- u7 ^

8 V. y  ^5 W4 ?, Z( f6 k
9021c11fed3e4c1885477e062b846258.png ' q  {. ~- b( @4 T# ?+ Y1 Q5 f

! t/ J+ Q6 k4 b3 \% J5 m2 r" s

9 F6 J) {, ?3 U. {' fNormal正常模式:当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次。8 S3 F$ P/ ~$ E7 v$ c
Circle循环模式:传输完成后又重新开始继续传输,不断循环永不停止。5 g2 n' f+ ^6 @  W- D+ Z

, {, M) B2 |; _7 o4 T6 f
Increment Address-DMA指针递增设置:
0 h+ q, ^0 @" O) f& |7 U! O, A/ M+ U/ G- h0 V. u- G8 t
2b1a952d6514444e9dbb019a9ae88c42.png - V1 p. B( K# y' X
5 Z+ V! p6 A' a' k
2 ~+ g  ]+ x9 ], T8 m
5、配置项目工程参数
" Z7 T+ {% R, [! \/ O(1)配置时钟树,用于系统内部时钟,以及各个外设时钟等。此处选择外部8M晶振作为主时钟频率,内部最大倍频80MHz。
2 D. b% k# _- U! I! ~7 W: }, P
4 F$ p5 D2 I/ d* ]7 G2 @6 t
2ce1933c10484d819234682f4abc0228.png
* R' r9 s) `% g
5 @, j6 v, @( F(2)完成配置工程。
' c, ]* I0 d% N6 `备注:需要注意代码生成过程中的继承关系,如图所示:需要保留开发者自己编写的代码时,请根据配置设置,不然生成代码后会删除自己编写的代码(从这个方面也可以看出开发者备份自己的代码是多么的重要。)8 _$ \9 }  k% j: O' i- N6 O

# J  k% G7 Z( Z
efdb616174f54925b6eac31109f227b5.png
) E' E9 B# W" q! t" U
6 W+ P, A0 R; }- O# I5 J8 B
41c3f2716e4e4eda8f62fa3a1d871322.png - U$ p4 ], v! y1 D' f1 }, r

) D9 R; }2 |' z4 b0 n(3)生成代码。7 Q7 y3 M& {% e8 s8 P

5 r# G8 R6 ~4 x" i% W0 A. ?
8eaa7d0babea40ee93f158481a6ee471.png
9 C9 s9 x7 I! B8 C. T  Q4 j6 A! C$ c9 `! T) l4 {$ d% A/ l
三、在KEIL 5中编写代码0 {+ [( u( x  l* w: C" o
1、使用KEIL 5(MDK)打开项目工程文件

* e( i' P2 W: i$ |(1)找到刚才新建工程的存储路径,安装项目名称,打开项目工程。( R1 K& Y1 J4 y
4 C! J7 i$ N3 W
9837b01954cc4d3ba3e25073f31b30b5.png 9 }0 n, l6 F; z% L0 p2 Q
) Y. l3 S' F* t0 M
2、添加LED指示灯作为系统提示( ?9 o% Q: b6 z2 T5 `0 S
添加每隔500ms,LED1闪烁一次的系统提示,用于提示程序运行正常。& m6 V. t( Y% V* T! g) g+ }
4 e$ q9 H& g# \2 j: J3 F4 a) d
6ab72ceaeb7a41af833842fe5ba6f34d.png 2 R" r6 h2 |# e) W: y

% G4 {' L# ^3 ^6 P' b) S) g3、添加HAL库UART  DMA 发送函数代码
$ g# _& B8 F* a; Y! G) E: |(1)STM32 HAL函数库的串口DMA相关函数如下:
1 `. C: ~# U/ f9 O. N
  1. HAL_UART_Transmit();串口发送数据,使用超时管理机制
    4 i6 [/ _- L% R& Z
  2. HAL_UART_Receive();串口接收数据,使用超时管理机制
    # t- ]1 ~3 O, N! b' ]3 p% \
  3. HAL_UART_Transmit_IT();串口中断模式发送
    1 ^3 K6 Y7 q8 K& ^# `. |
  4. HAL_UART_Receive_IT();串口中断模式接收7 A% l. J& Z% k/ s; a
  5. HAL_UART_Transmit_DMA();串口DMA模式发送
    9 c! b; a# b$ c
  6. HAL_UART_Transmit_DMA();串口DMA模式接收2 Z$ G; D" @) s1 P5 c1 g5 Y4 o
  7. HAL_UART_DMAPause() 暂停串口DMA4 f" Z( Q+ K* i
  8. HAL_UART_DMAResume(); 恢复串口DMA/ e: w# \  f+ U6 P% M) C
  9. HAL_UART_DMAStop(); 结束串口DMA
复制代码
9 I$ x3 v# U2 f
(2)添加串口DMA发送log代码:% P6 o9 F$ f* e; e* k- i; }
  1. /* USER CODE BEGIN WHILE */& c4 s' N' j+ Y! N: e5 C3 q0 t
  2.   while (1)* M5 S9 c9 s: r, e
  3.   {
    # r6 U1 s  I% p" d: s: {! o
  4.     /* USER CODE END WHILE */
    , A# T3 C6 V- F- M2 \
  5. 8 V$ C4 c5 s/ T7 x0 u) {
  6.     /* USER CODE BEGIN 3 */3 `' {2 {) s9 J+ Y8 T* n
  7.             HAL_Delay(500);0 p8 R8 w5 R: ]0 Y8 z( I# v# `
  8.                 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);//控制LED1闪烁
    3 K- H, i( V% Q' P8 {  `+ h1 I& F
  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"));//发送提示  5 I0 s$ {. ~+ q1 B
  10.         }
    ( c1 Q/ k: y6 d) `
  11.   /* USER CODE END 3 */
复制代码
+ S0 |5 ?( P0 N! o# f
4、添加HAL库UART  DMA 接收函数代码
" J% H* [! [% b5 S' H7 ^
(1)DMA接收设置前铺垫知识点:+ J. G9 K4 P7 e9 G5 q
        STM32的IDLE的中断产生条件:在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断停止。
: U( _& N6 u9 K0 A
4 ^' l  Q0 D& ]8 B1 j3 [2 F
(2)初始化中断接收配置:% u' ?5 i3 c1 [. ^
uart.c添加代码如下:
8 d9 Q4 g- t. a% }% D8 T, b9 X

  1. . _7 [/ e$ b! K9 y
  2. /* USER CODE BEGIN 0 */3 r! n: ?6 ]; ~6 F( w7 z: a
  3. . q& b! x' B8 v) K
  4. volatile uint8_t rx_len=0;                        //接收一帧数据的长度
    ( Z- A- M2 O+ h$ P( D0 _
  5. volatile uint8_t recv_end_flag;            //接收一帧数据结束的标志位5 h; t- g$ R: m- s3 o  Y. k
  6. uint8_t rx_buffer[100]={0};                        //接收一帧数据的数组大小
    5 t/ ~! q" Z/ V/ |4 N) _: N* t
  7. /* USER CODE END 0 */
复制代码
  1. /* USART1 init function */
    , ^/ u9 Y* E8 ]4 C

  2. $ w% X1 C" `; v- S. U9 I2 l' @- S* F
  3. void MX_USART1_UART_Init(void)! ?' ?( f5 y- f' s6 M$ [( Y
  4. {
    2 t6 I' s" A  v$ r( `. x5 Y

  5. ( x: t: X0 {6 D
  6.   huart1.Instance = USART1;
    ( R! j" {8 S4 E9 p9 O7 |/ o
  7.   huart1.Init.BaudRate = 115200;
    , U+ u' x  P! F* y6 P
  8.   huart1.Init.WordLength = UART_WORDLENGTH_8B;
    ; r, k8 E8 Z+ C# j
  9.   huart1.Init.StopBits = UART_STOPBITS_1;+ ], r. s2 F" `$ K. ~0 `8 c" E' ?
  10.   huart1.Init.Parity = UART_PARITY_NONE;; b- _/ b  ?. m' J. K% t
  11.   huart1.Init.Mode = UART_MODE_TX_RX;
    $ n( q# J' ~  m1 E7 j
  12.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;' i; }& \' }0 m* ~; f- z* A# v
  13.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;# W6 k  p+ l9 y# e
  14.   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;0 I& M. s4 v4 c* h4 l+ r
  15.   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;, n1 Q; s' d% O7 Q
  16.   if (HAL_UART_Init(&huart1) != HAL_OK)
    1 F9 M5 p0 k$ N6 ]6 c
  17.   {, y8 |2 e# S" s" m6 v; _
  18.     Error_Handler();
    ; w5 @0 j  i# F! G1 n
  19.   }
    + _0 J' ]4 v, }( Z$ n( y; D
  20.         /* USER CODE BEGIN 2 */; x  V7 Q- P# Z+ Z. [
  21.        
    ) D/ {0 A( f! U/ N, r( w" K
  22.                 __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);                     //使能IDLE中断7 L3 J* S" h% F: F- R
  23.                 HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);            //DMA接收函数
    9 d. k& s4 O& S: ]9 h5 ]

  24. ' ]0 Q: |$ z: g. P) y
  25.         /* USER CODE END 2 */
    7 J. N  ~  e# u4 K, m0 Y
  26.        
    2 ?, @2 r# e% X  H% A! x

  27. : a8 L0 t( M: Z
  28. }
复制代码

! s6 \+ S$ c5 n8 r8 xuart.h添加代码如下:
% W% A/ B1 m, b6 I
  1. /* USER CODE BEGIN Private defines */! l# v1 Y  o0 b  J1 U  e$ G! W5 [
  2. extern UART_HandleTypeDef huart1;2 n) W' }9 w. ~8 D
  3. extern DMA_HandleTypeDef hdma_usart1_rx;. e6 S$ E3 w2 N1 I, J8 G/ ^
  4. extern DMA_HandleTypeDef hdma_usart1_tx;
    . a) f! H' T! |1 g- {# \7 C
  5. # Y6 R9 X6 C4 L: \- @0 B
  6. #define BUFFER_SIZE  100  
    " u% ?# J) @, t+ U, C! r
  7. extern  volatile uint8_t rx_len ;                                  //接收数据的长度
    + d7 h5 Y9 E* X" g
  8. extern volatile uint8_t recv_end_flag;                     //接收数据完成标志位% m! S! z1 W: u. Y! L, G
  9. extern uint8_t rx_buffer[100];                                  //接收数据存放数组1 C- k# \; y. N: y

  10. * i, D! ?2 W2 b8 `; F" E
  11. /* USER CODE END Private defines */
复制代码

* s! J$ r6 O5 B$ c0 Hmain.c添加代码如下:3 `; ]9 B' H) M6 |& P4 a
  1. /* Private includes ----------------------------------------------------------*/
    6 F; [' |& ?! E& M* @( @! N# k
  2. /* USER CODE BEGIN Includes */
    6 t* q/ F1 w# @8 |* R3 v
  3. #include<string.h>                        //添加字符串头文件2 A8 K# s. v( t/ d1 p
  4. /* USER CODE END Includes */
    3 r$ l8 k7 R( N$ O: m. w0 V
  5. /* USER CODE BEGIN 0 */6 B6 n9 L, q, j$ q; ]
  6. /*******************************************3 a/ \" g' `3 k/ t' d6 d
  7. *函数名:DMA_Usart_Send8 N" Q- Y" q9 @
  8. *功能说明: 串口发送功能函数
    * g: @% I& A" g  o
  9. *形  参: buf,len
    ) _5 m3 w3 D( c* X
  10. *返 回 值: 无
    7 G- H3 `; Q2 o# d
  11. ********************************************/' R! v& W; U9 `- j
  12. void DMA_Usart_Send(uint8_t *buf,uint8_t len)       
    2 U/ G+ X1 i! J; r* y- L1 z8 o1 Q
  13. {
    1 t9 }. ?- {" }& d3 ~/ s
  14. if(HAL_UART_Transmit_DMA(&huart1, buf,len)!= HAL_OK) //判断是否发送正常,如果出现异常则进入异常中断函数
    & U4 q. \, O$ J0 s# N' O8 d
  15.   {
    * ~3 }% `' }% j; \; P- s: }5 B
  16.                         Error_Handler();                                                                                                                                //异常提醒3 H8 H9 g" d" ?' c+ t
  17.   }
    ' M- ~: P- c9 @2 O) n2 `7 g' X
  18. }
    0 Z  P) ?& ?8 D  X# k$ _
  19. /*******************************************
    6 A/ L( l6 p9 m7 m9 E
  20. * 函 数 名: DMA_Usart1_Read
    8 n: o3 e, C% J6 c2 T
  21. * 功能说明: 串口接收功能函数
    % D- a  P! k  i& p' A' \2 F5 k( X  R
  22. * 形  参: Data,len
    ( @" T4 E( Z  ?$ {! P
  23. * 返 回 值: 无
    ' K; X5 E9 }; D! e' l
  24. ********************************************/8 e$ b0 z8 T3 J
  25. void DMA_Usart1_Read(uint8_t *Data,uint8_t len)5 L* o8 s( E" M
  26. {& M# m( O- |) u# s' ^2 e4 Y
  27.                 HAL_UART_Receive_DMA(&huart1,Data,len);                                 //重新打开DMA接收1 y+ A+ Y1 g& H$ x  k1 \! k  r- j
  28. }( y; r7 @9 i0 x+ ^- N1 @/ A
  29. /* USER CODE END 0 */
复制代码

: W! [' n& @9 C  b) @9 Cmain.c  while(1)循环中添加代码如下:
) T: u! U3 _2 x% L2 C& y, v1 O
  1. /* Infinite loop */- V: w' _8 w7 n
  2.   /* USER CODE BEGIN WHILE */
    : }7 x, z* F8 _8 ?" G. H* z2 S7 L
  3.   while (1)
    2 L  a; H' n: L% ]* d
  4.   {
    / x( }+ w" k3 n. A/ V- u5 V
  5.     /* USER CODE END WHILE */% c9 Z) N# l* p+ Y* d( w
  6. " F- D1 X/ A) |* T0 z3 D7 @9 M5 @
  7.     /* USER CODE BEGIN 3 */
    & O. U- V: @" U4 }8 o$ h; u
  8.                        
    1 v0 k5 i$ U3 T/ y9 c4 S
  9.         if(recv_end_flag == 1)                          //接收完成标志,如果串口有数据接收,则执行该部分2 W1 v- {, l& k5 ~( s" v
  10.         {! W4 @5 [/ X! I
  11.                 DMA_Usart_Send(rx_buffer, rx_len);7 W, r8 f& o" i) Z4 `
  12.                 HAL_Delay(200);* m2 ^' B% r# B2 e
  13.                 DMA_Usart_Send((uint8_t *)"\r\n", sizeof((uint8_t *)"\r\n"));        ; C- \5 x3 Q4 y, R  f2 O
  14.                 rx_len = 0;                                                 //清除计数
    " y$ w1 i8 t& g
  15.                 recv_end_flag = 0;                                //清除接收结束标志位2 ~: p% t6 y6 i& j
  16.                 memset(rx_buffer,0,rx_len);- l) O# `" ?2 }5 B5 m
  17.         }/ ^& E. P1 Z+ v$ M1 m0 M  z1 k
  18.         else                                                                //如果外部没有数据,则执行该部分7 M3 }) G$ Y$ H: ?, @
  19.         {9 {  F$ |" j. U+ n* L$ r6 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"));
    / @8 _: Q# V( j$ P
  21.                 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);                //控制LED1闪烁. {0 J7 D0 S) D+ F' z7 ~+ Z
  22.                 HAL_Delay(500);
    . T) a" Y9 E# T
  23.         }
    ) u5 W9 G! |' D: m! j2 F/ F
  24.         HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);       //重新打开DMA接收                               
    5 m$ h  L' w+ ~
  25.   }
    . X1 n1 |6 I5 @* v: n' [
  26.   /* USER CODE END 3 */
复制代码
' b" B3 i: d6 y) F- S
stm32f1xx_it.c中添加代码如下:
1 n$ a* H& _: i4 V
  1. /* Private typedef -----------------------------------------------------------*/
    3 E2 U8 ~+ S5 e5 _: O! f: H$ f" H
  2. /* USER CODE BEGIN TD */
    $ g' X( b9 B3 u/ @4 _4 I7 Q
  3. #include "usart.h"6 T1 C4 b" X/ d- F9 {$ N
  4. /* USER CODE END TD *// o3 Y8 T2 y+ {8 |  B& X6 F

  5. 7 W4 _( y5 l& q
  6. /**
    : l0 D& Y1 s$ I4 c! @3 {% Q5 Q  h
  7.   * @brief This function handles USART1 global interrupt.
    3 F" l0 U0 u$ {" ~. s( B5 ?
  8.   */
    1 ?/ y& o2 T* C2 w" S
  9. void USART1_IRQHandler(void)$ `) R$ h9 \, G. \% x8 X
  10. {) \& N# H. Q! M7 o7 i/ ]- p
  11.   /* USER CODE BEGIN USART1_IRQn 0 */
    9 B8 W& O* }4 G% H  o/ O3 W& R) ~
  12.         uint32_t tmp_flag = 0;% e6 V' ~* ]" j
  13.         uint32_t temp;3 W, {8 C/ Q2 H3 e: K) r& O% j
  14.         tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位) o. ~- B4 D; P7 o& ]# U" R
  15.         if((tmp_flag != RESET))                                //idle标志被置位
    ! k  \8 e& F) t6 Q/ Q
  16.         {
    * L3 J- p; {7 B- }, P( O& f
  17.                 __HAL_UART_CLEAR_IDLEFLAG(&huart1);                //清除标志位
    ( ]! \5 n- ^$ x$ g2 }" i# ?# u
  18.                 HAL_UART_DMAStop(&huart1);     
    2 p6 z( o8 |6 L- ~3 a# T3 H( {
  19.                 temp  =  __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);   // 获取DMA中未传输的数据个数   + T& Z1 a1 H' t* `2 T* t
  20.                 rx_len =  BUFFER_SIZE - temp;    //总计数减去未传输的数据个数,得到已经接收的数据个数
    " d4 x0 D9 j% C* ~9 ~- J
  21.                 recv_end_flag = 1;                                       // 接受完成标志位置1       
    8 u+ J9 n* s3 i3 z- y
  22.          }
    % Z3 N, t4 ?- O3 W$ ^0 f1 {
  23.   /* USER CODE END USART1_IRQn 0 */
    ) q  ^2 a1 p7 r. [
  24.   HAL_UART_IRQHandler(&huart1);# L/ j4 {% `; _* G
  25.   /* USER CODE BEGIN USART1_IRQn 1 */6 Q) w1 h$ `' ^% C

  26. 6 K* ?6 v( Y! ~) a+ m. z
  27.   /* USER CODE END USART1_IRQn 1 */
    3 [1 S" O7 Z; q0 G! ^, T& o  d
  28. }
复制代码

& \' O" D  `! }0 M(3)至此,串口DMA收发数据需要添加的代码已经完成。
; ?4 b5 r1 E2 i/ t! s9 F- O
* F- |0 o7 A1 @
5、设置编程仿真下载模式
$ d2 b5 H4 Q. e' Q/ ^. k: x(1)选择Options for target ...>>Debug>>J-Link/J-JTRACE Cortex,点击Settings>>选择Port(SW),可以看到搜索成功SW Device,表示芯片可用,可以下载。1 {8 w' Z) h9 k& }

1 y' D8 g9 k( p$ I1 P
edefb6b9a2a14be3b1221ad6d5c7a8a2.png " X$ F+ ^9 S6 Y9 T3 ~
# C5 {4 L1 N; v' P
(2)点击编译,完成后提示“0 error(s),0 warning(s)”。
% B6 H( h4 E0 S+ h5 O7 s
$ y1 c& g% B' n8 _# m3 ~& m
f0ed816a3ed14487bf9e857c317fc99b.png
0 e- t$ w9 r$ N# \& L* r- {) w; g( }8 N9 t+ S
(3)点击Download(或者快捷键F8),即可下载程序。
  t- h& p- V: G8 h6 w; J( B$ V3 Y3 O9 a" r* X
ba221842d5db40808aa129dd83c593d0.png - U% f3 T8 i$ c: K  V# h

9 m% a2 v: Q; s1 D8 i0 H+ s(3) 如果下载程序后,没有看到LED1灯闪烁,可以按下述方式设置一下(Reset and run表示下载后自动复位和重启运行)。或者重新彻底断电再次上电(或按开发板的Reset按键复位MCU即可)。) W$ G: y3 W2 K1 Q; X8 n% _4 L8 l
0 W+ b# L/ G* P) k1 y
9f8aa1a4e8f04041bcf5cb183facd100.png
& z- f) u7 F+ \( r' s0 |8 k# V1 j, j& s- _6 u8 E
4、查看串口发送函数打印log效果
3 }# s2 v! X2 u- x$ L, I' ~; \(1)设置串口助手参数为:115200、NONE、8、 1(和代码中串口初始化参数一致)。
& D4 g" L7 S) B% y, n4 u( c9 k0 W) p" e  T3 c- r
(2)设置成功后,就可以看到串口打印的效果。如果串口助手没有发送给MCU的数据,则MCU每隔500ms闪烁LED1指示灯一次,且串口输出一个log。
/ i5 `1 _* i; V8 h  B
6 r; o  G9 J7 Y(3)如果串口助手往MCU发送数据,MCU把接收到的数据发送到串口助手进行打印显示。7 n- c% P! V, M* I6 j

) b2 t: Y3 E) n; R" v. p
16cd1063057845399adc6f45e25a20c7.png
, z! F$ I- O& M2 _: l  h, y" O; k2 c# W
————————————————
1 o4 Z8 x8 P/ r0 C1 k" |) W0 S* _/ E版权声明:智能小屋ZYXC
+ ^$ l1 D: g8 r" W6 r  K" N4 O" \' \
1 y; j% |$ m8 H$ c* d6 @. x
" o; \; o1 k, a5 b$ H: x; K
赞 收藏 评论0 发布时间:2023-1-15 00:07

举报

0个回答

所属标签

相似技术帖

官网相关资源

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