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

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

[复制链接]
donatello1996 发布时间:2025-5-23 17:55
     拿到了nucleo-U385开发板,在KEIL环境下编程,需要下载CubeU3支持包,在ST官网即可下载,并且在CubeU3支持包内还有KEIL环境所需要的pack安装包,这个应该是最近才做的一个方便开发者开发的一个机制:1 l1 A- p0 n/ x- X/ j
1.JPG 6 r( k! {% ?, n7 l
我直接用点灯的例程来改串口例程,方便省事:! R. K7 d  }  W# l$ S9 a# M) Y: v9 F
2.JPG
# t& P0 l9 V/ x整理好的例程结构如下:
# f$ x# I. y  L( t4 D1 g# Z% G
3.JPG , i& j9 m; g8 F
根据原理图可以得知,开发板的STLINKV3 VCP连接的串口是UART1,即PA9 PA10,可以直接与电脑的串口助手进行通信,另外开发板上还有PA2 PA3引脚,这个引脚被复用为LPUART1:% m& M; A! `9 x/ V6 C4 ?$ T
4.JPG 5.JPG
5 F, X, y! ~5 _$ ?/ F4 ~6 ~7 A我这个帖子就实现UART1和LPUART1的双通道串口通信,其中把LPUART1的接收功能打开,使用空闲中断和DMA进行接收,先看看UART1的初始化代码:
  1. <font face="微软雅黑" size="5">UART_HandleTypeDef huart1;
    , X1 n% E4 X1 z6 h

  2. : i3 D, \4 p' b
  3. int fputc(int ch , FILE *f): x, k; y+ g6 L% @9 g
  4. {
    - j1 |) t1 g5 t7 o, ?
  5.     while ((USART1->ISR & 0X40) == 0);
      @% Q3 u) D4 y
  6.   USART1->TDR = (uint8_t)ch;( j3 i4 P6 _/ M& g3 k
  7.     return ch;
    " J/ g) b/ L. v- x8 O9 T" S
  8. }  {+ d' m% v1 `8 k& p
  9. 5 Z+ k: L. t3 B. d
  10. void UART1_Init(uint32_t baud)
    7 H! @8 T$ r' }7 ?) c  ^/ c; V
  11. {
    " H2 d/ m; i) J+ L
  12.     GPIO_InitTypeDef GPIO_InitStruct = {0};
      M7 m/ u; c1 F7 O* I5 H* G0 p
  13.     RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    ; \& K6 J' j3 [+ ^' o/ \& b) S
  14. 3 ?$ k0 X1 @0 e! O
  15.     __HAL_RCC_USART1_CLK_ENABLE();+ X6 c- i+ l$ G9 h- p
  16.     __HAL_RCC_GPIOA_CLK_ENABLE();
    : [9 }  d) e% n4 W$ J) v) A9 N
  17.   y0 H5 }$ f. h0 s
  18.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;+ ^! G. h" x: R$ L) s8 U' r/ h
  19.     PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;" f) i, B# d, m; P  B; S
  20.     HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
    & n, n" ~! H% x$ ]& S: y- E
  21. ' A$ S) g( j" F( i  g( M
  22.     GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;8 Q- Y( I( {( p1 I) c
  23.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;6 \$ }8 ~. w; `
  24.     GPIO_InitStruct.Pull = GPIO_PULLUP;
    . w3 V; e- f. G9 I$ ?, @
  25.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    ( I. w' ^" {7 F/ Z0 g
  26.     GPIO_InitStruct.Alternate = GPIO_AF7_USART1;' j4 h+ @1 V" T( o, K6 j  v4 t/ d& G, \
  27.     HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
    2 C: ~9 F2 `  }7 G6 q$ b7 q5 }
  28. </font>   <font face="微软雅黑" size="5">
    0 w. D2 \" v+ z$ z
  29.   huart1.Instance = USART1;& {% c: j' v3 m
  30.   huart1.Init.BaudRate = baud;0 C# D# X4 [1 O
  31.   huart1.Init.WordLength = UART_WORDLENGTH_8B;! H' ~  B) Y5 m$ q+ }) L# j% ?  ^
  32.   huart1.Init.StopBits = UART_STOPBITS_1;% y% K1 s8 U5 h  z3 J! q. V
  33.   huart1.Init.Parity = UART_PARITY_NONE;
    , h' Z1 o4 b+ K% V
  34.   huart1.Init.Mode = UART_MODE_TX_RX;  l/ ?+ \/ r# H& ?) R8 m! P0 S3 d
  35.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;6 K$ R0 Q, t1 k( }% C$ l+ P
  36.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;) v7 v4 {! s  R6 y. n+ n
  37.   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;8 _$ U" J7 x, Z2 H
  38.   huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    ; X2 T4 _! a+ M9 k
  39.   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    " E: M9 Y# \" e* j8 X8 B
  40.   HAL_UART_Init(&huart1);. L0 D: Q# L( H9 c
  41. }</font>
复制代码
非常简单,只要熟悉STM32编程的没有一点难度,然后是LPUART1:6 K( y% k. x3 Q" W; l, l% o! @7 p
  1. <font face="微软雅黑" size="5">UART_HandleTypeDef hlpuart1;
    3 c5 r( _# b5 p4 i6 x0 U
  2. 6 U) S1 R# z& Y9 L
  3. DMA_NodeTypeDef Node_GPDMA1_Channel0;
    2 f/ K( A% s) b
  4. DMA_QListTypeDef List_GPDMA1_Channel0;
    ! W4 C; p4 D5 u, v! d: E- V+ a
  5. DMA_HandleTypeDef handle_GPDMA1_Channel0;
    1 F) t  z4 e2 t3 Q. w/ a/ B  q

  6. ! X8 A) |- E& T) T4 r
  7. void LPUART1_Init(uint32_t baud)
    $ Z5 ?; t  g5 V( T8 X5 g
  8. {
    3 ]( T$ F5 K! k* M, V1 G7 X7 n
  9.     GPIO_InitTypeDef GPIO_InitStruct = {0};
    1 V- X/ H, R! T6 w  n8 N4 p
  10.     RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};1 n* j6 @" F, M) U. V7 T$ w
  11.     DMA_NodeConfTypeDef NodeConfig;7 l2 c2 e  q, V% Y

  12. * u: E) }7 G. h; i8 z$ I% W# H
  13.     __HAL_RCC_LPUART1_CLK_ENABLE();7 @. h: E1 F; y; G( p2 |# K
  14.     __HAL_RCC_GPIOA_CLK_ENABLE();4 N5 g! s$ X# D# \& ~
  15.     __HAL_RCC_GPDMA1_CLK_ENABLE();
    4 V& X1 v( q% c

  16. 7 E8 H: b; @$ D$ [
  17.   PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;' h, w, c" ~/ Q
  18.   PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK3;( ~' v) A7 k6 o( a6 I- x3 \- {" g
  19.     HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);5 g) S* N& v$ N

  20. & p- o$ W7 ?2 E) q# ~! D/ X
  21.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;1 s# [1 I( W9 h' |
  22.     GPIO_InitStruct.Pull = GPIO_PULLUP;" ^/ c% w/ R) F5 Q
  23.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    ; E7 {+ |( U& D9 ^* b' E
  24. </font>   <font face="微软雅黑" size="5">3 W, K; t" ?1 }. p4 O0 d
  25.     GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;" W! ?" w1 p0 |# I# q
  26.     GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;* k% O5 J- @; l9 O8 m) B) I9 R
  27.     HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
    6 q4 c7 e6 q3 {/ A+ z+ ^! ]: \( s
  28. </font>   <font face="微软雅黑" size="5">
    ' C2 I. H: n- |+ V
  29.   hlpuart1.Instance = LPUART1;$ m# a* C) Y4 T* i4 D5 e7 m- z
  30.   hlpuart1.Init.BaudRate = baud;$ ~% b1 h: b' a' I
  31.   hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
    # }" e7 Z& q, M
  32.   hlpuart1.Init.StopBits = UART_STOPBITS_1;+ p! s1 a9 ?8 S0 m" A4 Y
  33.   hlpuart1.Init.Parity = UART_PARITY_NONE;6 E( X0 e  k4 V$ B% S
  34.   hlpuart1.Init.Mode = UART_MODE_TX_RX;
    . [/ t/ u& N  e. @
  35.   hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
      U$ S2 O! y& {6 D. U3 _7 \- R
  36.   hlpuart1.Init.OverSampling = UART_OVERSAMPLING_16;
    % `$ j) i( c0 E6 p; H
  37.   hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
      K. T" f( b+ r* N5 r8 d- s- ]
  38.   hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    & ?( ^" K5 p! e6 |0 {, U5 @* J( Z3 m, A
  39.   hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;% x9 j, M. u5 D' a# X( c
  40.   HAL_UART_Init(&hlpuart1);
    + o: K8 m( @% j6 M( U1 x& I# Y
  41. </font>   <font face="微软雅黑" size="5">9 f; j( S! q/ k- k" v+ O, w
  42.     __HAL_UART_ENABLE_IT(&hlpuart1 , UART_IT_IDLE);. a& v3 D+ _7 U2 r9 \: X  u
  43.     HAL_NVIC_SetPriority(LPUART1_IRQn,1,1);% V! [& t2 q  @  m3 _
  44.     HAL_NVIC_EnableIRQ(LPUART1_IRQn);( Q% ?" \" M) e: u% d
  45. </font>   <font face="微软雅黑" size="5">
    - W# \( d6 _; G7 W$ r+ d
  46.     NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
    ; j( ]7 a% j0 p, ]5 l9 q
  47.     NodeConfig.Init.Request = GPDMA1_REQUEST_LPUART1_RX;
    - @- f, c5 T# _  V% O
  48.     NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
    ; s5 Z/ g0 @2 Y" j
  49.     NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
    % p. z: a) @' P) T$ Q
  50.     NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
    / x/ [" a  H3 a! q* `; X
  51.     NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;9 I6 f; g3 i7 d
  52.     NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;- K1 a3 [3 F+ f$ C1 E
  53.     NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
    / w: D  V/ \4 W0 ]: X
  54.     NodeConfig.Init.SrcBurstLength = 1;
    & t- i; }& f6 P$ r
  55.     NodeConfig.Init.DestBurstLength = 1;+ m1 l- o2 E6 b: l/ {4 N
  56.     NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;# |4 Q& a/ w, c" k! ~
  57.     NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;$ q- X/ V$ [& T" x
  58.     NodeConfig.Init.Mode = DMA_NORMAL;6 b/ y$ v3 Q, d
  59.     NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;( i' P# T" d1 m" M
  60.     NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
    # t* H0 j/ x$ Z; x1 v8 O7 m9 R
  61.     NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
    ! S; l6 v3 g9 u6 w$ E/ e2 h3 g
  62.     HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0);5 T. P# E3 n; \4 V; S6 {" N
  63. ; r4 h; K* f3 Z  y8 N. v) S( f9 d' P
  64.     HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0);) @! p( R7 b9 j! u3 W9 [
  65. # h: b( E/ A( R  u/ c  j9 u3 e
  66.     HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0);
      F) p" h4 y. i* I; P

  67. $ Q* J1 W; \4 V" s  H; i
  68.     handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
    ) o5 R7 ]) K4 Y! F/ f' f
  69.     handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;0 z! B3 h& B8 t) E% w- \( o7 C
  70.     handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;# w6 g3 |7 Z3 g6 j8 R& i! \' H6 y
  71.     handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
    9 x$ v: N2 a' P0 j
  72.     handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;0 Z5 [. M1 `% H2 J4 x" N! X
  73.     handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
    # }0 J" i6 }# W2 ^& U+ u: Q
  74.     HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0);) Z( @' R( C: C

  75. , [5 x  G/ a7 S& b
  76.     HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0);# n4 P  s( G+ g+ X; }0 z* S
  77. - e! ]2 i6 Y1 }! w3 o: l' s
  78.     __HAL_LINKDMA(&hlpuart1, hdmarx, handle_GPDMA1_Channel0);
    + n% E0 S5 s$ c9 Y

  79. 3 J: N" I9 v5 t# _9 ?
  80.     HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV);: o  _4 [( E+ n/ M" b3 b  d
  81. </font>   <font face="微软雅黑" size="5">3 {& z  w( n+ e0 t) u9 M
  82.     HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);) W  R/ E1 P- E) v  X) g6 |2 g1 q
  83.     HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);5 ?9 a: P2 x" A
  84. }
    7 N9 |8 Q: g8 `( v, {( N9 q
  85. 3 w0 T) d  q7 ?6 Y+ H
  86. void LPUART1_Send_Char(uint8_t ch)
    9 K( Q# A" o, R  }2 `
  87. {2 o1 o4 q, l. Y/ X" u6 L4 V( f
  88.     while ((LPUART1->ISR & 0X40) == 0);
    * z+ ^5 e, |( }! f: C/ P* y1 s
  89.   LPUART1->TDR = (uint8_t)ch;
    . ^) L8 }  i0 {5 B
  90. }
    % ?! ^) n- z1 t) A( E
  91. ( F- H  t9 @1 a4 l2 b$ S  h* N/ t
  92. void LPUART1_Send_String(uint8_t * s)$ g2 ?6 ~/ K, V5 F2 B+ u
  93. {# i- |! Y1 s" _! V
  94.     uint32_t i;
    - B$ \/ y7 @& f1 z8 g: N$ H
  95.     for(i = 0 ; s != '\0' ; i++)
    ' E' ?* M- n) [) ]
  96.         LPUART1_Send_Char(s);$ e" p8 N' i. a( |0 [
  97. }
    1 p/ f: W% g- u, m5 o
  98. ) h. A/ _* o6 r
  99. void GPDMA1_Channel0_IRQHandler(void)
    , ]. Y% E" X* z1 [! m
  100. {
    # @/ M2 L, n8 @' R
  101.   HAL_DMA_IRQHandler(&handle_GPDMA1_Channel0);
      h  L6 g9 _: y: ~. U5 D6 }  s$ q
  102. }& }; E( M0 R! h1 X

  103. 7 P! b7 {4 M& ^* a
  104. uint8_t aRxBuffer[RXBUFFERSIZE];2 U. D. j- a3 G0 H5 x

  105. 6 `7 ]1 {; g8 A" p2 Q3 V& P
  106. void LPUART1_IRQHandler(void)                    ) g! }, E, W8 d$ \7 P
  107. {2 D7 D: F/ R& G) E/ {: Q
  108. //    int temp;; y/ }2 I0 v7 y+ ^3 F3 R* l
  109.     if(LPUART1->ISR & UART_FLAG_IDLE)
    # E/ l; j" H* J0 O7 A+ Y7 j
  110.     {
    3 H8 i% r4 E, ~+ R* V: ?- C
  111.         __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);6 h* @; u, S' G. l/ |
  112.         printf("LPUART1_IRQHandler. %d %s\n" , GPDMA1_Channel0->CBR1 , aRxBuffer);8 V2 ^' k, G6 `, J2 |; m2 R0 p# ]& m
  113. </font>        <font face="微软雅黑" size="5">) p2 L+ c; n4 ~! n( N" |
  114.         HAL_UART_DMAStop(&hlpuart1);
    6 r& J# D" L3 ]# T3 I
  115.         HAL_UART_Receive_DMA(&hlpuart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);, K4 m& j$ {; @2 R4 j
  116. //        rx1_len = BUFFERSIZE - DMA1_Channel5->CNDTR;
    1 P0 a* I2 N6 q0 q+ k
  117. //        uart1_recv_end_flag = 1;% }9 a8 j# s  B: i! E# m
  118.     }
    % B  ]& f4 K6 W% n! 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)。5 f9 z, G8 z3 r* M$ e- o3 C
9 d) R5 h& V& n5 `3 G
6.JPG ! F% _$ X. @$ h6 P* d  C, w

, \  q, e. b- J$ z) h! H5 j看看运行效果,使用两根typec线分别连接开发板的STLINKV3接口以及用一个USB转TTL模块接在PA2 PA3引脚上:
/ V2 @' J) ^% w3 }0 }
7.JPG IMG_20250523_174406.jpg
/ i5 q5 {: r/ I/ A首先上电之后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 手机版