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

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

[复制链接]
donatello1996 发布时间:2025-5-23 17:55
     拿到了nucleo-U385开发板,在KEIL环境下编程,需要下载CubeU3支持包,在ST官网即可下载,并且在CubeU3支持包内还有KEIL环境所需要的pack安装包,这个应该是最近才做的一个方便开发者开发的一个机制:; H& D  R& n0 |. p# i, ?& \& P- W
1.JPG
! k9 Z! y  Z, r/ l我直接用点灯的例程来改串口例程,方便省事:
8 ^" }/ S6 `! i9 V  P) r: [* L
2.JPG
7 h$ p4 b8 _# w" a" a( _2 D; I整理好的例程结构如下:
8 q* w! {4 Y; ]6 I2 M" T2 i
3.JPG " r" O4 x: |, U$ w/ C% c( N% o) i% w
根据原理图可以得知,开发板的STLINKV3 VCP连接的串口是UART1,即PA9 PA10,可以直接与电脑的串口助手进行通信,另外开发板上还有PA2 PA3引脚,这个引脚被复用为LPUART1:
- M: \9 S9 y" ~- l& k$ H/ n3 Q
4.JPG 5.JPG
, A. K1 q" B1 n, m5 X! W- I我这个帖子就实现UART1和LPUART1的双通道串口通信,其中把LPUART1的接收功能打开,使用空闲中断和DMA进行接收,先看看UART1的初始化代码:
  1. <font face="微软雅黑" size="5">UART_HandleTypeDef huart1;
    % p' x3 d* h/ o* b  B5 K+ g/ R

  2.   I8 s, e* m+ J- ?- ^
  3. int fputc(int ch , FILE *f)! u4 R- _1 B+ o5 V3 a* }8 [0 P1 L5 f
  4. {2 k9 I; G  e( f+ x1 Q
  5.     while ((USART1->ISR & 0X40) == 0);
    # G/ n7 ~5 S  L5 P3 d# D
  6.   USART1->TDR = (uint8_t)ch;
    , ]5 H; j0 ~' |+ \% q
  7.     return ch;5 Y, A2 @7 H+ A, i1 g0 p3 x: r
  8. }* K  d2 q. t6 W  c

  9. % g8 \- m2 E! j0 z' }7 I
  10. void UART1_Init(uint32_t baud)# P; f( ]% M: z' T. j
  11. {
    ) ?& G' f$ m8 c
  12.     GPIO_InitTypeDef GPIO_InitStruct = {0};4 G. e( q3 i1 K+ r" q: j* O7 z" g
  13.     RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    " z1 P" \6 A% Y7 h+ L/ [+ K
  14. 5 O5 A/ f) l' F% {& D
  15.     __HAL_RCC_USART1_CLK_ENABLE();
    3 z7 R+ [- E$ O
  16.     __HAL_RCC_GPIOA_CLK_ENABLE();
      B9 `& i  d7 @! z

  17. ; d0 b. f, ~% n, v' j; H. i
  18.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
    3 R* M1 I, a1 g
  19.     PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
    2 S1 }+ N5 d# N) M
  20.     HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);9 o- L; i3 V7 I. g: ?& h

  21. - W' a; m% d( X. ]; y: Q
  22.     GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;, E- H# o' w! |0 j
  23.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    ! K- b  B7 h) I/ n. `' q4 F& o( |7 m
  24.     GPIO_InitStruct.Pull = GPIO_PULLUP;% f) _. Z6 |/ J& B, B8 a8 ]
  25.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    + l  g) T( x4 Q1 w6 E3 a# d
  26.     GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    6 p; q- h3 h! |7 X( D+ C( E0 ]
  27.     HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);) \' G: S1 C- o6 H& L( [! z
  28. </font>   <font face="微软雅黑" size="5">
    ( S5 e2 q1 h, C( ?
  29.   huart1.Instance = USART1;- [+ U) O% e# ]
  30.   huart1.Init.BaudRate = baud;
    % Y# U# |  r; ^3 D
  31.   huart1.Init.WordLength = UART_WORDLENGTH_8B;
    : W. ]6 H3 f1 q$ s% W# x
  32.   huart1.Init.StopBits = UART_STOPBITS_1;
    4 ]$ M6 a) i8 y! D* c+ Z
  33.   huart1.Init.Parity = UART_PARITY_NONE;) X! f. `( g9 R  h+ S# g
  34.   huart1.Init.Mode = UART_MODE_TX_RX;
    " n& {" r& S* ]3 S, s
  35.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;6 ^5 ^3 ^2 T1 Q" V& [2 D  x
  36.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;0 E9 B9 f) L1 L
  37.   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;$ ?" m" n  u# I9 C1 L/ _
  38.   huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;1 F, r4 _; p& G8 o4 ^1 B
  39.   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;% u" _8 x/ r) J$ }
  40.   HAL_UART_Init(&huart1);
    1 h$ C. b6 d3 R% H- ~0 a
  41. }</font>
复制代码
非常简单,只要熟悉STM32编程的没有一点难度,然后是LPUART1:
1 {1 m( j/ w# P0 h  y  o
  1. <font face="微软雅黑" size="5">UART_HandleTypeDef hlpuart1;" o2 G9 i& [$ @; l% _: ^
  2. * o3 `* m1 d! @0 Z- A- j
  3. DMA_NodeTypeDef Node_GPDMA1_Channel0;
    1 D1 ~  N0 N: g! e4 t  R
  4. DMA_QListTypeDef List_GPDMA1_Channel0;$ L+ _" H; H- v$ O: }
  5. DMA_HandleTypeDef handle_GPDMA1_Channel0;
    ! {. |6 K9 g/ F6 ]

  6. : m. A3 Z3 @8 S- x  \; B3 E, c# s
  7. void LPUART1_Init(uint32_t baud)( i/ ?& m1 j/ h; T! ]4 N, j
  8. {% B+ c5 Q- |- j1 `7 G2 Y
  9.     GPIO_InitTypeDef GPIO_InitStruct = {0};
    1 A9 i( c" }/ I! \
  10.     RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    7 f9 e* W- S2 J( K% T5 ^( y8 V
  11.     DMA_NodeConfTypeDef NodeConfig;
    8 S& n5 l! P( F
  12. $ P, M% @' @, e# Y
  13.     __HAL_RCC_LPUART1_CLK_ENABLE();% V- a# F+ }( \- `, |
  14.     __HAL_RCC_GPIOA_CLK_ENABLE();
    2 V4 `1 z  I% |' x/ D& F. f; }
  15.     __HAL_RCC_GPDMA1_CLK_ENABLE();
    ! C/ ]$ q$ Q5 C  r

  16. % k; B- i5 \$ l6 {8 m4 n& b# d( x
  17.   PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;- f. x0 T5 v. `! r# Q% p  f) n
  18.   PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK3;% S, k/ V8 K% g7 G
  19.     HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
    7 L- U9 t; N4 l" ?4 s( Z7 X, j
  20. : A0 u* k4 Y; h; p! [0 x" n
  21.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    ) c8 {4 S( E: P8 ~
  22.     GPIO_InitStruct.Pull = GPIO_PULLUP;
    & D6 L4 t2 v! o# _1 a' K
  23.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;) ?4 t0 S( t6 o# M: M
  24. </font>   <font face="微软雅黑" size="5">' ?9 j  g0 ]0 N3 q2 \
  25.     GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;" _9 s9 x6 c9 ^8 H: O& o7 p
  26.     GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;& [4 o: Q# @3 W  q2 ?
  27.     HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);4 S2 K/ o3 Q4 E% C4 T7 f/ i6 u
  28. </font>   <font face="微软雅黑" size="5">! G0 q' k( h- e: Y' C3 \
  29.   hlpuart1.Instance = LPUART1;
    . l) r0 a3 v2 L6 H1 e
  30.   hlpuart1.Init.BaudRate = baud;
    9 i4 X& b- Z2 e8 J% a
  31.   hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
    3 J* W0 ^# `" b' A- u0 C
  32.   hlpuart1.Init.StopBits = UART_STOPBITS_1;
    ' c; \# Z( X* P% |' n; g
  33.   hlpuart1.Init.Parity = UART_PARITY_NONE;& ~" H" D9 ?7 R+ k( L: ~+ C
  34.   hlpuart1.Init.Mode = UART_MODE_TX_RX;8 u& ^( Y& L0 q( B: e8 D! c
  35.   hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;7 [$ j# p5 K$ `7 U0 L. G
  36.   hlpuart1.Init.OverSampling = UART_OVERSAMPLING_16;
    ) x% V; ]" g: ]
  37.   hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;, A7 M6 K! W% W! P, e
  38.   hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;/ O; B7 O( p5 B: M# N( Z# A. {  K: A
  39.   hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    3 T. G* B! Z% g2 z  [5 n6 c: m6 I0 Q
  40.   HAL_UART_Init(&hlpuart1);
    ) J$ k" o4 Z3 u% ]4 w* E0 w
  41. </font>   <font face="微软雅黑" size="5">2 }6 w6 e+ t. j4 C/ L
  42.     __HAL_UART_ENABLE_IT(&hlpuart1 , UART_IT_IDLE);$ J/ p7 f* a5 |8 }$ e
  43.     HAL_NVIC_SetPriority(LPUART1_IRQn,1,1);7 @  ]3 Q- E# X4 Z# h+ l/ h) U
  44.     HAL_NVIC_EnableIRQ(LPUART1_IRQn);
    . N# e# q* U3 s3 X# f* U
  45. </font>   <font face="微软雅黑" size="5">  T! S3 \" w) C0 L
  46.     NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
    ( k* ~9 `" C( w8 X  V
  47.     NodeConfig.Init.Request = GPDMA1_REQUEST_LPUART1_RX;3 @. U6 G  F; u. k
  48.     NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;2 r6 h5 i+ Z( c6 }5 l7 ^
  49.     NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;' S# R/ @" R! ~
  50.     NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
    3 s5 b; V4 u& C. U
  51.     NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;8 I! C& P/ O0 |+ s3 r- j
  52.     NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
    ! T0 ~! T' |( u& ]/ f
  53.     NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
    % J& k+ a9 Y# X3 K  F# k4 B
  54.     NodeConfig.Init.SrcBurstLength = 1;
    % r$ q! Z, X& b* f( W5 ]
  55.     NodeConfig.Init.DestBurstLength = 1;2 q5 v* |* B" f3 F5 M3 L+ V* C/ ?
  56.     NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;& H. G% K( x6 u9 B4 a& ]! A; G
  57.     NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;) Q+ h8 B" H  D& r% f% i7 x, s' U
  58.     NodeConfig.Init.Mode = DMA_NORMAL;
    # U: V1 M, k4 `3 n2 T  ]! {
  59.     NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;6 s! f8 ^* h2 _4 B
  60.     NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
    $ |+ o! G: ]+ e% {$ ^9 }/ \0 `) f
  61.     NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;) m9 w1 K$ J' _8 {0 q. V
  62.     HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0);$ B- U+ Z" X( y9 ~
  63. % G; Q+ K' C+ h" _/ A
  64.     HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0);
    - x1 f$ Y6 v7 \- q0 K# d8 m0 A

  65. # ~3 F7 J: R7 a1 n% X
  66.     HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0);
    , n% N  |, s$ l! J6 b, O& q% z# i8 {

  67. + u! I. P" X1 s0 ~- Z7 L
  68.     handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
    / T. L5 t6 p8 O9 g/ }1 v" N- j
  69.     handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;" G2 X5 n# }; B
  70.     handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
    2 d* v1 e0 ^% v. v# s7 g
  71.     handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;  p- Z: S/ y; L- h
  72.     handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;0 U7 f* H$ L2 a+ V: H! |8 Z% Y
  73.     handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
    3 A3 a' J% {4 H# X% Q: R
  74.     HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0);+ V) w! G6 A* G+ C( [
  75. & Q/ ^6 B, b/ k* q* {5 V% S
  76.     HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0);
    ( x$ Y  j* M( o& b

  77. % M, T. m. D' g) G8 M$ p( q- T
  78.     __HAL_LINKDMA(&hlpuart1, hdmarx, handle_GPDMA1_Channel0);
    1 {# h2 i! v: Y  M9 {$ g% f9 u8 ^

  79. / h( B. M4 }! G5 L  o: H0 s6 o1 S" a) X
  80.     HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV);
    $ \9 Z0 V- s: O
  81. </font>   <font face="微软雅黑" size="5">
    6 ?5 J5 C+ C5 u! ^+ M
  82.     HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);, l9 \0 f6 J2 d; f
  83.     HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);
    7 g1 w- U6 r- V
  84. }
    % }" t' H1 k% p  K
  85. 0 T+ ^! D# E+ E1 H+ O8 ^: x! ^
  86. void LPUART1_Send_Char(uint8_t ch): N  S; ]9 B% L) x) p9 S; Y7 G
  87. {( j# ]- T# w1 j6 M! K; y
  88.     while ((LPUART1->ISR & 0X40) == 0);4 b( p8 E" r/ d
  89.   LPUART1->TDR = (uint8_t)ch;
    ) P* U! p) Q: R5 Y6 l: \
  90. }8 D! e* \4 e3 v, `" z
  91. ! C2 Y: Y* `9 D, ?9 H9 p# I4 B# a8 ~
  92. void LPUART1_Send_String(uint8_t * s)% o" r6 Y, |. @- v; z
  93. {* ?1 F# }2 K! \! u0 i
  94.     uint32_t i;- T- \0 ?% F$ v0 C; Z# L
  95.     for(i = 0 ; s != '\0' ; i++)9 C: I5 P4 h( G7 Y# J8 }
  96.         LPUART1_Send_Char(s);
    3 @* _: p8 }+ K1 [5 j
  97. }
    6 d% E: o1 O3 ]; j
  98. 7 i4 ]( g* j0 k$ q; }6 B8 o: `" v9 U
  99. void GPDMA1_Channel0_IRQHandler(void)
    ; G8 w6 b5 _6 a! k8 @( W
  100. {: ^: O. o' J4 O# `3 B
  101.   HAL_DMA_IRQHandler(&handle_GPDMA1_Channel0);
    ! c. d  c/ H2 E8 ?+ Q# }% u  E( |1 X
  102. }: p5 Q* w$ |  k; Z

  103. $ {0 p' M* R0 o" ~  Z) K
  104. uint8_t aRxBuffer[RXBUFFERSIZE];
    ( M8 |; P0 R0 `( x+ }1 J

  105. 8 D( H3 Q1 F% _* i; w
  106. void LPUART1_IRQHandler(void)                    ; E; d' @3 X- c8 u
  107. {! x# _' x% n$ }
  108. //    int temp;+ f4 W) U- `! |* G0 \
  109.     if(LPUART1->ISR & UART_FLAG_IDLE), _; v) o( ~5 R: v3 y$ L: P9 i
  110.     {% G/ h8 H2 ]$ `& t0 p. X' w" z
  111.         __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);; y! @0 C9 ]+ w7 i' K5 w, {
  112.         printf("LPUART1_IRQHandler. %d %s\n" , GPDMA1_Channel0->CBR1 , aRxBuffer);0 r) Q# H2 f9 D# u
  113. </font>        <font face="微软雅黑" size="5">
    6 W5 w# d9 _$ M5 J7 |
  114.         HAL_UART_DMAStop(&hlpuart1);
    9 S. O  J3 x! Y3 F4 U/ o" Y+ t
  115.         HAL_UART_Receive_DMA(&hlpuart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);
    ' A  w! T1 Z4 _2 `& O' b. c
  116. //        rx1_len = BUFFERSIZE - DMA1_Channel5->CNDTR;
    8 t- w: d# T" K0 u7 n0 Z5 x
  117. //        uart1_recv_end_flag = 1;
    3 v$ n* \( i4 ~: y- B' z
  118.     }% e* K/ R7 `2 x4 ?$ N1 x1 J
  119. }</font>
复制代码
在ST的新系列里面,有个特殊机制,使用任何形式的DMA通信必须要打开DMA中断,这个在F103系列是不需要的,是F4以及之后的大部分系列都需要,另外,在F4之后的系列中,对于外设要用的DMA,可以自由配置通道Channel(流Stream/节点Node)等,其实是一个东西,就是DMA通道的意思,不同系列的名称不同,只有F103和F4系列的特定外设是绑定在特定DMA通道的。像本帖子,就把LPUART1的RX功能设置在在GPDMA的通道0(后续还把SPI1的TX功能设置在GPDMA的通道1)。" q( t6 I" m0 T! t/ j, k$ K

3 w1 ^3 o; f% |  t6 G 6.JPG 5 i' j5 W! u  H$ p  @% i

- e5 s  A5 X# O$ b; M( C看看运行效果,使用两根typec线分别连接开发板的STLINKV3接口以及用一个USB转TTL模块接在PA2 PA3引脚上:
  }) l- p- o; L5 w8 d
7.JPG IMG_20250523_174406.jpg
8 x) y  {; h. O/ x. u首先上电之后UART1和LPUART1都会打印信息,然后,对LPUART1发送数据,UART1会打印接收到的数据以及接收长度(100-DTR寄存器值)。
收藏 评论0 发布时间:2025-5-23 17:55

举报

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