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

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

[复制链接]
donatello1996 发布时间:2025-5-23 17:55
     拿到了nucleo-U385开发板,在KEIL环境下编程,需要下载CubeU3支持包,在ST官网即可下载,并且在CubeU3支持包内还有KEIL环境所需要的pack安装包,这个应该是最近才做的一个方便开发者开发的一个机制:- C; s) h3 j. T5 R; Z$ K, |& X
1.JPG
5 P  N$ L2 P' ]! g8 E9 V. t5 i我直接用点灯的例程来改串口例程,方便省事:
  t* b" _- J2 N4 j$ J
2.JPG 0 D, v: [$ W1 ^0 B3 N
整理好的例程结构如下:8 w/ w& Y( K* W* w* B- s: p
3.JPG 2 `5 V# w. }% B3 O. E
根据原理图可以得知,开发板的STLINKV3 VCP连接的串口是UART1,即PA9 PA10,可以直接与电脑的串口助手进行通信,另外开发板上还有PA2 PA3引脚,这个引脚被复用为LPUART1:" p4 ]" ]* ~5 X9 u
4.JPG 5.JPG
, _, @  C! m4 v: ^8 q& u3 v: D我这个帖子就实现UART1和LPUART1的双通道串口通信,其中把LPUART1的接收功能打开,使用空闲中断和DMA进行接收,先看看UART1的初始化代码:
  1. <font face="微软雅黑" size="5">UART_HandleTypeDef huart1;" D1 l! F8 M4 p- \1 `' r$ I

  2. ! V7 X3 |2 y4 _" d
  3. int fputc(int ch , FILE *f)
    ' h/ l1 e" ^" v  V% V8 P
  4. {
    3 F$ z# t% K  h1 }, k
  5.     while ((USART1->ISR & 0X40) == 0);
    ) k% }; S' j2 Y" ^% v1 ~- O3 {) m
  6.   USART1->TDR = (uint8_t)ch;
    % o+ V: u- y  n+ X; P" m8 x% n
  7.     return ch;( P/ z- n& _" Z" K
  8. }' c1 v; y' T% [# U  {
  9. 9 S  B# U, v: y" M& k& ~
  10. void UART1_Init(uint32_t baud)
    ; f8 {* j4 y- ]0 Z7 F
  11. {: ~' M2 \$ W4 }  q( h; i& ~3 q
  12.     GPIO_InitTypeDef GPIO_InitStruct = {0};. t) Y2 }! X2 b. |" i
  13.     RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    $ e, l( }" f# y7 F9 h3 r$ h% m
  14. 8 \/ y' K2 e8 e! A) M3 F% T! K
  15.     __HAL_RCC_USART1_CLK_ENABLE();
    5 |# l+ s2 D+ r, ^
  16.     __HAL_RCC_GPIOA_CLK_ENABLE();
    5 z# Q- y% W1 ]& H6 \
  17. 0 _# K# L0 c* U, E# C. d7 R
  18.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;6 y) w1 e: z' c1 j  b) v" I
  19.     PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
      m5 n! C$ `4 I  u, i2 }" m
  20.     HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);1 V! y* R- m4 m- x! H  I5 V
  21. ) D+ e4 |! B$ B2 p2 H7 w  |
  22.     GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;. W7 E, F  ?9 O0 f$ h
  23.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    9 x( o/ s  [# L  ~9 Y& o1 _( _
  24.     GPIO_InitStruct.Pull = GPIO_PULLUP;/ O+ m+ p4 R" E, X. W% h6 N$ F
  25.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    : a9 ~7 z: j- L  j9 J& ?6 V
  26.     GPIO_InitStruct.Alternate = GPIO_AF7_USART1;0 s2 z) |; M$ ^
  27.     HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
    6 \" o; t5 A- _
  28. </font>   <font face="微软雅黑" size="5"># I% Z$ \: b( N$ g/ M
  29.   huart1.Instance = USART1;1 a+ t5 A) q  M* M" K  Q6 v
  30.   huart1.Init.BaudRate = baud;
    ' \/ _$ Z2 J* E6 `% B. E' O" j" v
  31.   huart1.Init.WordLength = UART_WORDLENGTH_8B;
    7 H- G% m& c' W4 P: S
  32.   huart1.Init.StopBits = UART_STOPBITS_1;+ O0 f5 Q: c, L8 ~3 t
  33.   huart1.Init.Parity = UART_PARITY_NONE;1 {, B. ?( o* u" a
  34.   huart1.Init.Mode = UART_MODE_TX_RX;
    ( x% Y  U3 W5 m! O) m- T7 @$ O: c
  35.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    " O# d, J6 a5 O4 ~& l5 G5 E
  36.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    ) k4 o* P% \5 P1 F- m
  37.   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    3 @( o. f5 S  m, _2 H
  38.   huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    % ]! [9 c  P- Q& u" h% K
  39.   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;/ o7 ], n" j% X7 Z3 g- h# A) x
  40.   HAL_UART_Init(&huart1);
    2 O1 g' b/ O9 C2 [* o& g3 _
  41. }</font>
复制代码
非常简单,只要熟悉STM32编程的没有一点难度,然后是LPUART1:* o  J  T/ ?( j2 M
  1. <font face="微软雅黑" size="5">UART_HandleTypeDef hlpuart1;- V/ Z, R& C  |7 [  m% G! e

  2. : o- Q. p' ^) C  D1 m, e
  3. DMA_NodeTypeDef Node_GPDMA1_Channel0;
    * \5 i' L" g" h
  4. DMA_QListTypeDef List_GPDMA1_Channel0;
    # K* Z4 O& b  @3 a% s
  5. DMA_HandleTypeDef handle_GPDMA1_Channel0;
    * `6 b2 b- n: N

  6. 5 M* j4 {+ z. g8 P( L" V2 W  l
  7. void LPUART1_Init(uint32_t baud)
    : ^9 }2 t% f; m( Y
  8. {
    " c2 x% a6 T$ P& S" B% I" G
  9.     GPIO_InitTypeDef GPIO_InitStruct = {0};
    # i3 b# g4 E' s" r9 f
  10.     RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};9 K6 w2 |( z3 e6 T0 E
  11.     DMA_NodeConfTypeDef NodeConfig;, B7 [% G. t/ L) H/ L! O6 t; ]# I
  12. ! r2 F1 A- N. P5 Q
  13.     __HAL_RCC_LPUART1_CLK_ENABLE();: p% c8 m7 }' `' {6 |4 x+ H* B( r
  14.     __HAL_RCC_GPIOA_CLK_ENABLE();: x. T  `3 b* e# V# K
  15.     __HAL_RCC_GPDMA1_CLK_ENABLE();0 [$ e$ [: G2 D: \4 D
  16. ; \: y6 F5 j' t9 u. ~+ V! N2 d6 {
  17.   PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;
    / }9 Q; v2 {( p- w) ^6 a2 c# T; l$ E
  18.   PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK3;, H, m8 l$ U2 v
  19.     HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
    ) k/ [+ G8 O3 _$ B0 Q! l* b: j

  20. / L( @! q/ H( u. K
  21.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    ! l! I! }' u. d6 ~4 W! K
  22.     GPIO_InitStruct.Pull = GPIO_PULLUP;1 _' L" k* W. m( k
  23.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;2 Y+ P2 r! B; x
  24. </font>   <font face="微软雅黑" size="5"># {; T) V8 @) Y' C
  25.     GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;
    4 u/ N; e- L/ O- v! {5 R
  26.     GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
    5 T6 Q9 a0 Q* b
  27.     HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
    0 K- p0 ~- b2 b9 v
  28. </font>   <font face="微软雅黑" size="5">
    7 H7 A, R0 f1 @* k
  29.   hlpuart1.Instance = LPUART1;2 X/ a  @+ a4 s: k! S5 W
  30.   hlpuart1.Init.BaudRate = baud;
    & z8 ]* t6 Z& s+ Z3 \# g% v
  31.   hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
    ; |" N7 v) q- k0 e
  32.   hlpuart1.Init.StopBits = UART_STOPBITS_1;0 m- q/ O) j' r( \; G
  33.   hlpuart1.Init.Parity = UART_PARITY_NONE;+ h* ?- ?+ D& ^9 V5 @7 G
  34.   hlpuart1.Init.Mode = UART_MODE_TX_RX;+ `/ ^3 ]: y9 a( w+ @5 O) p0 S
  35.   hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;# `( t' P& t! V2 r3 Q. \/ V& `
  36.   hlpuart1.Init.OverSampling = UART_OVERSAMPLING_16;$ y, c) ~, T8 z
  37.   hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;) P8 Z  ^% s8 ]8 d
  38.   hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    : u  |5 M6 I& {8 M3 e% X
  39.   hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;  N% ^; m8 p; ^% e  k/ B1 Q
  40.   HAL_UART_Init(&hlpuart1);
    6 J( q7 ?6 N6 Y, T! T2 `
  41. </font>   <font face="微软雅黑" size="5">8 @% t, w2 ]8 [9 ]: W
  42.     __HAL_UART_ENABLE_IT(&hlpuart1 , UART_IT_IDLE);
    ' t; W, j# I/ t0 l: k6 \7 j* Z. J
  43.     HAL_NVIC_SetPriority(LPUART1_IRQn,1,1);
    ' |$ l) K- |# ?+ `& `
  44.     HAL_NVIC_EnableIRQ(LPUART1_IRQn);* E* V; _( F1 ?. F+ z
  45. </font>   <font face="微软雅黑" size="5">4 y; o) A! x3 ]# d6 \
  46.     NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
    3 G) R+ l7 }6 A7 b9 e
  47.     NodeConfig.Init.Request = GPDMA1_REQUEST_LPUART1_RX;
    , f1 W5 Q9 U! O" B
  48.     NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
    ; [* L& ^3 S' @  X0 `  I5 m2 s6 h
  49.     NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
    0 A0 f, n! j' T
  50.     NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
    + y* R2 }/ P, M
  51.     NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;! C+ h8 i9 {" h! s8 l
  52.     NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;! p- y0 M( t  y+ @
  53.     NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;) x3 k. H" y1 d, o8 h
  54.     NodeConfig.Init.SrcBurstLength = 1;% R: D7 @) n# B% W9 T  \! \4 R
  55.     NodeConfig.Init.DestBurstLength = 1;
    3 _( J4 G% G9 z
  56.     NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;& J7 h& d9 W* i' }1 f
  57.     NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
      f9 L6 ]  h1 E) K- m1 Y* B
  58.     NodeConfig.Init.Mode = DMA_NORMAL;
    ( I4 f* v% i; f! k3 R6 i: [5 Z# e
  59.     NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;! t1 ~( T* B* D1 g* E
  60.     NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;7 G3 O! |9 [  Y0 l) E% i9 O7 t* u9 `
  61.     NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
    + w  y  P3 }0 _: @" z: G
  62.     HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0);
    2 ^, \% o# I* E9 q

  63. 2 `- g0 b9 b' L
  64.     HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0);
    1 Q# M6 j6 D8 D) B% @* \

  65. # c" ]. o: Y7 g+ Q* ~% ^
  66.     HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0);4 J* U/ I0 E& S; h: m
  67. - s0 a2 I. ]2 w5 ^5 O
  68.     handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
    2 Z) r- X5 k$ V
  69.     handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;0 G3 p6 v6 p1 R- f( W7 C
  70.     handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;) ?+ A/ ^* T9 L0 f0 c6 h
  71.     handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
    7 k/ @4 }! L3 S9 g) V' M
  72.     handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;; ?: G5 t: d* a
  73.     handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
    9 C1 E: R- Q1 q; j8 ^" r6 r, s$ e
  74.     HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0);
    ; Y1 X1 v3 D! b
  75. . V. l3 ~  \7 o
  76.     HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0);
    0 [$ |8 |/ x$ D5 j

  77. + }' g( g1 T2 @- N6 f* {* ^
  78.     __HAL_LINKDMA(&hlpuart1, hdmarx, handle_GPDMA1_Channel0);" I6 ]: g6 i8 b
  79. % y4 S' X2 C" x* @3 Z8 M
  80.     HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV);, D7 _2 h6 i* T3 ~2 |
  81. </font>   <font face="微软雅黑" size="5">
    ' _8 w+ W" n1 n1 R4 D* I1 X- F* e
  82.     HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);7 Z+ D$ j, F9 @" b' S, l6 L
  83.     HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);
    8 q9 j4 e0 n" e- d, T
  84. }& B9 m& F$ }' Q8 w5 s  r
  85. - n5 p+ ~9 y# @3 |9 @
  86. void LPUART1_Send_Char(uint8_t ch)
    % ^  T9 t4 k6 L. F1 u5 |
  87. {+ w+ w3 ]' ?4 ^
  88.     while ((LPUART1->ISR & 0X40) == 0);
    # d2 K, S0 J& \, [
  89.   LPUART1->TDR = (uint8_t)ch;
    1 e0 l/ w" D! {4 b, X
  90. }2 _/ Y0 f9 c1 i8 ^6 L
  91. 9 d* S( a% P2 Z8 e- g/ \
  92. void LPUART1_Send_String(uint8_t * s)
    5 h7 z% v, Z% A2 ?& @5 j
  93. {
    ' O+ x! ?/ Q3 m& @% e
  94.     uint32_t i;/ ], x, @$ ?' @3 j1 F# Q
  95.     for(i = 0 ; s != '\0' ; i++)
    ( M7 x5 T1 a$ G
  96.         LPUART1_Send_Char(s);
    # ]4 b8 A9 g/ y( e7 V
  97. }, @) V, j3 O3 Y& M! Y  H
  98. 7 U  _0 T1 q) D% A- d
  99. void GPDMA1_Channel0_IRQHandler(void)
    0 p* {$ R5 l. e4 Q, d
  100. {
    8 W# p% l. a- l! w3 |$ v8 q! X
  101.   HAL_DMA_IRQHandler(&handle_GPDMA1_Channel0);
    , L+ ^* j+ O; A4 @1 z. f
  102. }
    8 M. Y1 u: n9 E

  103. # P6 \  [7 d0 C! Y, _& G# r4 ]! b* s
  104. uint8_t aRxBuffer[RXBUFFERSIZE];
    5 _; l: Y, B. u* P  O+ `

  105. 2 i( f6 F( E  a4 l; d1 r( J+ y; Y
  106. void LPUART1_IRQHandler(void)                    
    3 O) b# P! s8 |6 g/ ?- i: P# N
  107. {: B. g% R" k% P" ~$ z  E
  108. //    int temp;$ _' D4 f- L+ j! C% E4 A, Q
  109.     if(LPUART1->ISR & UART_FLAG_IDLE)$ o- e. W% i3 W1 @1 B
  110.     {1 R7 |. A* _* e0 ?$ h
  111.         __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);9 P2 L2 ]# ~! J( G2 j3 W
  112.         printf("LPUART1_IRQHandler. %d %s\n" , GPDMA1_Channel0->CBR1 , aRxBuffer);% o! r' d; p4 m: W/ c: o+ m4 M3 E
  113. </font>        <font face="微软雅黑" size="5">
    2 J, b/ D& f/ X; o
  114.         HAL_UART_DMAStop(&hlpuart1);
    ! H: O: a# X0 l. Y6 Y1 l* ^
  115.         HAL_UART_Receive_DMA(&hlpuart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);
    / U  S3 T0 U9 F2 ~5 Z
  116. //        rx1_len = BUFFERSIZE - DMA1_Channel5->CNDTR;0 c& b' J" Q* a! h; f4 k
  117. //        uart1_recv_end_flag = 1;
    5 H0 U) h# @. t! v) Y: z# r! X" M
  118.     }
    : |4 k/ w! _, `6 q7 q6 x3 x
  119. }</font>
复制代码
在ST的新系列里面,有个特殊机制,使用任何形式的DMA通信必须要打开DMA中断,这个在F103系列是不需要的,是F4以及之后的大部分系列都需要,另外,在F4之后的系列中,对于外设要用的DMA,可以自由配置通道Channel(流Stream/节点Node)等,其实是一个东西,就是DMA通道的意思,不同系列的名称不同,只有F103和F4系列的特定外设是绑定在特定DMA通道的。像本帖子,就把LPUART1的RX功能设置在在GPDMA的通道0(后续还把SPI1的TX功能设置在GPDMA的通道1)。1 H8 l9 X8 o* w4 |
- ~7 h1 N/ H6 U
6.JPG
5 X3 K7 ]% K* p* i  }& G% P
3 V( a2 U% ~$ T' M看看运行效果,使用两根typec线分别连接开发板的STLINKV3接口以及用一个USB转TTL模块接在PA2 PA3引脚上:& b+ @( h+ F  k8 V
7.JPG IMG_20250523_174406.jpg & |/ G6 x' V& l+ H
首先上电之后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 手机版