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

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

[复制链接]
donatello1996 发布时间:2025-5-23 17:55
     拿到了nucleo-U385开发板,在KEIL环境下编程,需要下载CubeU3支持包,在ST官网即可下载,并且在CubeU3支持包内还有KEIL环境所需要的pack安装包,这个应该是最近才做的一个方便开发者开发的一个机制:
4 R1 R1 Z, y& M
1.JPG
  A) ?$ \3 X) R我直接用点灯的例程来改串口例程,方便省事:1 C  z2 L% Y0 ^5 O* Y+ V: e
2.JPG
9 h; U: i' a) l) h5 d8 C4 \% `" f整理好的例程结构如下:
, N, c. Y! ]: N/ b# }" X5 U, j8 ~5 W
3.JPG 9 X9 n7 \" z5 K$ o6 `
根据原理图可以得知,开发板的STLINKV3 VCP连接的串口是UART1,即PA9 PA10,可以直接与电脑的串口助手进行通信,另外开发板上还有PA2 PA3引脚,这个引脚被复用为LPUART1:5 \" k. Z' J2 O
4.JPG 5.JPG
* _+ H# N" l6 e我这个帖子就实现UART1和LPUART1的双通道串口通信,其中把LPUART1的接收功能打开,使用空闲中断和DMA进行接收,先看看UART1的初始化代码:
  1. <font face="微软雅黑" size="5">UART_HandleTypeDef huart1;& C- y# Q/ x/ L& d0 k4 l0 ?

  2. + C* v2 d9 C7 ?- j( v. P, y% d* }
  3. int fputc(int ch , FILE *f)
    5 Z: w# V$ P: k# h( o
  4. {
    . y0 J0 O1 a( p( q$ c& l! Y
  5.     while ((USART1->ISR & 0X40) == 0);: I) {& c* }. \# v- _# F' Z$ P2 ^
  6.   USART1->TDR = (uint8_t)ch;
      V, \# b% M- D7 z* k
  7.     return ch;
    " l/ r3 _8 \3 K( T/ i2 c* P9 `1 L
  8. }
    9 e+ ~, @# \0 e2 w4 \" r8 d5 O
  9. ; I0 P  l/ W/ _, H8 n0 u
  10. void UART1_Init(uint32_t baud)
    4 T% g7 t; p6 G4 A5 Y$ t
  11. {
    ; Y9 H7 e4 i( l
  12.     GPIO_InitTypeDef GPIO_InitStruct = {0};
    $ q4 v+ g2 u/ I: L
  13.     RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    ) e; s3 h& ^; m/ r- `2 v3 X( {
  14. 8 C' |" u+ B' I& U$ d
  15.     __HAL_RCC_USART1_CLK_ENABLE();2 X5 i# M  T2 s1 _9 ~  w
  16.     __HAL_RCC_GPIOA_CLK_ENABLE();
    3 G& i9 M* |; n
  17. ( o. Z4 T7 j1 I2 A) y7 I! _
  18.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;0 S0 A  k% X* a! Z; D5 Z5 ?
  19.     PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
    $ }" c1 b; U& C2 Z* \7 g
  20.     HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);* x# n% H/ B) g3 L' a

  21. . m3 @" U& m4 _- L
  22.     GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;; r: [3 x$ l7 [, B  R, b  \9 F
  23.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;# {* z6 M, P# j; G( `! ^4 Z  V
  24.     GPIO_InitStruct.Pull = GPIO_PULLUP;) T1 b) V1 l. r. G
  25.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    / s9 s6 }4 Q9 p; P8 v  M3 O
  26.     GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    9 u- i' d8 q7 I  f. \
  27.     HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);& H+ G+ I6 d# C, z; S
  28. </font>   <font face="微软雅黑" size="5"># t; O- z9 Y+ E8 p
  29.   huart1.Instance = USART1;
    9 G+ C5 c! O5 W) C1 s
  30.   huart1.Init.BaudRate = baud;
    : W" G  s5 J, D
  31.   huart1.Init.WordLength = UART_WORDLENGTH_8B;8 t6 l  w2 \5 d% b6 c3 y7 i+ P; h
  32.   huart1.Init.StopBits = UART_STOPBITS_1;1 Z- I2 q6 `; u+ Q+ D
  33.   huart1.Init.Parity = UART_PARITY_NONE;
    , O* d. U+ K4 B6 y5 M6 F
  34.   huart1.Init.Mode = UART_MODE_TX_RX;3 _* L# v/ g  d! j3 S' ^: z
  35.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;* u7 v2 B7 U7 L) D6 S/ }0 G  ]
  36.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    / w4 j2 p( c7 S5 Z* x8 ^4 `9 }
  37.   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;; C* Q) r  P( C' D& ?5 I) q" H
  38.   huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    2 ]+ z: w4 @& n
  39.   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    " V9 O" o, F3 q! I5 X& \; @* e! L, J5 G
  40.   HAL_UART_Init(&huart1);( a/ L4 o; a8 Z* k
  41. }</font>
复制代码
非常简单,只要熟悉STM32编程的没有一点难度,然后是LPUART1:
( K$ h, a# z' r5 W7 M
  1. <font face="微软雅黑" size="5">UART_HandleTypeDef hlpuart1;
    1 Y' s8 A. b% O& V* S2 p5 m

  2. 1 W' s: ~& o; w: O5 R) r3 d
  3. DMA_NodeTypeDef Node_GPDMA1_Channel0;' m1 z( ~+ U2 g! }8 V6 p
  4. DMA_QListTypeDef List_GPDMA1_Channel0;  o5 I6 c* ]: _, s3 h& r0 Z3 @
  5. DMA_HandleTypeDef handle_GPDMA1_Channel0;
    % T8 P3 k) x9 H" }1 }
  6. - L! o5 W1 ]! q1 r; R/ }& G& |
  7. void LPUART1_Init(uint32_t baud)
    # P" P4 Y5 k' K& y5 |% {
  8. {# Q5 |  O* o0 n3 g
  9.     GPIO_InitTypeDef GPIO_InitStruct = {0};
    ! U/ g- A9 f6 B  v" T1 F* @3 J
  10.     RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    * u- k) Q# p8 M9 ^9 F5 X' ~
  11.     DMA_NodeConfTypeDef NodeConfig;
    : Z9 V6 }3 h9 u! M: T! D3 M' W

  12. " d+ j& l( u- x& T5 b9 i
  13.     __HAL_RCC_LPUART1_CLK_ENABLE();
    0 b0 }9 x6 P6 b$ T& Y; ]  I
  14.     __HAL_RCC_GPIOA_CLK_ENABLE();
    + c# C  a  K# o- t1 v* E: X- x
  15.     __HAL_RCC_GPDMA1_CLK_ENABLE();
    $ U$ [* ?  [# {6 U, p0 v

  16. 3 a" t  q( A$ y( I" ^
  17.   PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;& b! u0 z/ G, ~% n- `" x
  18.   PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK3;
    & {& v+ s2 z. }9 P' Z- Q
  19.     HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);! `, F1 {: w  j! v
  20. # N1 _& @) R0 v, h( G& M7 I
  21.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    % a( }  H1 C6 m5 C4 B; Q
  22.     GPIO_InitStruct.Pull = GPIO_PULLUP;
    - T8 z, g6 S" d. T& {9 Y; n& w1 i( `
  23.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;2 Z1 A5 e3 @7 [% e  t
  24. </font>   <font face="微软雅黑" size="5">9 t1 s) `% b2 f4 w
  25.     GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;5 O# K) t- S6 x. E: [
  26.     GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
    , g0 H2 H! C% d( {5 @( I# H
  27.     HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
    + U! n4 U- o8 \; R# Z" Q
  28. </font>   <font face="微软雅黑" size="5">7 j6 }  \- Q8 g$ D
  29.   hlpuart1.Instance = LPUART1;; q; d: e+ `$ y- g3 F: L
  30.   hlpuart1.Init.BaudRate = baud;! b1 g: b) X  c
  31.   hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;2 Q2 U  }: `' H, a! `+ ^7 F
  32.   hlpuart1.Init.StopBits = UART_STOPBITS_1;
    - B% Y3 g+ h' b7 a) G) E
  33.   hlpuart1.Init.Parity = UART_PARITY_NONE;
    9 x' l; k, w) k
  34.   hlpuart1.Init.Mode = UART_MODE_TX_RX;( k1 @( H6 H. j3 n3 u
  35.   hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;& |/ N; e9 n  E
  36.   hlpuart1.Init.OverSampling = UART_OVERSAMPLING_16;' K9 F) C6 n5 t7 e- m: t
  37.   hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;, A% z6 T+ b! N, N" `0 o- z
  38.   hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;  L6 O& g  p& o' w: ]" Y) m- `
  39.   hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;# Q! q. J7 ^* y# A* c
  40.   HAL_UART_Init(&hlpuart1);
    ' U& r8 Z) l8 \, S+ j9 X( {$ C
  41. </font>   <font face="微软雅黑" size="5">
    3 u. m% z& U4 G& q4 |7 T3 ]
  42.     __HAL_UART_ENABLE_IT(&hlpuart1 , UART_IT_IDLE);
    * c( n; Z& M/ x0 z/ U
  43.     HAL_NVIC_SetPriority(LPUART1_IRQn,1,1);
    $ O+ v) {( q3 d
  44.     HAL_NVIC_EnableIRQ(LPUART1_IRQn);, C* O& A8 w* ]7 {( T. V2 f
  45. </font>   <font face="微软雅黑" size="5">: `5 R! Q9 E' o7 C9 V  ]5 V' j0 t
  46.     NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;1 c. ~9 A, W# [: Q9 ]
  47.     NodeConfig.Init.Request = GPDMA1_REQUEST_LPUART1_RX;* S: X2 J2 M7 @. A9 ]( S
  48.     NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
    ( i# L1 o; T* p* G
  49.     NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
    1 l5 @6 e0 H% `! w2 @
  50.     NodeConfig.Init.SrcInc = DMA_SINC_FIXED;% L- {! U6 B. A& X: K
  51.     NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
    ! _3 a' l7 t# B# A6 z
  52.     NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
    / G* U  v; _& `" S# P" R
  53.     NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;6 N, s" a& E. F! K+ ?- f: {$ D
  54.     NodeConfig.Init.SrcBurstLength = 1;* r/ u$ Y; i! N1 Z  M
  55.     NodeConfig.Init.DestBurstLength = 1;
    ; U  k3 o: M4 a3 Z5 V2 Z
  56.     NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;' X& e( `% o& r
  57.     NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
    . ^* h0 Z  N; x
  58.     NodeConfig.Init.Mode = DMA_NORMAL;
    3 {+ G& q& W- t2 N; |7 W
  59.     NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;2 P; |: S3 s$ k' d; \4 V
  60.     NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
    1 o2 P$ Y4 d" ?9 F' @+ E$ N
  61.     NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
    , f, H8 f0 f" [4 Q
  62.     HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0);
    , ]7 Y! J/ }5 X) Q1 I  Y8 @
  63. 5 s! A, ^" b5 y/ O) y; U& Q* [
  64.     HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0);# a: U3 [! q5 P( \7 F4 ^1 p
  65. $ S% U2 `- a, L
  66.     HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0);
    1 Z% \" p3 Q. u" T$ I2 Y) Y

  67. % F3 N1 o5 _& |9 O5 Y
  68.     handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;# p4 p7 p2 U" a" t9 u4 @1 E9 j& ?9 R
  69.     handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;6 j8 L8 `- ^1 D; j% E1 }, R
  70.     handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
    - L1 b! |6 r: J/ u, C
  71.     handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;* C. p, Z1 e* ~' {" g
  72.     handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;* N% S' j8 F8 a' h+ l! r
  73.     handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
    8 _$ v+ G  \4 {5 ^
  74.     HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0);
    2 q6 I. B% k, j( E- _4 a* A3 r

  75. ( Z/ G1 y  P  I6 s$ m# o
  76.     HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0);: y; _+ B$ b/ v. {" ~3 r' a* g

  77. 6 u( y! v2 C- [" b" c$ [, ?
  78.     __HAL_LINKDMA(&hlpuart1, hdmarx, handle_GPDMA1_Channel0);4 |0 @" g& p# x0 E( M2 G
  79. 5 D/ T" o5 r) s( z( a& t, m' ?8 w( v
  80.     HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV);
    . U" P$ |) z, B% ^. n
  81. </font>   <font face="微软雅黑" size="5">! E& o$ w* X& p; d
  82.     HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);8 H" M. X( U- u) c3 w# {
  83.     HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);; N0 A; L  {# Z
  84. }
    - G: v# `/ |1 h2 c$ d1 i
  85. ' U. Q& H0 G1 {" t0 B
  86. void LPUART1_Send_Char(uint8_t ch)
    ! g( `" N  s, W, O, a" i0 _9 O2 D/ r+ d& T
  87. {
    ) |, j& L) ~* h7 @' x# q
  88.     while ((LPUART1->ISR & 0X40) == 0);0 S( V3 g% U! m* z
  89.   LPUART1->TDR = (uint8_t)ch;
    . Q* B2 c! L6 F( ~1 @! G& a
  90. }
    ' {4 _8 y9 b/ J" A3 ]
  91. 2 C- e, p. X+ W7 c6 l# n5 n
  92. void LPUART1_Send_String(uint8_t * s)
    ( ^) v& X! A4 `, k
  93. {: L. R- ~7 Z9 R8 G+ K
  94.     uint32_t i;
    5 G0 E! ?( ]: ^8 A
  95.     for(i = 0 ; s != '\0' ; i++)3 b0 C# V; {$ Z* U( b. W! i" l
  96.         LPUART1_Send_Char(s);6 D7 c/ M9 z) p6 A: @  J
  97. }
    # u. z0 @4 F, Q6 \6 F9 j
  98. & _$ H% |! U1 c5 E0 Z& R! z
  99. void GPDMA1_Channel0_IRQHandler(void)
    ) @" O+ z/ t; ~# t' n0 V8 _0 I5 o
  100. {7 N$ H) r; b- V  Q0 g+ |
  101.   HAL_DMA_IRQHandler(&handle_GPDMA1_Channel0);4 u$ [# s1 B1 O; c# {3 A2 l
  102. }
    ) v% Y2 f$ g+ R7 x7 u: m( L- D/ `

  103.   b* u( g% l, `4 R/ X
  104. uint8_t aRxBuffer[RXBUFFERSIZE];- g& C% e7 E1 j, z

  105. 0 f% s# Z( \5 O/ f; k
  106. void LPUART1_IRQHandler(void)                    
    8 u% Y# ^& y+ U" J$ }7 {1 P
  107. {
    2 Z' w0 q5 t1 K1 U5 s1 H/ B
  108. //    int temp;# E* t% Q+ T( X! V' H2 p* @
  109.     if(LPUART1->ISR & UART_FLAG_IDLE)
    & ?6 M' F0 Z0 l
  110.     {
    " l* e) v* m* `8 a
  111.         __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);3 }6 @$ t# D- J& t' L
  112.         printf("LPUART1_IRQHandler. %d %s\n" , GPDMA1_Channel0->CBR1 , aRxBuffer);
    # `# s/ ?1 @& I9 b, L" ?
  113. </font>        <font face="微软雅黑" size="5">% W3 P8 R" @& ?) D" P) ?' A1 S
  114.         HAL_UART_DMAStop(&hlpuart1);5 j  O  G2 \9 N* D- J! G
  115.         HAL_UART_Receive_DMA(&hlpuart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);+ `; t0 m. V* U0 ]( P9 V# S8 V/ O
  116. //        rx1_len = BUFFERSIZE - DMA1_Channel5->CNDTR;
    4 P; z7 r5 X% N- p! h# u( ^
  117. //        uart1_recv_end_flag = 1;
    / ~* p: N. r0 o
  118.     }8 x, d& V0 H& Q5 T6 ?
  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 T3 e; \( i- j0 P; D5 U
( k- R, o/ ^- u; g2 Y" f4 d; N' C 6.JPG # h# A+ y% H0 w
1 B2 J9 y/ S! a* n! o
看看运行效果,使用两根typec线分别连接开发板的STLINKV3接口以及用一个USB转TTL模块接在PA2 PA3引脚上:
2 F, R8 G/ j8 {0 D6 \
7.JPG IMG_20250523_174406.jpg % D+ Y+ @, _8 d# X0 X
首先上电之后UART1和LPUART1都会打印信息,然后,对LPUART1发送数据,UART1会打印接收到的数据以及接收长度(100-DTR寄存器值)。
收藏 评论1 发布时间:2025-5-23 17:55

举报

1个回答
星海灿烂 回答时间:7 小时前

你好,板载ST-LINK电脑可以识别不到吗?

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版