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

【实测教程】STM32CubeMX研究串口通信(RS485)

[复制链接]
STMCU小助手 发布时间:2023-1-14 17:49
一、开发板平台简介:
- s0 r3 f) {, k2 R3 Q1、开发板资源简介

$ p3 M6 J5 i+ u- v* b(1)开发板主芯片型号:STM32L431RCT6' h: D: i+ ]" U. ?% K. O1 k
(2)开发板主芯片封装:LQFP-64_10x10x05P/ U! `3 H( q: K$ q6 C$ n" g
(3)开发板主芯片内核:ARM® Cortex®-M4, K' J- I# O9 a8 T8 ~" R! r
(4)开发板主芯片主频:80MHz9 C7 k- t( ^) a8 h5 w
(5)开发板主芯片Flash大小:256KB% x3 Z/ R- B7 _/ ?; B: ]  p& s( N
(6)开发板主芯片RAM大小:64KB1 i+ O! c8 I+ ^% R) W8 Z
(7)其他外设:请参考芯片手册2 J& Y7 H  _5 X/ y# g; a

5 d" ^; X2 D5 [) x$ Z% J
bb91345227434ee7a43a34bf3fe366e6.png
0 c" |/ A7 `5 `) r​1 F# n* Q/ c6 b% L4 o
929c0cce04aa4115a8623703982bf3e1.png
  {4 n0 R1 ]3 W1 L0 M

+ R% Q: h2 N. k4 X2、串口简介
6 u8 v% j$ {2 Y6 e5 ]         串口全称为串行通讯接口,即数据在通信线上一次传输一位,按先后一定顺序传输。我们通常所说的单片机串口准确来说应该是串行异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART),使用TTL电平,串口需要RXD、TXD、GND三根线进行通信。3 c. M# N- E! s; {: f( S4 k" j' Z
8 ?  Q7 F5 a  U4 j- b" [* i
        (1)我们选用的STM32L431RCT6开发板串口1已通过USB转TLL串口芯片CH340G引出,使用时,只需要用公对公USB线连接电脑即可(注意也得需要安装CH340G驱动),后期验证试验也使用该串口1进行。
* y0 s3 g) E2 R; d* [: T. N( W4 q! _
6 R2 v2 K' f6 S9 \% F3 V$ Z        (2)开发板上的其他串口已通过排针引出,为TTL电平,通信的时候需要注意选择对应的电平模块,如USB转TTL串口模块等。$ J0 g! ^6 A1 A7 ^& f. }

  W& {( G4 k# J
% L1 q2 G2 ~+ Y2 F+ B
  二、新建工程
5 m3 T7 A2 N( b# r! G1、新建STM32CubeMX基础工程
$ C) z, l$ F% j6 j8 K
(1)打开STM32CubeMX,点击“File”-->"New Project"​6 q  u  n! C$ v" Q( Z/ y
$ C9 z" j) h3 a. F; v
2399170347904e959c855fefd5877f84.png
( V) s" a( Q- z! u7 ^6 d/ a9 ?! `' r. y$ U$ e- ~0 j6 C% G
(2)等待打开主芯片选项界面(大约1分钟时间)。
* {9 V" b3 K, b" b) G1 `
' H& J$ }/ M/ ]" \- ^8 ~% {% M
d74d2fdc60c9440483e2b7cf8d928e7f.png ( w; ]7 ~) M% ~1 O$ }& F5 k- d
​2 x2 C6 x- `& e, e
(3)昨天搜索框中输入(或选择)所需的主芯片型号(因为我们用的是STM32L431RCT6开发板,所以此处现在STM32L431RC),然后在右下角选择STM32L431RCTx(因为开发板主芯片是STM32L431RCT6),左键双击即可打开新建的项目。
: ?1 Q6 D; N/ v/ U' h2 p$ {# m. Q& ?, e1 U5 \0 L4 \
7b80345238d74bea82ce70e1a348f7b4.png
' E9 ^' C" y. \5 }! J4 |' }​
( b$ ?  o7 D: y/ g! `8 ~: \(4)选择时钟源。9 q, O( t3 b) i7 S& J
(1)因为开发板上有8M外部时钟,此处选择外部高速时钟(HSE)。
1 f5 z+ M: u. D" O: B& N6 D: d) N1 |2 Y& m- J8 n
(2)因为我们没有用到外部低速时钟(LSE),此处不做处理。0 B( @3 Q0 o0 ]% W

7 l' b* Q# X, l* N! R
72119b971f62410fa8344f7f9fb9f389.png
1 w! d+ @* |8 q$ }* N! c​! Y0 y+ g( {: C* m/ K$ f  C3 P% u7 @
2、配置GPIO控制LED+ V7 n5 q3 v2 s4 P5 ^! B
备注:LED灯用来指示系统是否正常工作。
5 P4 p7 n  w4 s, J4 O. _5 S0 c(1)查STM32L431RCT6开发板原理图得LED1控制引脚为PC0,则配置GPIO的引脚PC0。
' r* m7 ?6 L1 x5 r/ @: |5 u, U鼠标左键点击PC0,选择“GPIO_Output”,表示设置该引脚为输出模式。
! {3 Q  Z/ u# S& n. O3 b1 \
' f/ A! _/ y& @5 p& s$ S& ?  x4 N
492907c1e71149819adbaee4516a2af4.png : X  F! s/ B: J, G) q  \
​
) C4 F9 C9 H+ z+ C(2)根据自己的需求配置GPIO的参数,如输出方式、输出频率、上拉下拉等。因为GPIO控制LED的要求比较低,此处采用默认参数即可,不用修改。​
2 ^1 K  ]2 }, H, y: c/ U0 k4 D7 \) W- `' L2 ?. h2 E0 d
38ff4b80e1c5495ba3076a5158fd91fa.png ' [* u8 C$ `) v  M6 J* _! }0 s
9 A) g( S- p( A) P
3、设置串口1参数
3 V! u: i: a) {4 u9 p/ {4 ~1、查原理图得知,串口2使用STM32L431RCT6引脚为PA2-USART2_TX,PA3-USART2_RX,引脚设置如下:
$ z, ]- a# \* a& f. o (1)序号1用来设置串口收发引脚的选择。" D: v% V+ q" Q; n' x
(2)序号2-3-4-5-6设置串口参数,如波特率115200、8位、NONE无奇偶校验等。; L7 t5 U  F  k
" u( M, E, w8 I
2、设置NVIC settings 使能接收中断
" \: u- {! e2 y. J5 M( v& v8 Q$ X
. O8 S! d1 J; l7 w
f9d7783b08304465815834f4d2095571.png
* b( m; \" }8 ]- {- W3 W​
2 V/ K6 ]* A) V5 n$ Y4 V$ }8 ~0 f# K' C0 H4、串口DMA设置
7 ~4 b+ W  |; S9 U1 E
​% d/ J' p# [4 Q
6d26b13dd9d34039a2b426ca47680f8c.png 4 r, _9 t' |' M

3 R2 E5 M0 R, g0 `& Z* b7 [4 L) p% l (1)根据DMA1通道预览可以得出,我们用的串口1的TX、RX分别为通道4、通道5:! A" b' g! k" `1 y9 U
点击DMASettings 点击 Add 添加通道) L& ?3 S3 X2 a4 h$ C# c
选择USART_RX USART_TX 传输速率设置为中速
4 ?4 ~  \& S9 I1 G9 ]$ \( R. vDMA传输模式为正常模式,即发送一次就结束。
! d8 }( p" y+ N+ |+ @, r6 iDMA内存地址自增,每次增加一个Byte(字节)
# m. O2 L9 b7 x; O- l9 Y, {​7 A# Y8 m- x' B9 Z" O5 {
976712e0494a4482bf65c69fc09fcabd.png   L" u( t: A( t4 \
% Q2 P7 x8 A1 j( B
(2)DMA相关参数解析6 |3 k* h1 @, [" T7 _

5 ?* i+ ?  B& iDirction : DMA传输方向有四类
# H4 H2 {3 p4 y+ r6 l( w2 w外设到内存 Peripheral To Memory) W& K5 J. E: M% J
内存到外设 Memory To Peripheral6 u& r  T! F% Q! S6 `
内存到内存 Memory To Memory
1 a9 ~0 z! x- n2 p3 L外设到外设 Peripheral To Peripheral
( t0 M# Z1 A3 O- S
Priority: DMA通信传输速度有四类

/ o1 J$ I6 r0 D/ c5 g. u3 j最高优先级 Very Hight
4 X( p9 h0 v' F* `6 g0 Y高优先级 Hight
" T! w4 }. n: ?* s: B中等优先级 Medium* l: U: i) n- j6 p4 Y
低优先级;Low
2 [& Q$ |( M6 y  x5 A. a2 s
7 m' T  S$ ]" P2 C) K: R5 [/ l: h
Mode:DMA传输模式有两类

+ D$ n  X% U" t4 B6 a% s/ H% ?! s3 L
9021c11fed3e4c1885477e062b846258.png
. F! G" v3 ~& g0 U7 _- u​2 y/ I1 P5 t0 m2 h
Normal正常模式:当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次。" l7 X* H" D/ L9 |  w
Circle循环模式:传输完成后又重新开始继续传输,不断循环永不停止。* g" _; a1 J  `# ^" y

8 L. ~% Z# \& S% ^$ v
Increment Address-DMA指针递增设置:! B" c+ C: y" @2 Z

) e+ O! M# A4 ?) @3 ^" U
2b1a952d6514444e9dbb019a9ae88c42.png $ b  z, l4 p* q8 v0 Z" d/ T

8 [9 k7 _4 U- y 5、配置项目工程参数  d5 ?, d( c- c: J* d# T
(1)配置时钟树,用于系统内部时钟,以及各个外设时钟等。此处选择外部8M晶振作为主时钟频率,内部最大倍频80MHz。" W$ u( H$ j* `3 B

& u1 i$ }9 ^; W$ o$ S
2ce1933c10484d819234682f4abc0228.png
8 i: E4 I" v7 {- o( ?​
5 p$ h9 W  _5 w5 J' U- _) ~(2)完成配置工程。
# r0 H$ I4 r$ h- `: \
; v& X1 n* j* `3 `备注:需要注意代码生成过程中的继承关系,如图所示:需要保留开发者自己编写的代码时,请根据配置设置,不然生成代码后会删除自己编写的代码(从这个方面也可以看出开发者备份自己的代码是多么的重要。)# `0 ]7 w( _4 ~- |

$ \4 c) ]$ c! e4 G
efdb616174f54925b6eac31109f227b5.png
+ B- L: x* X0 d5 ]0 T5 L' |+ a$ z​( o; q8 J4 u3 I* M& D
41c3f2716e4e4eda8f62fa3a1d871322.png 1 e1 n) r; }% {$ o  @

, r$ x; [2 p& L(3)生成代码。
$ T! s9 q3 V: y2 l  P% I; A: l" h
3 W" b4 a1 L( O; A7 d' z# x+ r
8eaa7d0babea40ee93f158481a6ee471.png
8 U1 _& a& [$ ]5 l; G. J​1 U& @9 G. W5 ]% n; _& u$ |
三、在KEIL 5中编写代码
1 ]5 C5 ~. F- `6 C+ _1、使用KEIL 5(MDK)打开项目工程文件
; T6 b3 L1 X5 o- N
(1)找到刚才新建工程的存储路径,安装项目名称,打开项目工程。
( T8 Y6 i  [; Z) n; ?3 t. Y7 r
" Q7 z2 t( k  w9 }
9837b01954cc4d3ba3e25073f31b30b5.png
1 ^  x9 W* ~3 l7 B/ |​
" \0 R3 N& O' U  n8 y  j$ {# c2、添加LED指示灯作为系统提示
/ @& q- G" B  g' X添加每隔500ms,LED1闪烁一次的系统提示,用于提示程序运行正常。
0 u. n) \9 D2 _$ b6 [7 ?6 x
( Y8 m/ X9 i; D* }
6ab72ceaeb7a41af833842fe5ba6f34d.png
* t* M% J! ]) ~​
3 S" D# [# ~4 ?% F3、添加HAL库UART  DMA 发送函数代码
4 i' s$ i6 L9 A4 S9 @(1)STM32 HAL函数库的串口DMA相关函数如下:
3 f/ c; Z( p) P; I2 [; B/ ?6 w
  1. HAL_UART_Transmit();串口发送数据,使用超时管理机制! h. w& U! U6 i+ ^; Q( ?
  2. HAL_UART_Receive();串口接收数据,使用超时管理机制
    : ?% q( q+ N/ i' [5 m0 s
  3. HAL_UART_Transmit_IT();串口中断模式发送/ x* _. z4 Z- M4 }& F1 P9 W! d
  4. HAL_UART_Receive_IT();串口中断模式接收1 h1 Q! E( L2 U9 l
  5. HAL_UART_Transmit_DMA();串口DMA模式发送5 J* _) w5 P2 S0 w: V
  6. HAL_UART_Transmit_DMA();串口DMA模式接收9 e1 E3 Y! s7 {- b6 M
  7. HAL_UART_DMAPause() 暂停串口DMA
    7 U& V3 o0 R' T% |& Q
  8. HAL_UART_DMAResume(); 恢复串口DMA
    . ~1 O2 h7 m9 j  x8 D) ?; j  z
  9. HAL_UART_DMAStop(); 结束串口DMA
复制代码
4 u5 v9 i8 A: H# p. x3 Z$ q
(2)添加串口DMA发送log代码:
# `1 r- E/ v5 T7 _8 N0 d1 z( ]
  1. /* USER CODE BEGIN WHILE */
    % I2 Q5 n& J& [- c/ L
  2.   while (1)% N( O1 `/ I5 @6 I; I. S7 b9 r# s
  3.   {
    4 \- D0 ?' Z) ]8 u: {. q3 X
  4.     /* USER CODE END WHILE */
    ) b2 E; v( Y) I, b4 x

  5. ; z5 d% v) Z: z" v) E
  6.     /* USER CODE BEGIN 3 */9 b0 O8 W: _# C, C4 q7 M1 Y
  7.             HAL_Delay(500);
    5 O$ h& i% N; Z# _* M, a; ]# \
  8.                 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);//控制LED1闪烁) q6 [/ t4 S3 A! f" Z* K
  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"));//发送提示  - }" F5 i  f% j+ _! y! @) F) k
  10.         }. _( p, w# M$ O! E
  11.   /* USER CODE END 3 */
复制代码
( {8 I3 Y0 I9 X0 j- T$ q) G* n
4、添加HAL库UART  DMA 接收函数代码; m0 x' @$ b5 X9 {+ M  s4 N5 |6 }/ d
(1)DMA接收设置前铺垫知识点:
. o" O6 j6 B! I% ?7 \! Q- `        STM32的IDLE的中断产生条件:在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断停止。6 U3 P+ o7 c0 I* J
& i" b: y0 G. x# n: _; _
(2)初始化中断接收配置:
) i2 h7 B" c' Xuart.c添加代码如下:
2 S& U% P# g% u; Y5 V5 l

  1. / {9 l- S7 D8 M; P* y0 K! B
  2. /* USER CODE BEGIN 0 */
    ; D, S6 h6 T0 J' y' @1 G. J9 S+ K
  3. # J) `) [6 r  C; ^8 ?" {
  4. volatile uint8_t rx_len=0;                        //接收一帧数据的长度
    ; s  r6 f7 y0 l' c/ @  }- M3 L$ A
  5. volatile uint8_t recv_end_flag;            //接收一帧数据结束的标志位
    2 T1 |  s% z8 N' b" @+ B
  6. uint8_t rx_buffer[100]={0};                        //接收一帧数据的数组大小3 V4 k2 C! w6 w+ e# H% a% j
  7. /* USER CODE END 0 */
复制代码
  1. /* USART1 init function */* p2 V; `. w7 y
  2. 2 z/ J% A$ [4 @: n
  3. void MX_USART1_UART_Init(void)
    ) \3 X6 w5 T2 `
  4. {7 @1 V1 u) x. z4 p$ ]3 P, K6 ?; _( p
  5. * z3 V8 z! B6 K7 i' E7 G* k
  6.   huart1.Instance = USART1;
    7 W% O' C$ l3 H: ^' \5 M
  7.   huart1.Init.BaudRate = 115200;4 W6 n- [( {+ Z9 J# d. m! s
  8.   huart1.Init.WordLength = UART_WORDLENGTH_8B;
    + |- N7 H/ @+ f
  9.   huart1.Init.StopBits = UART_STOPBITS_1;/ u( j3 o% Q$ \" N$ [
  10.   huart1.Init.Parity = UART_PARITY_NONE;3 W# h1 T7 `" m7 l- X0 _* B
  11.   huart1.Init.Mode = UART_MODE_TX_RX;
    8 N. I0 t0 V- s
  12.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    5 X! M) Q/ m- x3 A) h" S$ P9 a) ^
  13.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;' N4 D8 N2 h+ b! I
  14.   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;5 X# |( Q5 M" O1 q4 ^0 l7 D5 x
  15.   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    7 y3 j1 t3 W, E; c" S. a& e
  16.   if (HAL_UART_Init(&huart1) != HAL_OK)
    # ~1 G: Y" y6 g- Q' O+ b
  17.   {6 t/ [+ [5 P' j
  18.     Error_Handler();+ P# m: R1 v% i8 f4 D- K
  19.   }
    & {  A1 \5 y1 @4 {
  20.         /* USER CODE BEGIN 2 */3 o+ P1 k1 U. M
  21.         5 T& @+ @) H2 y  D( `
  22.                 __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);                     //使能IDLE中断
    ! B! D/ T9 i6 N6 P
  23.                 HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);            //DMA接收函数
    # H5 W& A+ N- H$ n
  24. ! i/ X* R  z, D6 J7 z8 @, p
  25.         /* USER CODE END 2 */9 K+ \: u3 Z, Y3 U+ l" y, N
  26.         ( k# n) W0 W+ D2 P. d7 J  R$ N& U6 q

  27. " f  f, L9 _; `, _! q
  28. }
复制代码

. C2 h( }1 w. y; l# r; E) O% p

+ ~/ O+ W' X# H* w0 T: z; _% buart.h添加代码如下:
) Z: ^, [8 X& f. b
  1. /* USER CODE BEGIN Private defines */
    - c+ Y$ n3 D9 y7 I3 c
  2. extern UART_HandleTypeDef huart1;$ X) e7 b' B7 N, b2 L
  3. extern DMA_HandleTypeDef hdma_usart1_rx;
    + O9 R  }* H# }4 `
  4. extern DMA_HandleTypeDef hdma_usart1_tx;, T& T& u. R& {, j/ K! h+ Z2 c+ ?! S/ X
  5. 2 k- w/ q8 S8 @1 h4 Q) t9 g
  6. #define BUFFER_SIZE  100  
    7 H$ V4 H5 g4 r4 t8 n) `
  7. extern  volatile uint8_t rx_len ;                                  //接收数据的长度
    / i2 D  y0 ]) i  C3 {7 [1 k8 P: ?4 f
  8. extern volatile uint8_t recv_end_flag;                     //接收数据完成标志位
    7 ^( R1 u1 K" n' T& f
  9. extern uint8_t rx_buffer[100];                                  //接收数据存放数组
    4 _) I/ N$ [/ G) u; ?
  10. ! o9 b, C! ~" c) \
  11. /* USER CODE END Private defines */
复制代码
8 s' [: D" H/ l/ f
main.c添加代码接收函数如下:4 t- j4 y5 N! t# O% {

5 D* V" j( M2 k0 z
  1. /*******************************************- J% Y$ O( V6 f: e7 b
  2. * 函 数 名: DMA_Usart1_Read
    3 r% P  i6 j+ _* \. P+ n
  3. * 功能说明: 串口接收功能函数7 K4 s* g' E; v( i
  4. * 形  参: Data,len
    # m8 T; {+ V3 {! Z" Q' k
  5. * 返 回 值: 无
    % ~, |2 w! u( U2 r) Q
  6. ********************************************/
    # ^& B6 `" h" I7 n: h
  7. void DMA_Usart_Read(uint8_t *Data,uint8_t len). q/ s7 d; k# I+ E5 p
  8. {                               
    ( b7 ]& U) p3 I) C" u$ j
  9.                 HAL_UART_Receive_DMA(&huart2,Data,len);                                 //重新打开DMA接收
    & r" z" B. B  U" P3 x
  10. }9 Y7 d7 O- Y' |2 p1 o/ d9 K
  11. /* USER CODE END 0 */
复制代码
8 t) x5 p7 J" F6 c5 b) q1 g1 _
5、添加收发处理函数7 t% L8 B& ]  M" d- S7 @
(1)main.c  while(1)循环中添加收发处理代码如下:$ H! I# f6 e/ b3 f; V- m4 |

. g- z/ z3 W& n/ [: K
  1. /* Infinite loop */
    5 C; L. P% d' w/ e3 d4 C. a0 J* ?  p
  2.   /* USER CODE BEGIN WHILE */1 C+ m1 s; a5 \- a
  3.   while (1)  m/ P# O6 I, Y  I* P* Q  h
  4.   {
    0 @) B3 T# y- n
  5.     /* USER CODE END WHILE */
    2 r1 `6 c8 e( V* V( ^: X% ?# o/ S' H

  6. 2 E: b+ G$ }$ G3 Y
  7.     /* USER CODE BEGIN 3 */! q& i/ ^: b* v0 M
  8.                                 if(recv_end_flag == 1)                                                                                                                                            //接收完成标志,如果串口有数据接收,则执行该部分
    " j3 y" ~4 g1 \
  9.                           {1 V+ O. d6 n# ?3 t
  10.                                          DMA_Usart_Send(rx_buffer, rx_len);
    + C" l1 b( A1 O4 L
  11.                                          DMA_Usart_Send((uint8_t *)"\r\n", sizeof((uint8_t *)"\r\n"));        4 f, n. a1 i6 A6 k) x
  12.                                          rx_len = 0;                                                                                                                                                                     //清除计数
    # }' B' t: d3 i2 L( g
  13.                              recv_end_flag = 0;                                                                                                                                                         //清除接收结束标志
    ( ^1 E. p4 h$ N2 u& Z
  14.                                    memset(rx_buffer,0,rx_len);
    - M( E/ A, T4 x5 a; P9 z
  15.                           }8 u6 V7 `% i3 \
  16.                                 else                                                                                                                                                                                                                                //如果外部没有数据,则执行该部分
    & D! V: o4 ~* e: p7 R1 d+ c
  17.                                 {; N- k% E' V# X1 s% K
  18.                                                
    5 V; t/ f7 {( X; n* [" j& D
  19.                                                 DMA_Usart_Send((uint8_t *)"hello world,this RS485 send...\r\n", sizeof("hello world,this RS485 send...\r\n"));  t% g3 n# I+ ]
  20.                                                 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);                                                                                //控制LED1闪烁2 G& N9 `8 b$ `, q
  21.                                                 HAL_Delay(500);
    1 T/ |: @! \7 \' _. J4 v
  22.                                 }0 ^9 o' v- U+ A/ n! n8 }+ `
  23.                           HAL_UART_Receive_DMA(&huart2,rx_buffer,BUFFER_SIZE);       //重新打开DMA接收                                % t* E+ S4 E* N% z* N% b- M3 J+ u& A
  24.         }& w) j' z4 v1 ~
  25.   /* USER CODE END 3 */
复制代码
4 ^( u  N! M/ }" I6 R
(2)stm32f1xx_it.c中添加接收中断处理代码如下:1 ^# l9 K5 F2 P; g* ^
  1. /**$ j  L0 I' B+ B9 j6 T  S  |# {
  2.   * @brief This function handles USART2 global interrupt.
    5 @  c: c! |* f# T- B
  3.   */
    5 p3 Q: b6 h& s% q7 h8 }
  4. void USART2_IRQHandler(void)
    $ |% j8 |1 t. U; v+ S/ M8 G
  5. {
    2 V5 D0 h; ]' G, w6 f
  6.   /* USER CODE BEGIN USART2_IRQn 0 */$ c, }0 ]0 z" Q+ ~* O1 }" {) H
  7.         uint32_t tmp_flag = 0;' f/ n4 {  v* I. {1 v# p2 }
  8.         uint32_t temp;9 E8 L# W5 a- g* T# U# `8 s
  9.         tmp_flag =__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE); //获取IDLE标志位
    , p& U) ^9 A+ v3 w; W, W
  10.         if((tmp_flag != RESET))                                //idle标志被置位
    % z* D, G8 k' b" ?
  11.         {
    6 o! w, N6 q" c3 E" N' T& j8 {
  12.                 __HAL_UART_CLEAR_IDLEFLAG(&huart2);                  //清除标志位
    " C7 F' X! u( @. i
  13.                 HAL_UART_DMAStop(&huart2);     5 X' l4 @# M+ p1 ]6 }" u9 ^
  14.                 temp  =  __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);     // 获取DMA中未传输的数据个数   
    ' p2 e! R, |& R( l
  15.                 rx_len =  BUFFER_SIZE - temp;                                             //总计数减去未传输的数据个数,得到已经接收的数据个数3 r8 [# r. h4 p) R2 s
  16.                 recv_end_flag = 1;                                         // 接受完成标志位置1       
    " p4 L  t6 X- K8 W
  17.          }3 W: M3 i7 b; m9 V# y9 L" j+ w/ {8 x
  18.   /* USER CODE END USART2_IRQn 0 */6 }- Z% l' f. Q! r9 u0 y
  19.   HAL_UART_IRQHandler(&huart2);
    9 G$ R8 Q$ y0 ]5 I9 p
  20.   /* USER CODE BEGIN USART2_IRQn 1 */8 u! W+ Q4 U' ?4 L

  21. 5 s- {8 L0 v" A0 i; C1 S
  22.   /* USER CODE END USART2_IRQn 1 */: ], [& L: E$ g
  23. }
复制代码
. h% c& X/ q$ P
(3)至此,串口DMA收发数据需要添加的代码已经完成。
  m: E  b  A, N+ |/ z: J+ Y* G. S
* e' B& I$ s7 N: r8 l4 s 5、设置编程仿真下载模式
  ~+ @1 |' a( f# V! y/ D! Z6 O(1)选择Options for target ...>>Debug>>J-Link/J-JTRACE Cortex,点击Settings>>选择Port(SW),可以看到搜索成功SW Device,表示芯片可用,可以下载。
$ S& _: _# e/ V  V
8 z3 d3 u$ D( t' u8 [$ N
edefb6b9a2a14be3b1221ad6d5c7a8a2.png 2 H# n5 l: J' a8 d- T9 z2 y- L0 U

; f) e0 b; h8 W7 l3 i  k& C(2)点击编译,完成后提示“0 error(s),0 warning(s)”。
; ]& m" J! Z! r
( q( ]2 F# M" N& T
f0ed816a3ed14487bf9e857c317fc99b.png
& M0 D; d3 b1 g! _. j; n; J

' B- F* q% b2 M* b4 g(3)点击Download(或者快捷键F8),即可下载程序。
/ h& T0 }5 z0 N* u; v4 _9 f6 U# b3 v* j4 _
ba221842d5db40808aa129dd83c593d0.png " o8 w, g& @: O5 v. Z4 m' Y0 U
​
- K3 J  u2 f2 e) |, P( W9 d(3) 如果下载程序后,没有看到LED1灯闪烁,可以按下述方式设置一下(Reset and run表示下载后自动复位和重启运行)。或者重新彻底断电再次上电(或按开发板的Reset按键复位MCU即可)。
  _% l$ V, b" t% {0 c+ a; q5 A* @& z3 q5 L, p* Y4 |4 |# x+ U
9f8aa1a4e8f04041bcf5cb183facd100.png : a. Z" |/ J6 _/ g) @; m
​
( j) K5 S( }% l1 O4、查看串口发送函数打印log效果
% }) p& x6 w0 B+ i4 C5 T(1)设置串口助手参数为:115200、NONE、8、 1(和代码中串口初始化参数一致)。
: N. b. o7 ^' [# m2 `7 L(2)设置成功后,就可以看到串口打印的效果。如果串口助手没有发送给MCU的数据,则MCU每隔500ms闪烁LED1指示灯一次,且串口输出一个log。; n$ N  G: S6 A5 P& H, L
(3)如果串口助手往MCU发送数据,MCU把接收到的数据发送到串口助手进行打印显示。
* \5 X. v* a6 I6 T. B% s+ w4 O3 \0 K4 F3 G" ^9 f; ~
8f65172eef06499987e27edddf5320f2.png ( B6 C" _  s; M; |. a3 N1 z0 S7 |, o

6 d6 b- W9 `) l6 m/ \————————————————
/ j, H; a- G& Z. `1 C( _5 d9 H版权声明:智能小屋ZYXC
; @7 R& L  j1 \& c  j+ A/ q( i& G9 u6 V3 _+ Z+ @
, E$ |! D% e. T' }
赞 收藏 1 评论0 发布时间:2023-1-14 17:49

举报

0个回答

所属标签

相似技术帖

官网相关资源

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