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

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

[复制链接]
STMCU小助手 发布时间:2023-1-14 17:49
一、开发板平台简介:
# G9 D6 x  r+ ?4 j$ L1、开发板资源简介
8 \% A0 v0 l9 N
(1)开发板主芯片型号:STM32L431RCT61 H; }6 ^/ Q; [. G, W+ b7 g: p
(2)开发板主芯片封装:LQFP-64_10x10x05P  I( R! D6 R! r2 J8 i* `
(3)开发板主芯片内核:ARM® Cortex®-M4
9 ~$ L3 g6 m4 S$ n(4)开发板主芯片主频:80MHz
0 p+ |' d& w4 a9 n9 ?6 ]* z- @; o* h8 x# d(5)开发板主芯片Flash大小:256KB
4 r: m- R, I3 q) J: X(6)开发板主芯片RAM大小:64KB% P( D$ w5 _2 k  A8 i
(7)其他外设:请参考芯片手册/ d: j5 N" L+ j: ]7 x  T1 `# \; Y
/ L- g+ k. O. }( P4 w$ A, n- e7 s
bb91345227434ee7a43a34bf3fe366e6.png $ F9 G; S* Y' P0 @+ W% U0 i
3 a6 O9 H5 h( \; s& D
929c0cce04aa4115a8623703982bf3e1.png
9 U  }# }1 \! X# u
7 g5 d- w/ P) w9 ~
2、串口简介
' J1 M: S% T2 Y+ W/ ^         串口全称为串行通讯接口,即数据在通信线上一次传输一位,按先后一定顺序传输。我们通常所说的单片机串口准确来说应该是串行异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART),使用TTL电平,串口需要RXD、TXD、GND三根线进行通信。3 W- h/ y  a# v
' }1 g6 M7 `1 ^& p. f' y
        (1)我们选用的STM32L431RCT6开发板串口1已通过USB转TLL串口芯片CH340G引出,使用时,只需要用公对公USB线连接电脑即可(注意也得需要安装CH340G驱动),后期验证试验也使用该串口1进行。
" _1 T% ?3 q, I  y- _
9 x/ a( x/ M) n' a, `3 ?& x! J0 S# T        (2)开发板上的其他串口已通过排针引出,为TTL电平,通信的时候需要注意选择对应的电平模块,如USB转TTL串口模块等。, G0 l; H* Y% @( c4 X. C
) G3 |, L  q/ |+ Z% p. i

; a  [. p( F: m8 H( M6 W1 K  二、新建工程
1 h) A5 @: r  d! a1、新建STM32CubeMX基础工程
. o1 K5 V0 N9 Q
(1)打开STM32CubeMX,点击“File”-->"New Project"​
8 K; C5 I+ u# J$ Q; V* w8 v1 v+ z6 i+ j" C) d, e
2399170347904e959c855fefd5877f84.png
- c' I2 I( |( P: H' a! n7 j9 |/ _& A* w) {! i5 Y
(2)等待打开主芯片选项界面(大约1分钟时间)。  J, @% o$ k! T2 d4 P
+ p& M& a, z! B, B& e( D3 K
d74d2fdc60c9440483e2b7cf8d928e7f.png + h! Y3 I4 }0 b6 M# B4 [  X" u8 y3 W
! ?* |1 j4 j0 C3 [5 |2 p
(3)昨天搜索框中输入(或选择)所需的主芯片型号(因为我们用的是STM32L431RCT6开发板,所以此处现在STM32L431RC),然后在右下角选择STM32L431RCTx(因为开发板主芯片是STM32L431RCT6),左键双击即可打开新建的项目。
3 x2 z& i" k0 a% p5 X& V, r6 h7 v' l! d. B+ \$ V5 }6 M" l4 x' f
7b80345238d74bea82ce70e1a348f7b4.png   K- s: l% C2 U' y0 }5 G5 ]4 }
+ K! _) Y- |4 r6 a% a! `& T# u: x1 l$ d
(4)选择时钟源。  [% N$ l: F+ f6 |$ O
(1)因为开发板上有8M外部时钟,此处选择外部高速时钟(HSE)。
3 z8 E7 c/ z) c2 H6 N0 z: d3 N! K' ^8 P1 u
(2)因为我们没有用到外部低速时钟(LSE),此处不做处理。0 v- w' U( [3 I; I2 h* h& s
8 b3 W' {9 d" @
72119b971f62410fa8344f7f9fb9f389.png
. a1 R% D9 n$ h6 E; D2 c. V
4 b) J  t- u8 ?  [# W$ u2、配置GPIO控制LED
8 I" a% ^# A/ M( e备注:LED灯用来指示系统是否正常工作。, n& z3 ?- E' F+ q4 U) e' X! A
(1)查STM32L431RCT6开发板原理图得LED1控制引脚为PC0,则配置GPIO的引脚PC0。/ y$ J; f3 N6 a
鼠标左键点击PC0,选择“GPIO_Output”,表示设置该引脚为输出模式。3 {* W5 G1 Z& ]# e

3 q  u7 [. l% t8 S( ~: i7 A
492907c1e71149819adbaee4516a2af4.png / s1 i* O6 U& J7 N2 o- H" d
  Z! h1 T( q7 k) X2 N" c
(2)根据自己的需求配置GPIO的参数,如输出方式、输出频率、上拉下拉等。因为GPIO控制LED的要求比较低,此处采用默认参数即可,不用修改。​
* |& T1 a/ ^6 M7 _% }5 h- t' U; ^. J( y# b8 ^! B
38ff4b80e1c5495ba3076a5158fd91fa.png
, Y+ L2 w8 J4 x

8 `8 z5 ]  T- v0 d3、设置串口1参数
( p- ]# G( Z. }$ r9 ?1、查原理图得知,串口2使用STM32L431RCT6引脚为PA2-USART2_TX,PA3-USART2_RX,引脚设置如下:' q: Y8 K- p& C) g9 \
(1)序号1用来设置串口收发引脚的选择。
# H* z1 {* c: ]: X+ D(2)序号2-3-4-5-6设置串口参数,如波特率115200、8位、NONE无奇偶校验等。
" u% L3 x- G+ X2 O* K3 X# u2 E" |% S! m+ E9 P; U, h
2、设置NVIC settings 使能接收中断
, t2 w3 _8 v  D% H* H6 O, l2 S! B) c4 }) J" h$ ]: o
f9d7783b08304465815834f4d2095571.png * F% S- z4 s" ~9 `1 O% L' h
" w: Z! T/ |0 y, q; @
4、串口DMA设置
& S4 k. e5 x) e; _7 @' a6 d
; e$ M9 _% |7 Z' g: \, M8 C
6d26b13dd9d34039a2b426ca47680f8c.png / C/ ]- o! V  K# g/ s5 C" q
0 \/ Y; ~( y" _8 \& a, g
(1)根据DMA1通道预览可以得出,我们用的串口1的TX、RX分别为通道4、通道5:
6 P3 Q; S( s4 F- d2 H点击DMASettings 点击 Add 添加通道
) i+ }1 z( g& b1 |选择USART_RX USART_TX 传输速率设置为中速
8 b5 t) x9 K4 U6 z6 GDMA传输模式为正常模式,即发送一次就结束。
! u% `7 }" o) |1 `DMA内存地址自增,每次增加一个Byte(字节)
$ z; r* z$ ?# _2 P9 \6 i7 f  E) ~1 n
976712e0494a4482bf65c69fc09fcabd.png
! p! {3 V+ K& ?* t% G

( z7 t: b1 R2 W: N+ s9 \0 I- T% h(2)DMA相关参数解析) h' Y* e; P! P+ p- D- f' }
; b- p& f7 h7 O8 r" V3 }8 V, E/ D
Dirction : DMA传输方向有四类8 Q" d; \2 H) c7 ]
外设到内存 Peripheral To Memory7 p5 u' {( g" h4 s& \( m5 e- d
内存到外设 Memory To Peripheral
" j3 |& u) S5 K6 B( M9 _4 M  c内存到内存 Memory To Memory
$ I9 J( m: s% L7 `' }* t外设到外设 Peripheral To Peripheral
4 w' v3 n% b5 t( u
Priority: DMA通信传输速度有四类
/ J4 X; Q1 h6 E1 r
最高优先级 Very Hight
; }2 |7 ^& i- g; U5 r5 L% h8 r+ J高优先级 Hight# y* g! `5 @* m+ D* f
中等优先级 Medium
. g3 y! c5 D0 S, m, o, l4 F8 i2 O低优先级;Low
/ n) G' o5 h3 V
. P$ u: b1 \3 l/ ]* C
Mode:DMA传输模式有两类

- I: L5 i' @& O( P. ]1 e9 Z# e' R4 ~  N
9021c11fed3e4c1885477e062b846258.png & ~; {" X4 A% E

, U, M3 _2 ~* N' d5 e) \0 l% X  t7 zNormal正常模式:当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次。5 W: p4 E/ M4 M' v) L
Circle循环模式:传输完成后又重新开始继续传输,不断循环永不停止。9 Z4 |/ W+ ^% t; ]( F: M
% w3 ?% O: G/ d' U
Increment Address-DMA指针递增设置:$ h! `, H8 s. L% x& R3 O
! F7 T6 I# E" i8 h2 m7 r) f
2b1a952d6514444e9dbb019a9ae88c42.png
6 M. ?% {- d! p. r7 ~7 h: z
2 W- M5 \( I5 v# e& S' M
5、配置项目工程参数5 s  P* T7 c- s" h4 |7 Y, |1 W1 `
(1)配置时钟树,用于系统内部时钟,以及各个外设时钟等。此处选择外部8M晶振作为主时钟频率,内部最大倍频80MHz。
( i2 }7 S+ X& i$ O) m- L& j; a8 {/ `+ m# ?8 G1 s' i" o4 E
2ce1933c10484d819234682f4abc0228.png
. Z3 ^- a6 A- M1 \4 L. f: v! H* Y5 r. T
(2)完成配置工程。
1 o. t+ Q5 V; W' {) X5 _; U7 Q; t/ ?" R' P. K% l+ A
备注:需要注意代码生成过程中的继承关系,如图所示:需要保留开发者自己编写的代码时,请根据配置设置,不然生成代码后会删除自己编写的代码(从这个方面也可以看出开发者备份自己的代码是多么的重要。)1 T- B: w" ]0 \$ W" w# s+ o+ w
( p. a5 v5 W' G, e, r+ M
efdb616174f54925b6eac31109f227b5.png 0 Y( P! y; H% v6 d. W; C

6 p3 c; |: c7 P6 Q* q& u# ^ 41c3f2716e4e4eda8f62fa3a1d871322.png
% }6 }  q% m) z. s% K/ F

" O" E" m  G) k  O( f(3)生成代码。
: B  c7 F' T3 \
; r8 J) f9 @  T. g( v+ u) ?5 W
8eaa7d0babea40ee93f158481a6ee471.png   l! I" C+ u$ ]" I- I* t' R

  D1 t: _* G' b' F. u 三、在KEIL 5中编写代码7 T7 e) _& j. l, Z* n" P
1、使用KEIL 5(MDK)打开项目工程文件
# h& r0 S/ b$ Z/ x5 @1 |# H
(1)找到刚才新建工程的存储路径,安装项目名称,打开项目工程。
! ~& @% t1 H* G. J( c3 e' T( O
1 a/ h, X* h5 ]+ }5 \
9837b01954cc4d3ba3e25073f31b30b5.png
7 q' [" N* l9 x+ K) {$ d, i1 D1 o# E) J- K1 [; b/ W
2、添加LED指示灯作为系统提示, O9 ~8 n9 C' b5 k5 E6 }3 f
添加每隔500ms,LED1闪烁一次的系统提示,用于提示程序运行正常。
7 U, y  k9 e7 N8 |& L& b
! h. x( \% h% C+ g& W& q" p, {
6ab72ceaeb7a41af833842fe5ba6f34d.png
! ]8 e# `% [5 C/ B3 @/ b. k
$ G  A, W; V$ h6 O! G7 p: U3、添加HAL库UART  DMA 发送函数代码
& V0 A9 u  z: h+ l" i3 l$ Q1 U(1)STM32 HAL函数库的串口DMA相关函数如下:
4 \0 v8 ^7 v6 f: v: w3 B3 r
  1. HAL_UART_Transmit();串口发送数据,使用超时管理机制: ^" z  [8 J2 Z, I
  2. HAL_UART_Receive();串口接收数据,使用超时管理机制
    2 Z8 j) D' p, f1 ^. \; _6 z4 b# x, [
  3. HAL_UART_Transmit_IT();串口中断模式发送
    3 }" p) u: ~! ]$ F* \, S
  4. HAL_UART_Receive_IT();串口中断模式接收9 n" P7 r- f4 G3 w& |  o* v+ G
  5. HAL_UART_Transmit_DMA();串口DMA模式发送. ^, `' C, M; K  Y
  6. HAL_UART_Transmit_DMA();串口DMA模式接收* o0 g+ P/ x6 G& d+ N" J1 ^+ {
  7. HAL_UART_DMAPause() 暂停串口DMA
    7 ^  z! k& u/ a% @3 s( |7 B
  8. HAL_UART_DMAResume(); 恢复串口DMA
    ' Q, q3 \8 D# ~/ O/ i* `5 Z# A
  9. HAL_UART_DMAStop(); 结束串口DMA
复制代码

; G# Y% ^/ ^4 t5 j6 O* t% n. p(2)添加串口DMA发送log代码:
( U* _$ b/ u3 T0 u+ h
  1. /* USER CODE BEGIN WHILE */1 G4 z0 e2 T- O  D  B0 d% B
  2.   while (1)9 _( f5 o) s7 ~' M7 h: ?
  3.   {9 p1 S( q- i3 i& u) f+ s6 L4 ]& Y2 @
  4.     /* USER CODE END WHILE */
    : O. n$ N4 B: V2 o" k, c% u
  5. 8 N4 @+ D" Y0 V7 n7 x% l
  6.     /* USER CODE BEGIN 3 */% R8 y% j4 ?0 l. f1 B
  7.             HAL_Delay(500);
    3 }1 O3 A1 W  f. w
  8.                 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);//控制LED1闪烁
    ) @, }- ~. Z& v4 s5 [5 q* T' J
  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"));//发送提示  
    $ g: X4 c) E* x4 w2 ~" u1 a4 ^8 d
  10.         }
      c# z: m! ?4 X6 t. @
  11.   /* USER CODE END 3 */
复制代码
1 m2 J1 _' ]2 Q# u$ {% V* P; q
4、添加HAL库UART  DMA 接收函数代码8 ?. e* `: \/ m
(1)DMA接收设置前铺垫知识点:, p/ M1 C" x% V! }* |# c
        STM32的IDLE的中断产生条件:在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断停止。( i# A( r6 Q( q: X- ?
7 |! j$ W7 j* I4 n
(2)初始化中断接收配置:  n. G6 [9 v; R9 s" t7 |
uart.c添加代码如下:7 k! m5 V& l( {9 J/ [. b4 Y6 O
  1. 0 B& p( ?8 n' a0 u1 l  e/ h4 s
  2. /* USER CODE BEGIN 0 */
    % w, b6 k( [0 g/ m! n
  3. * A  _6 L. V5 o
  4. volatile uint8_t rx_len=0;                        //接收一帧数据的长度% d- D. o2 ?1 N& H
  5. volatile uint8_t recv_end_flag;            //接收一帧数据结束的标志位3 {) _5 T( w- R
  6. uint8_t rx_buffer[100]={0};                        //接收一帧数据的数组大小2 |1 @; n3 {" y2 E  h* a) P
  7. /* USER CODE END 0 */
复制代码
  1. /* USART1 init function */
    * e+ P$ i. N% y& A: Z; |5 C

  2. + ^; S, p5 v, E
  3. void MX_USART1_UART_Init(void)
    9 g7 V$ L2 j* c4 |% D7 G+ Y
  4. {
    1 C# n' z9 I3 @  ^' m3 X

  5. % ]( ]  b3 ^/ o. X5 A. q' |
  6.   huart1.Instance = USART1;: e2 ]) V9 [% `1 n3 W7 ?
  7.   huart1.Init.BaudRate = 115200;
    * O6 B6 @7 u  P6 j' R
  8.   huart1.Init.WordLength = UART_WORDLENGTH_8B;
    % `* m: I8 l2 h3 @0 K
  9.   huart1.Init.StopBits = UART_STOPBITS_1;% @2 L& [4 A* T  W7 t. N
  10.   huart1.Init.Parity = UART_PARITY_NONE;" x1 C. z+ q# s# r' h" z0 D
  11.   huart1.Init.Mode = UART_MODE_TX_RX;
    / F. E1 |5 X9 K$ b5 K
  12.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    4 N$ Y" C4 g/ _; u
  13.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;% I( K# l% x' N- z
  14.   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;7 N3 m) l. u+ g+ ]' D% @! @4 i
  15.   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    ! ^; r; i( w: A/ [
  16.   if (HAL_UART_Init(&huart1) != HAL_OK)
    7 U  J$ T1 e; b7 j6 J  J' @
  17.   {
    9 f$ z( e; a% Z2 M
  18.     Error_Handler();# W4 W% \" y! @! N
  19.   }% J* V5 l* U! R) Y# J  N! d
  20.         /* USER CODE BEGIN 2 */( \; ~0 u1 V2 O
  21.         % ~1 n" d; H# }" O) {' r3 a7 Z
  22.                 __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);                     //使能IDLE中断/ H( U9 x6 P- f1 X
  23.                 HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);            //DMA接收函数! g3 R3 B" N! e7 `
  24. % X$ R- v  A8 |: R, M
  25.         /* USER CODE END 2 */7 T# R4 e* j( Z& R+ q' D4 t, Y
  26.         $ W: K4 h) |  w: J. Z1 r

  27. 2 ]% |6 p  S0 e) ~0 g8 ^
  28. }
复制代码
0 G, z$ B% n8 i8 B% [8 a0 i
* ~6 N* [7 U* _( J
uart.h添加代码如下:

! _2 X4 K( c, f
  1. /* USER CODE BEGIN Private defines */
    7 O) g" {) L+ H: x/ `0 S
  2. extern UART_HandleTypeDef huart1;/ m+ b2 r* V) e) O# v) v  f6 c
  3. extern DMA_HandleTypeDef hdma_usart1_rx;
    2 A# P$ V9 Y; d. u2 A% i
  4. extern DMA_HandleTypeDef hdma_usart1_tx;
    ; k7 @0 D( t5 {6 S$ S- R

  5. # f1 V2 R  T7 C- r0 ?) ~2 z! v
  6. #define BUFFER_SIZE  100  
    0 B' K4 J7 n6 e& O0 X" U; [; y# _
  7. extern  volatile uint8_t rx_len ;                                  //接收数据的长度
    ( K  S, @) l: `8 `" d) M
  8. extern volatile uint8_t recv_end_flag;                     //接收数据完成标志位6 g( z7 b: A$ ~2 J1 Y! U3 V7 Y
  9. extern uint8_t rx_buffer[100];                                  //接收数据存放数组  V  l' V6 x9 ^1 G: T

  10. & c" J: ]$ i/ m) q% Q
  11. /* USER CODE END Private defines */
复制代码
6 ~7 a$ F; O+ R6 l% W
main.c添加代码接收函数如下:% O" X- l" G; H% k
+ f5 d' ?0 @# ~# y& G7 Z
  1. /*******************************************+ Z/ t; J, d0 B& v# f) F- q  n- K
  2. * 函 数 名: DMA_Usart1_Read6 U7 i" V5 i( i$ o8 G% R4 x
  3. * 功能说明: 串口接收功能函数
    9 w% v" {4 H( k4 e& X
  4. * 形  参: Data,len1 s: n3 b3 O# ?1 W) G6 v! Z' h5 U
  5. * 返 回 值: 无
    1 b) c9 u7 S3 A/ A& i7 ^$ a
  6. ********************************************/, q" P' c2 D/ s* C
  7. void DMA_Usart_Read(uint8_t *Data,uint8_t len)
    , S5 D3 J6 ~* P4 D& G; \
  8. {                                1 z% i: ?' G( v/ B
  9.                 HAL_UART_Receive_DMA(&huart2,Data,len);                                 //重新打开DMA接收
    + g# X9 t) L: M& F" @3 w4 {) r
  10. }
    " Z5 q. @4 e6 D/ k. f0 ~/ n+ r
  11. /* USER CODE END 0 */
复制代码
) A6 c& s+ r  Q& L7 N0 d' A
5、添加收发处理函数
& {5 \. p; @& ~8 }(1)main.c  while(1)循环中添加收发处理代码如下:
6 x# b+ Y. @4 d* q
$ w& s! s  P: d) I( Z) k$ v5 x5 C5 g
  1. /* Infinite loop */1 J$ T6 U3 @5 {( C# E& H
  2.   /* USER CODE BEGIN WHILE */( [+ U# y. ]6 ~, v$ T8 q" ]
  3.   while (1)8 q) P& E3 Q3 }0 O) X
  4.   {' n2 c  m3 i4 j' t( t! Y# k% [, m$ H
  5.     /* USER CODE END WHILE */' A6 x. h# u) I+ t

  6. / u  E, W1 @# V0 V
  7.     /* USER CODE BEGIN 3 */  b) f, _& H* F: C! F( J5 ]4 n
  8.                                 if(recv_end_flag == 1)                                                                                                                                            //接收完成标志,如果串口有数据接收,则执行该部分
    ( j" [- u7 U3 r4 ]
  9.                           {
    # }& S4 M4 J1 H. S; L
  10.                                          DMA_Usart_Send(rx_buffer, rx_len);+ F2 k$ z+ S" ^9 P5 {
  11.                                          DMA_Usart_Send((uint8_t *)"\r\n", sizeof((uint8_t *)"\r\n"));        - B+ l& n* P! }, K
  12.                                          rx_len = 0;                                                                                                                                                                     //清除计数0 b' y/ K1 H. I' I! J! k
  13.                              recv_end_flag = 0;                                                                                                                                                         //清除接收结束标志  [+ t" ]' e% t: x3 O
  14.                                    memset(rx_buffer,0,rx_len);( L4 n7 n# f9 [7 C& c
  15.                           }+ f* i3 l1 r) P0 p
  16.                                 else                                                                                                                                                                                                                                //如果外部没有数据,则执行该部分) z' L7 d6 o/ f! H0 q& e; M. I% E
  17.                                 {
    9 m" G7 k7 E& a
  18.                                                
    7 F7 y/ a2 G8 y( x  a2 W" T. i5 z! n) A
  19.                                                 DMA_Usart_Send((uint8_t *)"hello world,this RS485 send...\r\n", sizeof("hello world,this RS485 send...\r\n"));4 v- K6 ]6 l4 l. ^
  20.                                                 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);                                                                                //控制LED1闪烁
      u, D; N# j( O) G5 c
  21.                                                 HAL_Delay(500);8 U) D( d$ y3 z" i
  22.                                 }. \8 U- f  j+ r5 C1 Y
  23.                           HAL_UART_Receive_DMA(&huart2,rx_buffer,BUFFER_SIZE);       //重新打开DMA接收                                / a5 B) Z. S7 F$ F. V
  24.         }/ z! [- Y5 V& x  T5 C
  25.   /* USER CODE END 3 */
复制代码

( R% h% Y$ O. C8 g/ {4 S(2)stm32f1xx_it.c中添加接收中断处理代码如下:( U  Q5 \' O8 S4 T" }9 G' T' X
  1. /**5 \6 X8 Y  R5 g5 |1 v, h
  2.   * @brief This function handles USART2 global interrupt.
    ; w3 C9 Y! L! y- O) P; I) d
  3.   */
    3 b% ~- ?( t  a: ?
  4. void USART2_IRQHandler(void)
    ( q7 X4 E7 j5 D3 C2 ~/ u' s
  5. {
    9 s7 X0 f9 p1 P" V
  6.   /* USER CODE BEGIN USART2_IRQn 0 */4 K3 h$ d, E) V  y
  7.         uint32_t tmp_flag = 0;6 x) b, ?" T- {% K' u4 x
  8.         uint32_t temp;# I1 S7 d/ m) w9 V4 Z" v
  9.         tmp_flag =__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE); //获取IDLE标志位( l5 j8 O) o0 E9 d) r
  10.         if((tmp_flag != RESET))                                //idle标志被置位
    8 C$ h( n* t$ n% Q" z, X
  11.         { " n  ]0 s9 [& t6 x7 ?
  12.                 __HAL_UART_CLEAR_IDLEFLAG(&huart2);                  //清除标志位
    5 [( O* x. m6 K6 h5 ^4 H
  13.                 HAL_UART_DMAStop(&huart2);     
    2 M9 J( S' z# ?8 t/ k$ U
  14.                 temp  =  __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);     // 获取DMA中未传输的数据个数   
    " o, W$ {/ A9 m5 R4 V! ~
  15.                 rx_len =  BUFFER_SIZE - temp;                                             //总计数减去未传输的数据个数,得到已经接收的数据个数8 h! I9 E# I6 p! L' Q( E
  16.                 recv_end_flag = 1;                                         // 接受完成标志位置1        ! O5 s0 t& g+ \( x1 @3 p. u
  17.          }
    0 B/ e! b. r" ~5 ~+ K
  18.   /* USER CODE END USART2_IRQn 0 */
    * I! o: P* p# S
  19.   HAL_UART_IRQHandler(&huart2);
    & a  \6 U- U! w7 R
  20.   /* USER CODE BEGIN USART2_IRQn 1 */
    7 H* K' Z7 T+ T) g* z

  21. 8 D  s4 U* h" a& Q$ A! v+ u3 U# z9 G1 W
  22.   /* USER CODE END USART2_IRQn 1 */) U0 M% e$ q$ ]  v+ B7 Z" w8 D" M
  23. }
复制代码

" e( }3 I. b3 _/ S4 K1 u(3)至此,串口DMA收发数据需要添加的代码已经完成。
- G! y  q0 i* E+ m( d6 Q* {6 x' o# {. I4 J  F% T' c
5、设置编程仿真下载模式" a+ N/ M% R4 T9 l8 d
(1)选择Options for target ...>>Debug>>J-Link/J-JTRACE Cortex,点击Settings>>选择Port(SW),可以看到搜索成功SW Device,表示芯片可用,可以下载。( Q1 k4 N  [4 \2 T
! }& X, r( x, W6 I6 r. o( L
edefb6b9a2a14be3b1221ad6d5c7a8a2.png
" q0 [+ k/ e7 x% \; R7 I
* e; G  {9 X1 o  R: n1 P
(2)点击编译,完成后提示“0 error(s),0 warning(s)”。
8 b' I- K* E' F4 H5 J1 ?
8 K8 z0 x, ^5 T" S; j7 \, b4 E
f0ed816a3ed14487bf9e857c317fc99b.png
/ u' M8 G3 [7 H9 Q
% d- u2 z2 m9 W' E* R
(3)点击Download(或者快捷键F8),即可下载程序。! o4 v' Q- p- o8 h; y6 b4 H; Q
$ N- M) `7 k  _6 U3 {( F
ba221842d5db40808aa129dd83c593d0.png
( s2 A1 z! a# f) w
+ {0 k+ Y" I( a5 L, F7 I(3) 如果下载程序后,没有看到LED1灯闪烁,可以按下述方式设置一下(Reset and run表示下载后自动复位和重启运行)。或者重新彻底断电再次上电(或按开发板的Reset按键复位MCU即可)。
: R- W9 h# n3 d% W4 N( {, a
% ]0 r8 F  h2 B3 H' {* ^/ \2 u
9f8aa1a4e8f04041bcf5cb183facd100.png ; P, a: d5 c  ]# |

/ g: M" Y' N8 e" f& f/ X# V4、查看串口发送函数打印log效果
0 s  L) Q$ ~& l8 w8 ?  H: T  J9 q(1)设置串口助手参数为:115200、NONE、8、 1(和代码中串口初始化参数一致)。
% e2 ^  T& Z' b9 i$ h(2)设置成功后,就可以看到串口打印的效果。如果串口助手没有发送给MCU的数据,则MCU每隔500ms闪烁LED1指示灯一次,且串口输出一个log。# A5 ]! Z' S) D: p0 b1 `9 ]8 M! B3 P
(3)如果串口助手往MCU发送数据,MCU把接收到的数据发送到串口助手进行打印显示。
1 M6 B% L3 c! h! ~
/ b9 R5 e& ~, j* m0 s 8f65172eef06499987e27edddf5320f2.png
$ @# V0 X" L: f2 w. G1 ]
2 l' r" `% |  I( i* ]. U! \1 Y————————————————
" X% ~) z! G1 ^% m版权声明:智能小屋ZYXC
* w& H  J" n4 `; M9 [  ^/ o' X! f6 R
$ J  J( r' W/ t4 @
收藏 1 评论0 发布时间:2023-1-14 17:49

举报

0个回答

所属标签

相似技术帖

官网相关资源

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