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

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

[复制链接]
donatello1996 发布时间:2025-5-23 17:55
     拿到了nucleo-U385开发板,在KEIL环境下编程,需要下载CubeU3支持包,在ST官网即可下载,并且在CubeU3支持包内还有KEIL环境所需要的pack安装包,这个应该是最近才做的一个方便开发者开发的一个机制:/ E. |# a$ o' d* h) n
1.JPG : M& r1 S; d3 H2 j6 |
我直接用点灯的例程来改串口例程,方便省事:
( C' G! T2 i& r- A
2.JPG
# F. `& O5 Z( ]8 z. l整理好的例程结构如下:( a  p( h' {7 A2 Y: j% y% k
3.JPG
# I/ V' x' m% h, B9 b3 \/ g" }4 H0 d根据原理图可以得知,开发板的STLINKV3 VCP连接的串口是UART1,即PA9 PA10,可以直接与电脑的串口助手进行通信,另外开发板上还有PA2 PA3引脚,这个引脚被复用为LPUART1:6 l. i! m" Y, v# p2 m  ?" \2 L
4.JPG 5.JPG
, F% g5 u# D* d; e. H6 X: d我这个帖子就实现UART1和LPUART1的双通道串口通信,其中把LPUART1的接收功能打开,使用空闲中断和DMA进行接收,先看看UART1的初始化代码:
  1. <font face="微软雅黑" size="5">UART_HandleTypeDef huart1;
    3 ^+ W, X7 a: ]; Z/ i. g
  2.   O7 W/ G2 Z# {9 B
  3. int fputc(int ch , FILE *f)
    $ k7 ~1 p5 z$ Y
  4. {
    ; f& y3 `, G( v2 s# N
  5.     while ((USART1->ISR & 0X40) == 0);
    % E8 n$ O! q6 {- W: a
  6.   USART1->TDR = (uint8_t)ch;
    " V2 d2 p5 z& d8 m- t2 B+ U8 Z4 X0 ^
  7.     return ch;
    5 n" D6 Q  F$ d6 N" d& y$ l5 |
  8. }
    1 C" c- \: N0 j, n6 v

  9. 2 Y* d# E1 l( G- y( Z- d/ F0 k/ u
  10. void UART1_Init(uint32_t baud)
    6 m6 o: I+ V7 I8 @: u3 W
  11. {  B5 B/ e# s- U- U3 U8 [
  12.     GPIO_InitTypeDef GPIO_InitStruct = {0};
    4 }# H& }3 E* T! W; ?- }$ e
  13.     RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    3 c" J7 K! V) B9 U  N' {6 P" s
  14. 2 e* n0 ^2 `  ?' o
  15.     __HAL_RCC_USART1_CLK_ENABLE();$ U$ v9 b( H4 O* e+ X' a
  16.     __HAL_RCC_GPIOA_CLK_ENABLE();
    ' q; C( f" B9 q# Z
  17. $ S; R8 T7 h6 x
  18.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
    9 L2 v7 N; U, v5 E" d
  19.     PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;7 P, g& l: U" j1 V+ }7 J; |
  20.     HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);: U  e# l$ Q' a" e$ S
  21. ( Z* U) Z, ^, A) S- d  E- k% h
  22.     GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
    6 ~+ ?7 d8 E5 E. F: h4 N5 m
  23.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;& K/ l) L) w' t, @# }# t
  24.     GPIO_InitStruct.Pull = GPIO_PULLUP;; a* t$ q1 V/ d9 i. C% B2 M# B; j
  25.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;6 L1 B5 Q& A& E* K
  26.     GPIO_InitStruct.Alternate = GPIO_AF7_USART1;1 d6 n1 k  Y4 S8 q
  27.     HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);- ^0 n$ O$ [" X
  28. </font>   <font face="微软雅黑" size="5">
    % q& ]: m8 M# l; Y! c* T
  29.   huart1.Instance = USART1;
    . G- Q( R. j3 f9 S/ a7 Z" y$ ^8 V: a
  30.   huart1.Init.BaudRate = baud;8 C7 h+ ^- t" {
  31.   huart1.Init.WordLength = UART_WORDLENGTH_8B;, Y( }) m" w' d# q. p' T8 _! D
  32.   huart1.Init.StopBits = UART_STOPBITS_1;4 Q0 f7 {$ g  `7 @' J
  33.   huart1.Init.Parity = UART_PARITY_NONE;6 i& \8 `* P4 J) M. z5 e; T
  34.   huart1.Init.Mode = UART_MODE_TX_RX;
    + i7 J9 P& m* |" K, Z( b5 E' i
  35.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    3 {% e0 v" U8 q
  36.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    7 \8 B/ B3 j! n. ?0 o; C1 G
  37.   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    & t4 w' u/ c; M' p1 g  e8 S
  38.   huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;1 ?* T% D% v, W' q+ T
  39.   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    ; i  {# ]2 L: A6 c) w
  40.   HAL_UART_Init(&huart1);
    5 L& |0 }& Y  c) C; @$ u
  41. }</font>
复制代码
非常简单,只要熟悉STM32编程的没有一点难度,然后是LPUART1:
4 i, N9 g7 l* {" Z: \! W
  1. <font face="微软雅黑" size="5">UART_HandleTypeDef hlpuart1;
    ; O7 {2 _- K+ \* j  ?. U

  2. 5 k! l; b- |" S6 l0 _' g
  3. DMA_NodeTypeDef Node_GPDMA1_Channel0;
    ) ?$ `# Z, a2 D; a
  4. DMA_QListTypeDef List_GPDMA1_Channel0;) f4 H+ R, i/ Y) ~  U
  5. DMA_HandleTypeDef handle_GPDMA1_Channel0;
    4 e$ k! M3 D! r( R( J
  6. / C6 _7 p# k- u1 J- J+ X+ o* ~
  7. void LPUART1_Init(uint32_t baud)
    ' c: V6 G% L9 @- n) c+ R  J
  8. {; @; T5 G9 \* V) z+ K
  9.     GPIO_InitTypeDef GPIO_InitStruct = {0};
    , p: ]$ b6 ?5 L' g: S3 F
  10.     RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    9 A2 C. Z4 b9 A+ i& \* z9 \2 p
  11.     DMA_NodeConfTypeDef NodeConfig;2 R6 l* q: p: A- u! ~) Q

  12. . H( p0 n& g9 H' _6 v* T
  13.     __HAL_RCC_LPUART1_CLK_ENABLE();/ U" z& Y* x, }$ U
  14.     __HAL_RCC_GPIOA_CLK_ENABLE();
    0 Y* A8 }- U$ R
  15.     __HAL_RCC_GPDMA1_CLK_ENABLE();
    ! e+ S! i/ {- U- R3 V

  16. 5 }' R$ }8 D0 N7 v: `' k: |
  17.   PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;
    & k* |3 X( [$ ?( Z* D1 h2 e$ A. Z8 i9 V
  18.   PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK3;
    6 D; U" p# p& Y; j
  19.     HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
    - W# e0 n7 U( }
  20. 5 A$ I) ^0 }! L2 a* I. ~
  21.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    : g$ N7 ^+ N0 a# ]% {
  22.     GPIO_InitStruct.Pull = GPIO_PULLUP;- W: S6 ?& M% V  |+ u
  23.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;; r/ K% _9 w5 v: c
  24. </font>   <font face="微软雅黑" size="5">. K6 \  t% X! f" B3 R
  25.     GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;
    : x" `. e7 N) q# H' g8 d
  26.     GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
    : F( _& a( U. e* E% u
  27.     HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
    1 t, i1 t+ }/ F" @8 u/ F8 _
  28. </font>   <font face="微软雅黑" size="5">
    # E% t" N! R1 Y
  29.   hlpuart1.Instance = LPUART1;2 M% p8 p9 p  \
  30.   hlpuart1.Init.BaudRate = baud;
    3 B' ]5 a+ M7 u" L, `3 q: P+ b
  31.   hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
    + Q" V; C! o/ R& |& Z
  32.   hlpuart1.Init.StopBits = UART_STOPBITS_1;0 ]8 c, S5 M. {! K
  33.   hlpuart1.Init.Parity = UART_PARITY_NONE;+ z9 K  D5 t$ e' W+ d
  34.   hlpuart1.Init.Mode = UART_MODE_TX_RX;" u) K( S% c9 ?: x3 g) F
  35.   hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    1 H( o; h( i3 r
  36.   hlpuart1.Init.OverSampling = UART_OVERSAMPLING_16;& |: g% _' n  @- d+ g; L
  37.   hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    % y- v/ c: W& t/ @! U! F
  38.   hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    * r! [4 O7 F2 H( M" g+ W' g- N
  39.   hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;4 m' \5 L: C. W
  40.   HAL_UART_Init(&hlpuart1);
    ( R% f$ X! ~0 x7 Q
  41. </font>   <font face="微软雅黑" size="5">" z4 O2 R& `8 L" h$ B
  42.     __HAL_UART_ENABLE_IT(&hlpuart1 , UART_IT_IDLE);2 ^7 d6 e+ d2 {, b0 q! d3 T
  43.     HAL_NVIC_SetPriority(LPUART1_IRQn,1,1);$ g7 _! i/ r5 ?8 K- c$ l' y- |( `
  44.     HAL_NVIC_EnableIRQ(LPUART1_IRQn);
      Z2 q+ v& e' V; J2 s
  45. </font>   <font face="微软雅黑" size="5">* x, f& o2 @' z7 k+ k$ ^+ s
  46.     NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
    / m6 f7 _$ O+ j( j- _! U* U
  47.     NodeConfig.Init.Request = GPDMA1_REQUEST_LPUART1_RX;
    6 w+ q7 ^. n6 n9 n, S: v
  48.     NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;5 k; [: S: O) [$ K7 o; |
  49.     NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
    , V2 f- t) v3 j, Y
  50.     NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
    0 `9 L6 L; ]! w% E& r( [  i$ t* D, D
  51.     NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
    7 F/ k9 M4 C- V, L( P
  52.     NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
    ' _/ i$ D8 O- p" D: ]
  53.     NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;, A4 w- |1 X" Z/ k$ U8 Z! F9 w
  54.     NodeConfig.Init.SrcBurstLength = 1;4 Y4 Q# y# \: W1 }
  55.     NodeConfig.Init.DestBurstLength = 1;
    9 |/ y* l- J' Q: v" o, g3 `
  56.     NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
    , f' G  t4 q8 E& a6 j- S: D. ]
  57.     NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
    0 z' _/ A1 J: l4 a% b3 v- a
  58.     NodeConfig.Init.Mode = DMA_NORMAL;( ^- }0 c5 _. s1 C- V# J) X
  59.     NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;$ L* [2 W' L, B# m
  60.     NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
    7 l5 W8 A, t. y& B) B
  61.     NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;1 n8 X# }9 E/ @& Z8 n
  62.     HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0);7 ?9 o, j7 Z* \+ d% V" V; }
  63. - b8 W" [( h% A$ f* l4 m0 w/ t. O
  64.     HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0);9 V* Y; q6 \: ^. o/ F1 ]
  65. & S. A/ }! X$ D6 G, x8 T
  66.     HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0);2 p# u: {& c/ d0 z
  67. " U: L7 q& }+ Q: S
  68.     handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
    / B/ E3 D7 I4 H. `, {& H  S
  69.     handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;: c+ F/ e$ I5 ^. ^7 n% X5 ^& p
  70.     handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;% j6 Z' G: K9 F6 u4 C
  71.     handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
    8 i- U6 `' x/ ^6 H) y0 J
  72.     handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
    - I/ h% E2 r1 _3 X
  73.     handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
    8 i0 a5 ^: v$ B& |3 J. ]( H5 c
  74.     HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0);
    : S! {! X% U; m0 B5 s' b: L2 t% u
  75. + G' F; d; ~0 f9 t7 K( Y9 K( @. \
  76.     HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0);
    9 \4 V% j) O+ f4 K" X* t
  77. ; h/ l# `9 J& M7 O' l
  78.     __HAL_LINKDMA(&hlpuart1, hdmarx, handle_GPDMA1_Channel0);" ?: `- H( D" K

  79. " o) l. N- |* j9 W, F: h; A
  80.     HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV);
    ' m/ |7 \6 z! k. u( _3 i
  81. </font>   <font face="微软雅黑" size="5">
    # e: y0 |9 ]% x: A3 F  Q( R7 V( J
  82.     HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);
    6 d8 }# [( t, C+ W; [# |2 J4 b
  83.     HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);' {+ H3 W' D; _  n; B7 n
  84. }
    7 B8 a! c/ o* D$ R4 c) g
  85. / I6 S3 a1 n' g1 P
  86. void LPUART1_Send_Char(uint8_t ch)/ n. |+ R% O& e8 ~" o6 b% @
  87. {- ~% u' Y6 X6 r  Y" f
  88.     while ((LPUART1->ISR & 0X40) == 0);* e: _! ~: Z" O1 l
  89.   LPUART1->TDR = (uint8_t)ch;
    . r7 g  B+ k( Y2 q6 I) A
  90. }
    : U; b2 p8 C# W$ O  Q0 K- [* l

  91. ' X) _* B- U8 h
  92. void LPUART1_Send_String(uint8_t * s)" l) ^1 _3 J$ S" X3 ^
  93. {
    $ ^2 r& U# D" d% u% e! t
  94.     uint32_t i;
    3 Q& G, J5 G$ _& Y
  95.     for(i = 0 ; s != '\0' ; i++)
    ; V5 D- n: k2 I( {9 ~( i" I+ |7 E
  96.         LPUART1_Send_Char(s);- Q- Z3 T3 `9 A# H: e! A
  97. }! _7 H$ {. G8 M& V6 \

  98. ! [* R& ?2 u) @; k. F$ I
  99. void GPDMA1_Channel0_IRQHandler(void)
    2 C, ^2 P) F, I. Y6 d
  100. {% m; c* D0 Q2 o8 H. C
  101.   HAL_DMA_IRQHandler(&handle_GPDMA1_Channel0);
    ) M* _  I/ X$ N2 g$ [. P4 I( `
  102. }
    : ^5 i* ?) Y+ F1 `: G. M0 f0 j9 s/ d; V

  103. ( O2 p$ [" @' L, U
  104. uint8_t aRxBuffer[RXBUFFERSIZE];
    ; B9 D- I# O: s4 }# {: s& z
  105. 0 v# P- r* e% N0 S  v
  106. void LPUART1_IRQHandler(void)                    3 b  H8 M0 j6 Y0 u6 x1 F; Y
  107. {- j6 Z/ y8 s$ l
  108. //    int temp;
    , Z, D4 d$ ?  ^( o2 {7 X
  109.     if(LPUART1->ISR & UART_FLAG_IDLE)( @1 p$ p4 \, X3 i* N3 Q; f
  110.     {1 u3 p, x" |3 {5 S- X' q( B
  111.         __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);
    % o6 p1 K! C. i* Y0 B1 |
  112.         printf("LPUART1_IRQHandler. %d %s\n" , GPDMA1_Channel0->CBR1 , aRxBuffer);( k7 n* `4 ~) ]1 f/ l0 ^
  113. </font>        <font face="微软雅黑" size="5">
    6 c. D/ x* R& ]
  114.         HAL_UART_DMAStop(&hlpuart1);& n, `3 n2 v; ]! \  v
  115.         HAL_UART_Receive_DMA(&hlpuart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);
      A* V+ }1 M* F- a& d/ r
  116. //        rx1_len = BUFFERSIZE - DMA1_Channel5->CNDTR;
    9 e9 f+ ^8 Y, D4 v: b+ B
  117. //        uart1_recv_end_flag = 1;
    5 ]1 H2 N9 e9 @6 r. E  z
  118.     }
    4 c( ^6 Y, {+ }8 z) I
  119. }</font>
复制代码
在ST的新系列里面,有个特殊机制,使用任何形式的DMA通信必须要打开DMA中断,这个在F103系列是不需要的,是F4以及之后的大部分系列都需要,另外,在F4之后的系列中,对于外设要用的DMA,可以自由配置通道Channel(流Stream/节点Node)等,其实是一个东西,就是DMA通道的意思,不同系列的名称不同,只有F103和F4系列的特定外设是绑定在特定DMA通道的。像本帖子,就把LPUART1的RX功能设置在在GPDMA的通道0(后续还把SPI1的TX功能设置在GPDMA的通道1)。
+ Q& c7 [2 C/ a' S/ k
* S! K8 T" m) e 6.JPG * p6 H0 ~9 o0 V0 y

6 i* j. q4 [; f7 G看看运行效果,使用两根typec线分别连接开发板的STLINKV3接口以及用一个USB转TTL模块接在PA2 PA3引脚上:& n0 x' t2 a  c# `/ @6 F
7.JPG IMG_20250523_174406.jpg ( {! e$ D5 a* S, C
首先上电之后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 手机版