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

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

[复制链接]
donatello1996 发布时间:2025-5-23 17:55
     拿到了nucleo-U385开发板,在KEIL环境下编程,需要下载CubeU3支持包,在ST官网即可下载,并且在CubeU3支持包内还有KEIL环境所需要的pack安装包,这个应该是最近才做的一个方便开发者开发的一个机制:& d. j. Q: s: Q9 V
1.JPG
$ z5 K6 _- i1 Z) O( d0 T% P) V我直接用点灯的例程来改串口例程,方便省事:6 H! k* c( D9 f8 W4 Y
2.JPG
4 j$ W5 o! [5 x+ a整理好的例程结构如下:
6 I; v' ?# A6 ^1 b  r7 S2 l0 z
3.JPG ) z* }1 t$ }( z$ r. [
根据原理图可以得知,开发板的STLINKV3 VCP连接的串口是UART1,即PA9 PA10,可以直接与电脑的串口助手进行通信,另外开发板上还有PA2 PA3引脚,这个引脚被复用为LPUART1:
- {  K1 {, ]4 h, c9 `: a9 Q0 O' D$ @; V
4.JPG 5.JPG
2 L& q9 V. _* M) p% b% j我这个帖子就实现UART1和LPUART1的双通道串口通信,其中把LPUART1的接收功能打开,使用空闲中断和DMA进行接收,先看看UART1的初始化代码:
  1. <font face="微软雅黑" size="5">UART_HandleTypeDef huart1;% X) }; I& o1 ^0 f" m% e5 M

  2. 7 [6 l% j& i& F1 V# _* s% H% @
  3. int fputc(int ch , FILE *f)
    ' `; E; }' h2 ^8 ^6 N5 |
  4. {
    ( Z' r! D; |$ Y5 X# u
  5.     while ((USART1->ISR & 0X40) == 0);2 ~2 d. o9 T3 T8 _6 l
  6.   USART1->TDR = (uint8_t)ch;9 _! v. m; ?1 C, k1 o/ j& p, G) Z
  7.     return ch;; R, l  E+ D4 ]+ W
  8. }. N2 N, [- _( r6 E0 b( R
  9. 1 `: B8 J6 f7 P5 R
  10. void UART1_Init(uint32_t baud)$ j0 B0 T* W( v  E& f
  11. {' C% Q6 m& [9 A
  12.     GPIO_InitTypeDef GPIO_InitStruct = {0};
    $ L" F: n2 q/ L
  13.     RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    + D- R$ V! r' s# k( C. G; [+ d; q

  14. 7 ^' Z* C) i( T' o/ R: ?  Y
  15.     __HAL_RCC_USART1_CLK_ENABLE();
    " K* D: E, c2 L! A; M) h
  16.     __HAL_RCC_GPIOA_CLK_ENABLE();) x0 x7 m8 ?6 B2 e5 t+ X. }, d/ }! w

  17. 0 {; G; N( H( u, Z0 O* y2 d8 N/ ~
  18.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;0 c: ~# c3 D* {4 F- B& _
  19.     PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
    # u$ ]; C! f# F, v
  20.     HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);; E8 ?7 _; T3 @( b
  21. 9 Y3 B7 F( i8 T. a1 V. @4 D0 a
  22.     GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
    5 I/ t. b4 I  p! T( {
  23.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;3 H$ i% q! U7 M' ?) g# X2 k4 K" E
  24.     GPIO_InitStruct.Pull = GPIO_PULLUP;
    + ~. y& b; t" H4 ?/ n
  25.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    # Q/ _6 M, g, W2 s/ v" R$ {
  26.     GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    : \1 S- d4 i( O. |* C
  27.     HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
    ( O4 Y) r. P9 l0 N/ b- Q) H
  28. </font>   <font face="微软雅黑" size="5">* v! f  B7 O9 K
  29.   huart1.Instance = USART1;
    ! Q3 I3 O; }; a8 R+ [- L, X
  30.   huart1.Init.BaudRate = baud;
    # z0 E: ~9 r1 k. L+ l0 K7 J. x) e+ R
  31.   huart1.Init.WordLength = UART_WORDLENGTH_8B;
    2 M4 ]  o7 t* J( Q, H$ j
  32.   huart1.Init.StopBits = UART_STOPBITS_1;
    ) Z: \5 c$ D( N: \9 V9 X% m
  33.   huart1.Init.Parity = UART_PARITY_NONE;5 d8 u# [7 T: i  _6 L
  34.   huart1.Init.Mode = UART_MODE_TX_RX;
    1 i  g+ K: F6 i, H; ^
  35.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;; S, w- z  p# A
  36.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;$ v$ L. Y7 r" M8 f$ y! t( v5 F; N
  37.   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    6 ?4 }$ ^& _3 `" Z4 W! K/ f
  38.   huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    % \1 m! w* G6 w) ~. t
  39.   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    - W  T: C- R" g$ v1 A7 d7 `9 A! Y
  40.   HAL_UART_Init(&huart1);
    ; @! p- C: `( W/ `
  41. }</font>
复制代码
非常简单,只要熟悉STM32编程的没有一点难度,然后是LPUART1:7 O2 _! R! `% l! X! n: A# H
  1. <font face="微软雅黑" size="5">UART_HandleTypeDef hlpuart1;
    8 F! s, f: W- ?2 Y6 r

  2.   G. |1 ~  H% w- A  u& ?. V
  3. DMA_NodeTypeDef Node_GPDMA1_Channel0;2 n$ S  j/ w2 ?2 }" M
  4. DMA_QListTypeDef List_GPDMA1_Channel0;
    / ]3 H1 S! D  @
  5. DMA_HandleTypeDef handle_GPDMA1_Channel0;
    , ?5 M, O: T- X
  6. , s7 }7 t3 d4 o" I
  7. void LPUART1_Init(uint32_t baud)
    0 K6 \5 A. V% F% X
  8. {
    " d1 M  {0 ]$ _1 u9 H! ?6 _- \( G3 F& E
  9.     GPIO_InitTypeDef GPIO_InitStruct = {0};
    ) J: d8 T9 y/ l' X! V3 `2 ^
  10.     RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    $ j7 G* _5 ~; u: Y
  11.     DMA_NodeConfTypeDef NodeConfig;8 `5 p( Q0 P( \
  12. 0 ], p" j% b# ]4 u! f
  13.     __HAL_RCC_LPUART1_CLK_ENABLE();# J# R. j. v& s
  14.     __HAL_RCC_GPIOA_CLK_ENABLE();8 q# `; i2 X" R/ o4 ^) V+ i
  15.     __HAL_RCC_GPDMA1_CLK_ENABLE();
    ; D' o" ]4 A" ~+ F# R" Z7 `

  16. " v% T1 F- l2 K/ w+ ~! @' @
  17.   PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;  R) a9 c+ D# ^
  18.   PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK3;
    3 S; Q8 l( Z6 X/ w1 [: P% K. `6 R
  19.     HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);" Q3 \- B' f# [, c) h

  20.   D" N1 L- ?  |8 x4 a* ]
  21.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    " Z9 r( e! C, H% z6 q! z
  22.     GPIO_InitStruct.Pull = GPIO_PULLUP;& l) j" Y& }0 r7 j) e
  23.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    " P5 v9 s% w1 s
  24. </font>   <font face="微软雅黑" size="5">
    7 N9 X3 s8 }, |4 S+ o
  25.     GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;
    1 V1 k8 Z2 d& y. j" K, t# H- z
  26.     GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
    " ]5 y% B/ h- L- K8 t* K
  27.     HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);/ S! x# q; W3 B- m
  28. </font>   <font face="微软雅黑" size="5">
    9 l* P$ D% l3 f( S7 \; l6 N' X
  29.   hlpuart1.Instance = LPUART1;
    2 r  r- a: Y4 V( Y6 R+ H$ T6 {( y% i
  30.   hlpuart1.Init.BaudRate = baud;
    1 J2 f' \# Y6 W: W* i
  31.   hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
    1 O8 G# e1 b  g
  32.   hlpuart1.Init.StopBits = UART_STOPBITS_1;1 t2 E  K1 o2 o1 k  E8 w
  33.   hlpuart1.Init.Parity = UART_PARITY_NONE;
    $ `8 Q. z; P5 ?' _- F  z
  34.   hlpuart1.Init.Mode = UART_MODE_TX_RX;1 \) z" i. X/ Q/ @( `
  35.   hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;" _" e/ k& ]: ]( u* R$ E$ _' l* h
  36.   hlpuart1.Init.OverSampling = UART_OVERSAMPLING_16;
    9 j! G$ ?2 ~+ w! x
  37.   hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    & \- h5 k% m( c+ w9 n
  38.   hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    # ]2 N6 @; y) Q9 x
  39.   hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    ) T) C; {4 k8 O  M
  40.   HAL_UART_Init(&hlpuart1);
    4 @( g$ M, t6 S6 F8 ]6 K* w0 \1 x& w
  41. </font>   <font face="微软雅黑" size="5">/ [' G1 L4 W4 n
  42.     __HAL_UART_ENABLE_IT(&hlpuart1 , UART_IT_IDLE);
    / C4 }+ O' T. I
  43.     HAL_NVIC_SetPriority(LPUART1_IRQn,1,1);
    2 l. x/ T6 e; }& I( @: D/ C3 ]
  44.     HAL_NVIC_EnableIRQ(LPUART1_IRQn);% i: Z. h4 R, o4 P8 A% }
  45. </font>   <font face="微软雅黑" size="5">
    0 V9 G9 p" Y. P6 `9 d
  46.     NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
      z7 Z: Q7 n( {4 e0 C2 i# k9 z
  47.     NodeConfig.Init.Request = GPDMA1_REQUEST_LPUART1_RX;/ m; V% m1 y( A+ X/ S4 C
  48.     NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;6 w9 s) |5 K' W5 d9 k
  49.     NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;( g- p7 `" h* B
  50.     NodeConfig.Init.SrcInc = DMA_SINC_FIXED;) X$ x# F7 V+ K! v
  51.     NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
    ! d8 h$ \3 ?5 E) b* B& ?
  52.     NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;+ S# H* d3 `- K2 n9 h) ?
  53.     NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;. X; d) a/ [0 Y1 h! c$ _% A
  54.     NodeConfig.Init.SrcBurstLength = 1;
    , N- y- ~5 W# }& Q; p7 ^
  55.     NodeConfig.Init.DestBurstLength = 1;
    % u7 |2 }* b8 b; V6 M8 }/ M/ M
  56.     NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;) Q6 [0 V- V+ Q9 M1 i4 }) j: y5 v
  57.     NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
    5 o6 E& h6 g0 ]6 e
  58.     NodeConfig.Init.Mode = DMA_NORMAL;
    + C5 \. l) \$ N& y4 J  j
  59.     NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
    6 }9 E  @6 o+ k2 H5 ^7 p4 P
  60.     NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
    . \/ d6 f5 I+ Z' `+ H) U
  61.     NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;- D- O9 s! n; \
  62.     HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0);% d* }: T) {" O! I

  63. ) F$ l# l+ C% Q  g" L6 }) {
  64.     HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0);
    3 w9 t4 A' t& ?' u6 ~  z. y0 X
  65. : o0 e+ `+ \' V( a' t( ~9 d
  66.     HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0);6 X. h6 E6 y% b! z. ?
  67. , R. s' N+ l# _) N  u  }+ r: A$ A" v
  68.     handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
    ! p4 T. H7 `* Z& Y: a, o
  69.     handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;0 R( p: d9 z- m# R
  70.     handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;5 g/ L1 P$ N% }1 ~7 o
  71.     handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;6 J( N$ W6 Z6 }9 I
  72.     handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;+ I: A8 D# E4 n. F
  73.     handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;- g1 h4 N! k  c4 g2 H* ]; G
  74.     HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0);5 [2 Q- F! ]  }2 v

  75. 9 A9 k+ b7 U2 r% k! h: K1 I
  76.     HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0);: G/ \3 w  I; z0 G3 T
  77. 2 A/ N8 m' U9 p/ W3 i- A5 O) B
  78.     __HAL_LINKDMA(&hlpuart1, hdmarx, handle_GPDMA1_Channel0);
    2 ]: p! X6 C% I( q

  79. 4 ?+ \6 t) g  J, t
  80.     HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV);
    % E( B" d( S# z( b( X
  81. </font>   <font face="微软雅黑" size="5">0 h* r: {; P+ i7 D, G
  82.     HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);/ y  Y! b9 B; _( I9 M7 V: G
  83.     HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);* Q& P6 J0 H8 I8 L# N
  84. }
    ' [' }6 S' a8 L$ d% ]: q

  85.   Z1 I  ~4 c% V/ z! ~& N, m2 j& w
  86. void LPUART1_Send_Char(uint8_t ch)
    0 M/ A% ?- M: b! O, L+ O  V
  87. {
    , k% \/ u" f, z' \" B: U
  88.     while ((LPUART1->ISR & 0X40) == 0);# o4 F- {. \. F4 c/ c5 J' m  j
  89.   LPUART1->TDR = (uint8_t)ch;
    2 ]& T/ O! v3 d. u3 K- m7 q
  90. }
    : Z% X* M4 E" e7 X$ y  X7 b. u

  91. + M2 d; d5 @* D! n5 F3 v
  92. void LPUART1_Send_String(uint8_t * s)' I. Z7 N! x1 u! O) F( D3 C
  93. {
    0 v+ n: r/ m  I7 ~4 G+ o
  94.     uint32_t i;
    : [5 e+ x) G' c8 w
  95.     for(i = 0 ; s != '\0' ; i++)
    ) W* C6 J, |' E9 L& Y2 E
  96.         LPUART1_Send_Char(s);
    % h, t6 w( J: E
  97. }3 I# l' }+ M. b' a, @4 C  i

  98. 8 S- h- z  X" f1 c7 a
  99. void GPDMA1_Channel0_IRQHandler(void)
    2 Z: R( t9 k/ W3 d: j3 }( S4 E
  100. {# X, b$ [0 R* j/ `+ M7 y* o3 B- x
  101.   HAL_DMA_IRQHandler(&handle_GPDMA1_Channel0);
    $ f7 @4 R# O( X. {6 {. L
  102. }0 r0 D$ f4 u; h4 B0 L
  103. + ^0 y' v5 R) w) u- z
  104. uint8_t aRxBuffer[RXBUFFERSIZE];
    1 e/ O0 F8 X! q+ `' \$ c6 I

  105.   B+ C& b5 y, l0 y6 f1 _4 P; o
  106. void LPUART1_IRQHandler(void)                    9 ^! E9 H8 J5 [. R3 |8 n
  107. {
    2 M7 c8 ?0 c; h8 m% S5 K
  108. //    int temp;
    ( W4 Z" L) y% k* v0 m0 A: I
  109.     if(LPUART1->ISR & UART_FLAG_IDLE)
    % q" {( t$ H5 T, {# s2 J
  110.     {
    " z  T+ m6 O' k+ _" P# m
  111.         __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);
    * R4 h( ~7 l% `: |, o
  112.         printf("LPUART1_IRQHandler. %d %s\n" , GPDMA1_Channel0->CBR1 , aRxBuffer);
    ) p) A' B* I1 }
  113. </font>        <font face="微软雅黑" size="5">; \4 Q% h* o  V/ j
  114.         HAL_UART_DMAStop(&hlpuart1);9 R: c" V* L- t, d
  115.         HAL_UART_Receive_DMA(&hlpuart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);9 A: N$ K/ f# d" l- |5 ~
  116. //        rx1_len = BUFFERSIZE - DMA1_Channel5->CNDTR;0 q( b: \- y0 v* I3 C* W7 k% s
  117. //        uart1_recv_end_flag = 1;  b6 m: k" ?; M8 A8 {: f! Y
  118.     }) @  g% I  u8 n  g% d' V  z  e
  119. }</font>
复制代码
在ST的新系列里面,有个特殊机制,使用任何形式的DMA通信必须要打开DMA中断,这个在F103系列是不需要的,是F4以及之后的大部分系列都需要,另外,在F4之后的系列中,对于外设要用的DMA,可以自由配置通道Channel(流Stream/节点Node)等,其实是一个东西,就是DMA通道的意思,不同系列的名称不同,只有F103和F4系列的特定外设是绑定在特定DMA通道的。像本帖子,就把LPUART1的RX功能设置在在GPDMA的通道0(后续还把SPI1的TX功能设置在GPDMA的通道1)。
6 w. r0 Z2 G, _2 l2 f' m+ v- @+ L, h6 U4 f
6.JPG . h* C- a5 f) r0 D8 k# e" d- ~
: P3 z: t/ E- W! X& t
看看运行效果,使用两根typec线分别连接开发板的STLINKV3接口以及用一个USB转TTL模块接在PA2 PA3引脚上:% J( I  Y* e- P0 F. ]
7.JPG IMG_20250523_174406.jpg / u+ z: Q7 y0 T- b+ z/ H/ s
首先上电之后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 手机版