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

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

[复制链接]
donatello1996 发布时间:2025-5-23 17:55
     拿到了nucleo-U385开发板,在KEIL环境下编程,需要下载CubeU3支持包,在ST官网即可下载,并且在CubeU3支持包内还有KEIL环境所需要的pack安装包,这个应该是最近才做的一个方便开发者开发的一个机制:
( I8 x4 B% [9 W+ W1 t% W* p
1.JPG
( s' f  ]. x6 j我直接用点灯的例程来改串口例程,方便省事:/ X9 s* i6 B5 {9 W: y1 z
2.JPG & Y2 d) H5 [5 i$ w# s# w
整理好的例程结构如下:
. v% E5 Y8 ^5 g( e* `3 d! x, V
3.JPG
1 ~' n% k) c4 P  D根据原理图可以得知,开发板的STLINKV3 VCP连接的串口是UART1,即PA9 PA10,可以直接与电脑的串口助手进行通信,另外开发板上还有PA2 PA3引脚,这个引脚被复用为LPUART1:8 N4 w; c- ]! t. ?/ M. z, |
4.JPG 5.JPG
4 p' a9 {! q7 q! z我这个帖子就实现UART1和LPUART1的双通道串口通信,其中把LPUART1的接收功能打开,使用空闲中断和DMA进行接收,先看看UART1的初始化代码:
  1. <font face="微软雅黑" size="5">UART_HandleTypeDef huart1;
    0 J: y2 J- O2 L" `2 q& j4 I

  2. . Z( o! c6 k" H  q  _
  3. int fputc(int ch , FILE *f)- }/ J+ Y3 i2 s- O4 @! }
  4. {
    & D3 l! u4 k0 U! A
  5.     while ((USART1->ISR & 0X40) == 0);! W  m9 r7 r' i( E- ^2 e
  6.   USART1->TDR = (uint8_t)ch;. l" `0 Q( D' }  i# V
  7.     return ch;  g1 ?4 J; L! e. L
  8. }4 Q& Y) Z8 X- T! P

  9. / t* s* d/ [9 }
  10. void UART1_Init(uint32_t baud)0 G1 E( L; a8 e; L( Y3 K9 F
  11. {
    $ @( K  U+ L% k9 @
  12.     GPIO_InitTypeDef GPIO_InitStruct = {0};
    - k( _/ j$ O+ X$ J" q& @
  13.     RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};6 X, U6 h( |9 V2 W

  14. " r# J& c% h5 c# y( S. P* P5 t
  15.     __HAL_RCC_USART1_CLK_ENABLE();$ |# \( E3 H0 e2 k" _7 P  `
  16.     __HAL_RCC_GPIOA_CLK_ENABLE();
    9 U$ `2 P8 z: `$ h% d! {( y% b
  17. 1 j8 N( e2 i7 E- R- v1 H1 K" b
  18.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;7 Y  V& s8 l* {; R3 T  G( O; q
  19.     PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
    9 V- }- t+ \. u  F% w- c* o
  20.     HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);! C- D& p, i- [" x' f

  21. . Q* S  N$ G* i4 Y! x7 [1 c
  22.     GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;1 B0 d: ^  l6 e( W1 I
  23.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;( |( D# x! M2 o  A4 g
  24.     GPIO_InitStruct.Pull = GPIO_PULLUP;
    0 a7 i& V. K: Z# w# [* B
  25.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    5 Y6 x4 E" ~. ^
  26.     GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    6 _+ {( ]! A+ `. I' o: h, \7 z8 ^
  27.     HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);  z$ _" V7 ^1 Q1 h: n  Y
  28. </font>   <font face="微软雅黑" size="5">
    , n8 L; \) f5 {( r9 q  l
  29.   huart1.Instance = USART1;  K* u' o' N. _* ?( ]
  30.   huart1.Init.BaudRate = baud;
    & h: w  n0 A% U8 Q  N- H
  31.   huart1.Init.WordLength = UART_WORDLENGTH_8B;2 d" ^# a( p& q6 f' Y" b
  32.   huart1.Init.StopBits = UART_STOPBITS_1;" L3 c9 C4 r" d2 T* m/ b4 D. r$ o, i2 C
  33.   huart1.Init.Parity = UART_PARITY_NONE;6 B: L/ S+ B, u! i6 J7 r+ {
  34.   huart1.Init.Mode = UART_MODE_TX_RX;
    * r8 {  u, R; }% D4 s' r- Q1 k
  35.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;" H) d& A( y2 n8 }4 n7 g4 o
  36.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;0 |2 q$ P+ s! Y5 [- ^
  37.   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    ; Y* U' @/ F% F" a& S
  38.   huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;9 `/ ^1 a) X% J" ]$ S6 U
  39.   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;- o  a, |, n+ @3 r& ^
  40.   HAL_UART_Init(&huart1);1 n' s' I* V. O$ [, m% T# E
  41. }</font>
复制代码
非常简单,只要熟悉STM32编程的没有一点难度,然后是LPUART1:4 p" |- J" C( v- _$ e
  1. <font face="微软雅黑" size="5">UART_HandleTypeDef hlpuart1;
    # |; {  w9 F' E6 g: q
  2. & f5 R7 J8 {8 L4 w
  3. DMA_NodeTypeDef Node_GPDMA1_Channel0;/ J* m+ l. y2 V2 \% h3 T8 D# [
  4. DMA_QListTypeDef List_GPDMA1_Channel0;
    % A0 v1 T' \* Z
  5. DMA_HandleTypeDef handle_GPDMA1_Channel0;
    ; d1 z0 \' Z7 E# c( f: `" U% N1 @
  6. ' T; I" E2 Z' p
  7. void LPUART1_Init(uint32_t baud)
    4 h! d1 k0 F: t  ]' R  X  w: G! j& A) Y
  8. {7 `, g* Q8 D' B# u7 d6 {& C
  9.     GPIO_InitTypeDef GPIO_InitStruct = {0};8 p& ~3 E9 E6 H! q3 O( v
  10.     RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};4 y6 d$ s+ ~' G' M
  11.     DMA_NodeConfTypeDef NodeConfig;  u3 k3 }% H; t9 S! q' B
  12. . ^6 O* b: c9 S: w- G3 L
  13.     __HAL_RCC_LPUART1_CLK_ENABLE();( Q& G% h8 S1 x5 `! a
  14.     __HAL_RCC_GPIOA_CLK_ENABLE();
    8 I* |' H/ y9 m- W6 [: K. e% m
  15.     __HAL_RCC_GPDMA1_CLK_ENABLE();# J: ^9 F' I; S6 w/ {4 `

  16. 9 E" Z! K4 Z5 J: V
  17.   PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;
    ! t/ G# Y/ p* c. b9 c  J
  18.   PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK3;3 v4 Q) b. y! {2 {" V
  19.     HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);: R, J) k) ?( h

  20. 4 ]; M3 V: \$ n- D/ O6 T( p
  21.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    : U: i0 Z+ _$ l
  22.     GPIO_InitStruct.Pull = GPIO_PULLUP;
    * N# Y! R1 J! {- Y" @* C3 n
  23.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    ( ^* t! Y- \  z5 X' y3 J. c
  24. </font>   <font face="微软雅黑" size="5">' Z: \3 ?* e- ~: V
  25.     GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;2 A) V+ T3 a5 X/ a: m  @7 O- T
  26.     GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
    - T& d1 s9 k! {1 h3 h: j
  27.     HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);1 `  L! ?4 c( k% p# f1 {
  28. </font>   <font face="微软雅黑" size="5">* O  I" J! E- V- \
  29.   hlpuart1.Instance = LPUART1;
    1 u( e$ J! b6 d
  30.   hlpuart1.Init.BaudRate = baud;
    ) ?' p8 D- U" a; F, h
  31.   hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
    ' k3 Z3 v: x& s2 g' d3 E
  32.   hlpuart1.Init.StopBits = UART_STOPBITS_1;/ M7 y# m/ f" b4 s4 Z3 z
  33.   hlpuart1.Init.Parity = UART_PARITY_NONE;( u2 o2 C! P( \! Z
  34.   hlpuart1.Init.Mode = UART_MODE_TX_RX;
    $ j  E3 \2 z# D  Q
  35.   hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
      b# ?: l5 |/ z+ F; O6 U
  36.   hlpuart1.Init.OverSampling = UART_OVERSAMPLING_16;
    . U5 L% n1 A8 d5 r/ J
  37.   hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;* o3 B0 A9 Y+ d1 t* ?0 r5 ~7 N
  38.   hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    ( P1 \4 B$ v" u' D0 C% C: C
  39.   hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    * N8 Y& l6 r7 Z- J
  40.   HAL_UART_Init(&hlpuart1);: W2 W  f% Z$ s; w
  41. </font>   <font face="微软雅黑" size="5">
    - G3 A( f/ b* q
  42.     __HAL_UART_ENABLE_IT(&hlpuart1 , UART_IT_IDLE);
    ( M. m; y8 L6 @& N9 M4 U" _
  43.     HAL_NVIC_SetPriority(LPUART1_IRQn,1,1);  n! T6 |$ P- j6 |$ U% w8 T
  44.     HAL_NVIC_EnableIRQ(LPUART1_IRQn);+ y0 C. Q2 e4 v. I/ S
  45. </font>   <font face="微软雅黑" size="5">; a2 R/ q( A& E/ z/ k! u* [
  46.     NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
    7 n  y! H) g) {* i3 ?; v5 Q( W
  47.     NodeConfig.Init.Request = GPDMA1_REQUEST_LPUART1_RX;: Z. K6 O& u; E% x' u6 k" B: Z9 _
  48.     NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
    8 c3 j3 x# h7 Z/ R1 S5 l1 z2 y
  49.     NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;. F% b9 J+ i  G6 K) H& X7 A
  50.     NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
    - a: P3 W! |: [2 p* Y- D' k5 ]
  51.     NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;* c. ]. ]# D1 p# {
  52.     NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;) E0 r: N5 i5 Z- y1 J3 C* w' }
  53.     NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
    : f  v' \+ o0 Z" T* I
  54.     NodeConfig.Init.SrcBurstLength = 1;
    ) [. g, k  B( _/ F: B' k
  55.     NodeConfig.Init.DestBurstLength = 1;
    ! [5 O' A6 v  |' @/ ~1 X7 w
  56.     NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
    ' W' p- x6 R# _- B
  57.     NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
    ; E& v# ?: w6 I5 ^2 s- ^- d: s
  58.     NodeConfig.Init.Mode = DMA_NORMAL;
    9 y5 _6 x0 d5 R# }
  59.     NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;! ?- ~! P  G, L/ ^( q# i' J
  60.     NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
    " N' o  H% C6 I( M" T8 P) ~
  61.     NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
    ( W+ l# ]  U5 @; i6 |* Y
  62.     HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0);
    - t; c9 N* T! i. h
  63. ; `* q* r% u/ S2 G
  64.     HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0);; [) P$ \& V. [' r
  65. / j  i+ L" O, |+ z1 P3 b$ W
  66.     HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0);0 e+ O2 s1 U& t& O

  67. 8 V  R4 }+ d2 N# m+ m" y' g
  68.     handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;) ?  |! F8 b' P) w: i
  69.     handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;8 @5 a" ^7 v! [, r
  70.     handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
    . k. l- v3 N- L; h! r/ b
  71.     handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;, Z3 H2 G$ Q) q  w: p
  72.     handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
    5 Y/ A7 g8 c. x( M% t
  73.     handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
    ) _. H2 f. }) c' ]
  74.     HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0);
    2 T" l- f- G2 p( |; U

  75. 0 @3 N3 K. \& |( H7 l# ^
  76.     HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0);6 l* \6 T; T' v) h' S2 f
  77. , \- Q# }9 m5 g1 a5 b' x
  78.     __HAL_LINKDMA(&hlpuart1, hdmarx, handle_GPDMA1_Channel0);
    / }  A9 K$ E" n( L

  79. 8 p( t. d- K( x) w
  80.     HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV);: O! y: h9 h* I7 X4 t& M
  81. </font>   <font face="微软雅黑" size="5">. [1 |* W: m# ~
  82.     HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);  z  A6 Q! t/ V3 N! @$ r
  83.     HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);4 D  \8 f7 G0 [
  84. }
    $ q  r' k: S# B9 a4 y4 M

  85. 4 K9 V  |' [5 |9 [0 Q0 d! ]
  86. void LPUART1_Send_Char(uint8_t ch)3 B* o7 E$ W3 a0 x
  87. {
    3 [3 B' Y* z3 N& P
  88.     while ((LPUART1->ISR & 0X40) == 0);
    ' J: M; s5 D4 R7 e+ n. w9 e
  89.   LPUART1->TDR = (uint8_t)ch;
    9 i6 {( z6 M2 @. L0 h- y
  90. }5 }9 L9 h" q: Z1 }) O+ G( a

  91. , l' F( c; ^# `' H. g( v
  92. void LPUART1_Send_String(uint8_t * s)9 {3 j; f4 Z* I  g! y- t
  93. {# n4 o4 @4 @3 H; m
  94.     uint32_t i;
    1 w0 r' S, t; S7 N5 a- S! l9 Z! z* F0 @
  95.     for(i = 0 ; s != '\0' ; i++)7 P" d9 U: m* }0 @/ w
  96.         LPUART1_Send_Char(s);9 F4 }7 O# s) b0 K& n; Z: Q7 P! d2 D
  97. }! `+ J4 T# s$ B( Y
  98. 1 i! M0 r- J. e8 k% H7 W) A
  99. void GPDMA1_Channel0_IRQHandler(void)8 F9 M+ J4 P) L3 m' ^4 \0 A9 X
  100. {. L* I/ Z" Q* _- k: C" f6 g& b
  101.   HAL_DMA_IRQHandler(&handle_GPDMA1_Channel0);
    # S/ n" Z# A% V
  102. }
    ( u; q/ b6 C3 {, i
  103. 1 t: P$ y6 `8 M
  104. uint8_t aRxBuffer[RXBUFFERSIZE];
    ; @3 }" Z# s$ E4 J) J- T2 Q
  105. ' o/ K% o2 k1 @' x+ T1 J
  106. void LPUART1_IRQHandler(void)                    4 ~" i* d  A4 V# I  `3 f
  107. {
    $ Y6 ~+ r# U8 @( o1 i
  108. //    int temp;
    5 `3 i2 Q0 u) M4 y$ m
  109.     if(LPUART1->ISR & UART_FLAG_IDLE): ]. z% D3 l7 G* H
  110.     {, y1 W+ ^, ]6 |! h( n1 h  Y
  111.         __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);2 H6 b4 h* C' f: w4 F% g- H
  112.         printf("LPUART1_IRQHandler. %d %s\n" , GPDMA1_Channel0->CBR1 , aRxBuffer);
    , a3 h2 J$ k- ^, _: W/ _/ ?0 X
  113. </font>        <font face="微软雅黑" size="5">
    & {, ]$ c7 p$ G5 J; N
  114.         HAL_UART_DMAStop(&hlpuart1);8 j7 I7 ?2 e4 [
  115.         HAL_UART_Receive_DMA(&hlpuart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);
    0 e9 S( Y) S; p6 l
  116. //        rx1_len = BUFFERSIZE - DMA1_Channel5->CNDTR;, S- v9 U/ {! ^5 Q! E' B
  117. //        uart1_recv_end_flag = 1;
    2 h, y4 E9 U. O  o/ k& O) C/ D% f
  118.     }
    ! p1 V5 e- B+ f! Q( `( \$ G
  119. }</font>
复制代码
在ST的新系列里面,有个特殊机制,使用任何形式的DMA通信必须要打开DMA中断,这个在F103系列是不需要的,是F4以及之后的大部分系列都需要,另外,在F4之后的系列中,对于外设要用的DMA,可以自由配置通道Channel(流Stream/节点Node)等,其实是一个东西,就是DMA通道的意思,不同系列的名称不同,只有F103和F4系列的特定外设是绑定在特定DMA通道的。像本帖子,就把LPUART1的RX功能设置在在GPDMA的通道0(后续还把SPI1的TX功能设置在GPDMA的通道1)。
7 S& `$ j- {* H, K. Z) Z4 S7 d9 G8 a" ?  P  a& l  R/ A/ u' u
6.JPG
, t: {  D8 |" I+ H4 d
2 G9 J) r3 a, S: ^) o8 B# G看看运行效果,使用两根typec线分别连接开发板的STLINKV3接口以及用一个USB转TTL模块接在PA2 PA3引脚上:" g0 A; g. A/ h, y; z  E! Z, a
7.JPG IMG_20250523_174406.jpg % O# G( X, c! X& B  X9 ?
首先上电之后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管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版