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

【STM32U3评测】实现双通道串口通信系统

[复制链接]
donatello1996 发布时间:2025-5-23 17:55
     拿到了nucleo-U385开发板,在KEIL环境下编程,需要下载CubeU3支持包,在ST官网即可下载,并且在CubeU3支持包内还有KEIL环境所需要的pack安装包,这个应该是最近才做的一个方便开发者开发的一个机制:5 r" j6 `' n) h; N' h
1.JPG
, I6 b. j: u* ^# j" S, F我直接用点灯的例程来改串口例程,方便省事:2 O( U) a4 a* }
2.JPG
5 X' e3 a" b- X5 ^; [整理好的例程结构如下:7 Z3 h1 Z% q4 F5 P
3.JPG + p$ x" w3 g( W3 ?9 u& k$ w- n1 }* e
根据原理图可以得知,开发板的STLINKV3 VCP连接的串口是UART1,即PA9 PA10,可以直接与电脑的串口助手进行通信,另外开发板上还有PA2 PA3引脚,这个引脚被复用为LPUART1:
. X! Q" L+ }* g
4.JPG 5.JPG 3 R2 f$ k$ O: S5 n2 |; j
我这个帖子就实现UART1和LPUART1的双通道串口通信,其中把LPUART1的接收功能打开,使用空闲中断和DMA进行接收,先看看UART1的初始化代码:
  1. <font face="微软雅黑" size="5">UART_HandleTypeDef huart1;
    % r, {, x$ i9 ^% v: k

  2. & i5 u  v+ g) M
  3. int fputc(int ch , FILE *f)- F6 K: h2 m+ c0 O- `% u, \6 u
  4. {. U3 G: K  |2 v2 Z, i, f9 e$ ?
  5.     while ((USART1->ISR & 0X40) == 0);& t- x: V* p5 ]7 E, ^  W
  6.   USART1->TDR = (uint8_t)ch;
    ! h) a2 }2 D) g
  7.     return ch;
      p$ Q/ U. Y2 d& ?: G% r
  8. }; c& m8 |; l# e2 v4 T8 b
  9. , ?4 P2 _$ |3 t$ P, s9 Y( E( @. k5 k  Q
  10. void UART1_Init(uint32_t baud)) r8 O9 Z0 T# y4 o  h" s/ S& E- k
  11. {* G9 K: Q$ ~" ?7 c
  12.     GPIO_InitTypeDef GPIO_InitStruct = {0};- g" D9 X" k9 X; k4 A6 o8 e+ k
  13.     RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
      c4 a4 i: ~' ]+ h* a  w" W9 B6 B! o

  14. ( `0 n7 x: o0 }  [- L
  15.     __HAL_RCC_USART1_CLK_ENABLE();; ^+ q) B/ K6 o) `( |) p$ t
  16.     __HAL_RCC_GPIOA_CLK_ENABLE();
    * J1 D  O' B- [1 |+ _

  17. / z+ }3 Z2 U6 B7 q# \
  18.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;% J3 v1 X' L5 v
  19.     PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
    ! g8 g0 r0 r9 V6 t
  20.     HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
    7 {7 V' L  ]7 i2 \/ m  T. f
  21. 0 |) ?- R3 E  S4 q# B, t( T- S
  22.     GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
    ( F3 t  a9 [+ E4 W% M" g
  23.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;2 k7 J9 W- p* T4 j3 u4 \
  24.     GPIO_InitStruct.Pull = GPIO_PULLUP;% ]) O6 x) A( N9 H# k! s
  25.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;% ?6 Y1 o4 c1 i' s
  26.     GPIO_InitStruct.Alternate = GPIO_AF7_USART1;0 r, t/ e) ]& d' |) G
  27.     HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
    9 E$ d& ?7 F4 h8 T
  28. </font>   <font face="微软雅黑" size="5">
    0 e6 p& H2 s% {
  29.   huart1.Instance = USART1;2 ]& q# o$ h9 [# T0 _
  30.   huart1.Init.BaudRate = baud;
    ) x- I) x- l" x- X* X& _. @. f' U
  31.   huart1.Init.WordLength = UART_WORDLENGTH_8B;2 S: ]1 {5 W- e7 r
  32.   huart1.Init.StopBits = UART_STOPBITS_1;- J; f6 _, Y7 O) h$ \+ `1 D6 c
  33.   huart1.Init.Parity = UART_PARITY_NONE;
    6 {& [3 G. l& r8 k
  34.   huart1.Init.Mode = UART_MODE_TX_RX;! t! g9 G: Y  R" }/ `# \6 E3 a# f; Z
  35.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;" [9 Y' y( r6 p( A9 m7 u
  36.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    , _' R# A8 {! O8 \; f
  37.   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;, A! _( Y9 W! a7 j' U+ H" x8 ^
  38.   huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    , V# ?! m/ n4 a; }
  39.   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;6 b4 V4 l; K- ~: e% u
  40.   HAL_UART_Init(&huart1);
    0 C8 Y: r/ j: N( P" y; `
  41. }</font>
复制代码
非常简单,只要熟悉STM32编程的没有一点难度,然后是LPUART1:* V7 {5 Q, h6 S1 p5 r( n
  1. <font face="微软雅黑" size="5">UART_HandleTypeDef hlpuart1;2 w- R# [* x( B' ?& C
  2. ' a2 S% I7 y8 z3 ?
  3. DMA_NodeTypeDef Node_GPDMA1_Channel0;
    " \) M* X% q: q' n
  4. DMA_QListTypeDef List_GPDMA1_Channel0;' N# ~+ s, F" T- z% j
  5. DMA_HandleTypeDef handle_GPDMA1_Channel0;
    " }0 j7 l: T8 b. V
  6. 4 N3 B' }% X- b+ ~3 Q
  7. void LPUART1_Init(uint32_t baud)5 ~7 z& j  J; y; `; ~
  8. {. g# F: q' `: S1 [" j0 H, u
  9.     GPIO_InitTypeDef GPIO_InitStruct = {0};9 X. v. N& w1 v; W$ w" u* U
  10.     RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    : {  |% H7 _* x0 l! t, s* A- T
  11.     DMA_NodeConfTypeDef NodeConfig;
    7 x6 n0 Y2 d; H( h  N- O1 Y

  12. " H& ]. B5 K* J/ |0 |
  13.     __HAL_RCC_LPUART1_CLK_ENABLE();
    9 L& O: T! O) `7 t( c+ B
  14.     __HAL_RCC_GPIOA_CLK_ENABLE();2 [- W3 b( I# F! }9 B- p" F5 t) N. `
  15.     __HAL_RCC_GPDMA1_CLK_ENABLE();) E/ n; z$ P8 T

  16. . a( I4 m  [* l2 x  A) q& e
  17.   PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;1 G9 `! ^7 h6 |
  18.   PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK3;
    ; j4 |8 i# B( I
  19.     HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);  Y4 `! g' S1 h2 _* c. _, {" p# U
  20. : c, W/ y; {; q5 G  c2 X
  21.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;# h0 N! [; ?: r) F: U1 \
  22.     GPIO_InitStruct.Pull = GPIO_PULLUP;4 x0 z- u) @9 M2 J& R0 }+ A8 q/ [" c( Z
  23.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;7 e  l$ t* I3 k! \/ t
  24. </font>   <font face="微软雅黑" size="5">4 }% C9 p* O. s
  25.     GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;& {6 y- _- d) k' _8 l5 x% L
  26.     GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
    9 l, |7 h2 T5 _+ G, S% k; p- e: c
  27.     HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
    7 w# R; Y: `) |  j8 B: V) ?
  28. </font>   <font face="微软雅黑" size="5">7 [/ v6 o' s  G& Z% I5 P, S& i
  29.   hlpuart1.Instance = LPUART1;
    , t2 T. ], Q2 B
  30.   hlpuart1.Init.BaudRate = baud;
    2 Z+ k& w2 u9 u* q
  31.   hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;2 i6 G; ?" B7 s/ r
  32.   hlpuart1.Init.StopBits = UART_STOPBITS_1;% s" q; L$ }( x  X8 p
  33.   hlpuart1.Init.Parity = UART_PARITY_NONE;
    . X! @& j  x5 c: p$ @4 ?
  34.   hlpuart1.Init.Mode = UART_MODE_TX_RX;7 E, ^( O: }7 X* B' W
  35.   hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    4 D0 r- n7 [* j+ `# x4 y- r4 I
  36.   hlpuart1.Init.OverSampling = UART_OVERSAMPLING_16;7 Z  r( j# _8 v: x4 j6 Q
  37.   hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;6 s# |) v* h5 B+ n
  38.   hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;/ r( X; Q  P. j5 d2 I2 H9 G1 O
  39.   hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    ' O9 @7 Q  _1 {" l/ g: X% N6 a
  40.   HAL_UART_Init(&hlpuart1);! z) A- V$ A5 W3 Z1 ^
  41. </font>   <font face="微软雅黑" size="5">
    ; o; @1 m1 ]5 N" c; `
  42.     __HAL_UART_ENABLE_IT(&hlpuart1 , UART_IT_IDLE);( Y3 p  r2 L9 a3 J7 }
  43.     HAL_NVIC_SetPriority(LPUART1_IRQn,1,1);
    2 w' ]& d; F8 T' V, u6 z6 o' {
  44.     HAL_NVIC_EnableIRQ(LPUART1_IRQn);
      F2 R% Z# C4 R1 X8 x6 v
  45. </font>   <font face="微软雅黑" size="5">6 o2 [/ ~2 c3 b7 w$ T, }& N1 B- q
  46.     NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;* x' W2 h' }: j
  47.     NodeConfig.Init.Request = GPDMA1_REQUEST_LPUART1_RX;
    $ ?9 h1 }& f2 i& M, r) `' y
  48.     NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;8 q; v6 F: o$ ^9 b
  49.     NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;0 N1 l" f+ n2 t
  50.     NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
    ) H9 u, N4 D0 Z
  51.     NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
    % N) c- H9 w9 r/ a. o
  52.     NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
    8 U/ R, X9 F5 d- G- k
  53.     NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
    / P* t, h% R7 H8 X
  54.     NodeConfig.Init.SrcBurstLength = 1;' E- u4 E5 z+ h/ b; g, l2 P7 K, p
  55.     NodeConfig.Init.DestBurstLength = 1;
    : B. K" P6 S4 Q4 e: \2 \
  56.     NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;4 `6 s& M& N4 g( ?. J1 {& i' h4 k5 l
  57.     NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;4 p9 h4 I8 q3 l4 v
  58.     NodeConfig.Init.Mode = DMA_NORMAL;! C# Z2 I# Z7 t2 {4 F
  59.     NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
    " ]) C5 s9 |+ Y# y* I  V- t
  60.     NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;* X% F1 H+ L2 w
  61.     NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
    : K: Z+ d9 s5 q
  62.     HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0);
      ~  m& @: N) F
  63. 7 \9 u) B" {8 ?; J  o
  64.     HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0);/ e1 l# r. X1 U
  65. % N- m; s7 G( ?. h
  66.     HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0);( J7 R* e& i8 U; C" |

  67. 0 ]! E# r4 \' o+ ~
  68.     handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
    & M' l# K0 P7 H3 N$ x1 o( Y
  69.     handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;) V9 V$ @! h# W. u) D& b  A
  70.     handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;. h9 S9 w. [0 k
  71.     handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;( L  S/ L7 f3 R. s7 ~0 S
  72.     handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;( B' T5 R% [8 ?( V2 j0 D0 y5 v
  73.     handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
    ! a7 |0 m2 f) M) N8 e, T1 F0 u6 j
  74.     HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0);
    5 G: z6 @$ x% q0 N
  75. ' K' g! Z# s! x( N1 s) o* U
  76.     HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0);; S1 d1 m' j0 ?- Z

  77. 4 c4 k6 s0 e9 S4 E& n0 |
  78.     __HAL_LINKDMA(&hlpuart1, hdmarx, handle_GPDMA1_Channel0);
    8 U9 M$ O# n* Z6 Z

  79. 8 V0 `# ?! W6 Z$ h1 h; f( h8 p5 l
  80.     HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV);
    . T  ]+ F; l* p
  81. </font>   <font face="微软雅黑" size="5">
    : c* k, |; L4 F, @; U) N
  82.     HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);
    . t* `) B8 [% ^. t6 {! |0 |7 W
  83.     HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);+ U! s+ L! l- U, D6 N5 A
  84. }
    3 _1 L' b* M6 P- ^

  85. : }0 B2 {  T# t1 A
  86. void LPUART1_Send_Char(uint8_t ch)
    3 M6 ~9 Y/ O3 `( R/ f# L9 {0 @
  87. {
    ) O& B$ @1 t7 @, t1 P* H3 Q/ ?
  88.     while ((LPUART1->ISR & 0X40) == 0);
    6 X4 y/ K$ d2 L
  89.   LPUART1->TDR = (uint8_t)ch;- Q2 C! C/ [+ z9 c
  90. }) [/ [3 R2 K8 h* `2 L  U& ^( ?

  91. / O: i9 F) c( T: P! m; ]
  92. void LPUART1_Send_String(uint8_t * s)
      u9 B( g0 v: K% ]8 |2 m
  93. {
    % Z9 k$ N  C9 w
  94.     uint32_t i;  _1 h, e3 ?1 a, C# V4 z3 ~
  95.     for(i = 0 ; s != '\0' ; i++)4 ?; h. i: e0 J( w2 B
  96.         LPUART1_Send_Char(s);. A; n* Z2 D; u% M
  97. }7 m" @; ~  x4 F; c/ _  ?" V

  98. 5 g/ b$ W7 T: X1 V6 h1 I' V" Y
  99. void GPDMA1_Channel0_IRQHandler(void)" @( e5 h$ ]* F# N1 M2 Y0 N
  100. {
    8 Y  l6 v6 m2 b! t& m* n
  101.   HAL_DMA_IRQHandler(&handle_GPDMA1_Channel0);! C0 t: J8 L- D: C% p/ i- P3 f
  102. }7 z2 f4 g) K; [* A* x8 l7 r

  103. 5 `" ]7 r/ d8 ~& Z/ M
  104. uint8_t aRxBuffer[RXBUFFERSIZE];. \& @8 _+ z1 v1 x9 G% w
  105. - m+ K, L3 A+ X8 }; e6 L3 e* Y
  106. void LPUART1_IRQHandler(void)                      ^# Z' y* U* S# P9 g& ^
  107. {
    3 R9 m  S3 p" j  ~6 ?
  108. //    int temp;( k- r% w7 L4 m  ~1 A5 A5 S, W
  109.     if(LPUART1->ISR & UART_FLAG_IDLE)
    5 M8 f0 A0 }( l  O
  110.     {
    " E  M& _) o  F! V9 Z2 v* t
  111.         __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);
    7 C) d# K. i- m6 c, F* d
  112.         printf("LPUART1_IRQHandler. %d %s\n" , GPDMA1_Channel0->CBR1 , aRxBuffer);
    . _+ d- ?; h6 v& e
  113. </font>        <font face="微软雅黑" size="5">! z& r1 `1 q+ S% z
  114.         HAL_UART_DMAStop(&hlpuart1);' [: p" y+ I  i$ A3 L7 p- K: \( y
  115.         HAL_UART_Receive_DMA(&hlpuart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);- r( P! t% |" O, `* I
  116. //        rx1_len = BUFFERSIZE - DMA1_Channel5->CNDTR;- A% d3 J4 e) X1 F+ u" _/ ]
  117. //        uart1_recv_end_flag = 1;
    8 p1 J  ?/ }) l3 l9 v* g
  118.     }5 W. y+ v4 g' O9 M
  119. }</font>
复制代码
在ST的新系列里面,有个特殊机制,使用任何形式的DMA通信必须要打开DMA中断,这个在F103系列是不需要的,是F4以及之后的大部分系列都需要,另外,在F4之后的系列中,对于外设要用的DMA,可以自由配置通道Channel(流Stream/节点Node)等,其实是一个东西,就是DMA通道的意思,不同系列的名称不同,只有F103和F4系列的特定外设是绑定在特定DMA通道的。像本帖子,就把LPUART1的RX功能设置在在GPDMA的通道0(后续还把SPI1的TX功能设置在GPDMA的通道1)。
# c7 E$ F' w/ Q
/ d) e2 k; s7 L, ]3 }! P 6.JPG
8 v  N: `$ b# \/ A, O/ t* n
- @* d, x: p0 ?4 U2 X8 f- V: U看看运行效果,使用两根typec线分别连接开发板的STLINKV3接口以及用一个USB转TTL模块接在PA2 PA3引脚上:$ y6 A: i$ u# n3 c! W; O
7.JPG IMG_20250523_174406.jpg : R3 d0 K  J$ I" w) R. a* {6 k/ z: P
首先上电之后UART1和LPUART1都会打印信息,然后,对LPUART1发送数据,UART1会打印接收到的数据以及接收长度(100-DTR寄存器值)。
收藏 评论6 发布时间:2025-5-23 17:55

举报

6个回答
星海灿烂 回答时间:2025-5-25 15:04:59

你好,板载ST-LINK电脑可以识别不到吗?

donatello1996 回答时间:2025-5-25 23:48:46

星海灿烂 发表于 2025-5-25 15:04
你好,板载ST-LINK电脑可以识别不到吗?

没看懂你的表述是什么意思

星海灿烂 回答时间:2025-5-26 08:58:46

donatello1996 发表于 2025-5-25 23:48
没看懂你的表述是什么意思

就是把板载ST-LINK的C口接入电脑,电脑可以识别到ST-LINK吗?

donatello1996 回答时间:2025-5-26 16:13:19

星海灿烂 发表于 2025-5-26 08:58</p>
<p>就是把板载ST-LINK的C口接入电脑,电脑可以识别到ST-LINK吗?

[md]那肯定可以识别啊,不识别怎么下载代码发帖子😄

星海灿烂 回答时间:2025-5-26 16:53:24

donatello1996 发表于 2025-5-26 16:13
那肯定可以识别啊,不识别怎么下载代码发帖子😄

使用的是全功能的Type-c线吗?

donatello1996 回答时间:2025-5-26 17:42:37

星海灿烂 发表于 2025-5-26 16:53
使用的是全功能的Type-c线吗?

没听说过typec线还分什么全功能不全功能的,我直接用手机充电线来接开发板的,一端是typeA的HOST,一端是typec,把线连接电脑和手机,能识别出手机的存储卡,那就肯定可以给开发板用

所属标签

相似技术帖

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版