拿到了nucleo-U385开发板,在KEIL环境下编程,需要下载CubeU3支持包,在ST官网即可下载,并且在CubeU3支持包内还有KEIL环境所需要的pack安装包,这个应该是最近才做的一个方便开发者开发的一个机制:/ E. |# a$ o' d* h) n
: M& r1 S; d3 H2 j6 |
我直接用点灯的例程来改串口例程,方便省事:
( C' G! T2 i& r- A
# F. `& O5 Z( ]8 z. l整理好的例程结构如下:( a p( h' {7 A2 Y: j% y% k
# I/ V' x' m% h, B9 b3 \/ g" }4 H0 d根据原理图可以得知,开发板的STLINKV3 VCP连接的串口是UART1,即PA9 PA10,可以直接与电脑的串口助手进行通信,另外开发板上还有PA2 PA3引脚,这个引脚被复用为LPUART1:6 l. i! m" Y, v# p2 m ?" \2 L
, F% g5 u# D* d; e. H6 X: d我这个帖子就实现UART1和LPUART1的双通道串口通信,其中把LPUART1的接收功能打开,使用空闲中断和DMA进行接收,先看看UART1的初始化代码:- <font face="微软雅黑" size="5">UART_HandleTypeDef huart1;
3 ^+ W, X7 a: ]; Z/ i. g - O7 W/ G2 Z# {9 B
- int fputc(int ch , FILE *f)
$ k7 ~1 p5 z$ Y - {
; f& y3 `, G( v2 s# N - while ((USART1->ISR & 0X40) == 0);
% E8 n$ O! q6 {- W: a - USART1->TDR = (uint8_t)ch;
" V2 d2 p5 z& d8 m- t2 B+ U8 Z4 X0 ^ - return ch;
5 n" D6 Q F$ d6 N" d& y$ l5 | - }
1 C" c- \: N0 j, n6 v
2 Y* d# E1 l( G- y( Z- d/ F0 k/ u- void UART1_Init(uint32_t baud)
6 m6 o: I+ V7 I8 @: u3 W - { B5 B/ e# s- U- U3 U8 [
- GPIO_InitTypeDef GPIO_InitStruct = {0};
4 }# H& }3 E* T! W; ?- }$ e - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
3 c" J7 K! V) B9 U N' {6 P" s - 2 e* n0 ^2 ` ?' o
- __HAL_RCC_USART1_CLK_ENABLE();$ U$ v9 b( H4 O* e+ X' a
- __HAL_RCC_GPIOA_CLK_ENABLE();
' q; C( f" B9 q# Z - $ S; R8 T7 h6 x
- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
9 L2 v7 N; U, v5 E" d - PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;7 P, g& l: U" j1 V+ }7 J; |
- HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);: U e# l$ Q' a" e$ S
- ( Z* U) Z, ^, A) S- d E- k% h
- GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
6 ~+ ?7 d8 E5 E. F: h4 N5 m - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;& K/ l) L) w' t, @# }# t
- GPIO_InitStruct.Pull = GPIO_PULLUP;; a* t$ q1 V/ d9 i. C% B2 M# B; j
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;6 L1 B5 Q& A& E* K
- GPIO_InitStruct.Alternate = GPIO_AF7_USART1;1 d6 n1 k Y4 S8 q
- HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);- ^0 n$ O$ [" X
- </font> <font face="微软雅黑" size="5">
% q& ]: m8 M# l; Y! c* T - huart1.Instance = USART1;
. G- Q( R. j3 f9 S/ a7 Z" y$ ^8 V: a - huart1.Init.BaudRate = baud;8 C7 h+ ^- t" {
- huart1.Init.WordLength = UART_WORDLENGTH_8B;, Y( }) m" w' d# q. p' T8 _! D
- huart1.Init.StopBits = UART_STOPBITS_1;4 Q0 f7 {$ g `7 @' J
- huart1.Init.Parity = UART_PARITY_NONE;6 i& \8 `* P4 J) M. z5 e; T
- huart1.Init.Mode = UART_MODE_TX_RX;
+ i7 J9 P& m* |" K, Z( b5 E' i - huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
3 {% e0 v" U8 q - huart1.Init.OverSampling = UART_OVERSAMPLING_16;
7 \8 B/ B3 j! n. ?0 o; C1 G - huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
& t4 w' u/ c; M' p1 g e8 S - huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;1 ?* T% D% v, W' q+ T
- huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
; i {# ]2 L: A6 c) w - HAL_UART_Init(&huart1);
5 L& |0 }& Y c) C; @$ u - }</font>
复制代码 非常简单,只要熟悉STM32编程的没有一点难度,然后是LPUART1:
4 i, N9 g7 l* {" Z: \! W- <font face="微软雅黑" size="5">UART_HandleTypeDef hlpuart1;
; O7 {2 _- K+ \* j ?. U
5 k! l; b- |" S6 l0 _' g- DMA_NodeTypeDef Node_GPDMA1_Channel0;
) ?$ `# Z, a2 D; a - DMA_QListTypeDef List_GPDMA1_Channel0;) f4 H+ R, i/ Y) ~ U
- DMA_HandleTypeDef handle_GPDMA1_Channel0;
4 e$ k! M3 D! r( R( J - / C6 _7 p# k- u1 J- J+ X+ o* ~
- void LPUART1_Init(uint32_t baud)
' c: V6 G% L9 @- n) c+ R J - {; @; T5 G9 \* V) z+ K
- GPIO_InitTypeDef GPIO_InitStruct = {0};
, p: ]$ b6 ?5 L' g: S3 F - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
9 A2 C. Z4 b9 A+ i& \* z9 \2 p - DMA_NodeConfTypeDef NodeConfig;2 R6 l* q: p: A- u! ~) Q
. H( p0 n& g9 H' _6 v* T- __HAL_RCC_LPUART1_CLK_ENABLE();/ U" z& Y* x, }$ U
- __HAL_RCC_GPIOA_CLK_ENABLE();
0 Y* A8 }- U$ R - __HAL_RCC_GPDMA1_CLK_ENABLE();
! e+ S! i/ {- U- R3 V
5 }' R$ }8 D0 N7 v: `' k: |- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;
& k* |3 X( [$ ?( Z* D1 h2 e$ A. Z8 i9 V - PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK3;
6 D; U" p# p& Y; j - HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
- W# e0 n7 U( } - 5 A$ I) ^0 }! L2 a* I. ~
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
: g$ N7 ^+ N0 a# ]% { - GPIO_InitStruct.Pull = GPIO_PULLUP;- W: S6 ?& M% V |+ u
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;; r/ K% _9 w5 v: c
- </font> <font face="微软雅黑" size="5">. K6 \ t% X! f" B3 R
- GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;
: x" `. e7 N) q# H' g8 d - GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
: F( _& a( U. e* E% u - HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
1 t, i1 t+ }/ F" @8 u/ F8 _ - </font> <font face="微软雅黑" size="5">
# E% t" N! R1 Y - hlpuart1.Instance = LPUART1;2 M% p8 p9 p \
- hlpuart1.Init.BaudRate = baud;
3 B' ]5 a+ M7 u" L, `3 q: P+ b - hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
+ Q" V; C! o/ R& |& Z - hlpuart1.Init.StopBits = UART_STOPBITS_1;0 ]8 c, S5 M. {! K
- hlpuart1.Init.Parity = UART_PARITY_NONE;+ z9 K D5 t$ e' W+ d
- hlpuart1.Init.Mode = UART_MODE_TX_RX;" u) K( S% c9 ?: x3 g) F
- hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
1 H( o; h( i3 r - hlpuart1.Init.OverSampling = UART_OVERSAMPLING_16;& |: g% _' n @- d+ g; L
- hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
% y- v/ c: W& t/ @! U! F - hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
* r! [4 O7 F2 H( M" g+ W' g- N - hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;4 m' \5 L: C. W
- HAL_UART_Init(&hlpuart1);
( R% f$ X! ~0 x7 Q - </font> <font face="微软雅黑" size="5">" z4 O2 R& `8 L" h$ B
- __HAL_UART_ENABLE_IT(&hlpuart1 , UART_IT_IDLE);2 ^7 d6 e+ d2 {, b0 q! d3 T
- HAL_NVIC_SetPriority(LPUART1_IRQn,1,1);$ g7 _! i/ r5 ?8 K- c$ l' y- |( `
- HAL_NVIC_EnableIRQ(LPUART1_IRQn);
Z2 q+ v& e' V; J2 s - </font> <font face="微软雅黑" size="5">* x, f& o2 @' z7 k+ k$ ^+ s
- NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
/ m6 f7 _$ O+ j( j- _! U* U - NodeConfig.Init.Request = GPDMA1_REQUEST_LPUART1_RX;
6 w+ q7 ^. n6 n9 n, S: v - NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;5 k; [: S: O) [$ K7 o; |
- NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
, V2 f- t) v3 j, Y - NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
0 `9 L6 L; ]! w% E& r( [ i$ t* D, D - NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
7 F/ k9 M4 C- V, L( P - NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
' _/ i$ D8 O- p" D: ] - NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;, A4 w- |1 X" Z/ k$ U8 Z! F9 w
- NodeConfig.Init.SrcBurstLength = 1;4 Y4 Q# y# \: W1 }
- NodeConfig.Init.DestBurstLength = 1;
9 |/ y* l- J' Q: v" o, g3 ` - NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
, f' G t4 q8 E& a6 j- S: D. ] - NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
0 z' _/ A1 J: l4 a% b3 v- a - NodeConfig.Init.Mode = DMA_NORMAL;( ^- }0 c5 _. s1 C- V# J) X
- NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;$ L* [2 W' L, B# m
- NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
7 l5 W8 A, t. y& B) B - NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;1 n8 X# }9 E/ @& Z8 n
- HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0);7 ?9 o, j7 Z* \+ d% V" V; }
- - b8 W" [( h% A$ f* l4 m0 w/ t. O
- HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0);9 V* Y; q6 \: ^. o/ F1 ]
- & S. A/ }! X$ D6 G, x8 T
- HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0);2 p# u: {& c/ d0 z
- " U: L7 q& }+ Q: S
- handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
/ B/ E3 D7 I4 H. `, {& H S - handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;: c+ F/ e$ I5 ^. ^7 n% X5 ^& p
- handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;% j6 Z' G: K9 F6 u4 C
- handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
8 i- U6 `' x/ ^6 H) y0 J - handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
- I/ h% E2 r1 _3 X - handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
8 i0 a5 ^: v$ B& |3 J. ]( H5 c - HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0);
: S! {! X% U; m0 B5 s' b: L2 t% u - + G' F; d; ~0 f9 t7 K( Y9 K( @. \
- HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0);
9 \4 V% j) O+ f4 K" X* t - ; h/ l# `9 J& M7 O' l
- __HAL_LINKDMA(&hlpuart1, hdmarx, handle_GPDMA1_Channel0);" ?: `- H( D" K
" o) l. N- |* j9 W, F: h; A- HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV);
' m/ |7 \6 z! k. u( _3 i - </font> <font face="微软雅黑" size="5">
# e: y0 |9 ]% x: A3 F Q( R7 V( J - HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);
6 d8 }# [( t, C+ W; [# |2 J4 b - HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);' {+ H3 W' D; _ n; B7 n
- }
7 B8 a! c/ o* D$ R4 c) g - / I6 S3 a1 n' g1 P
- void LPUART1_Send_Char(uint8_t ch)/ n. |+ R% O& e8 ~" o6 b% @
- {- ~% u' Y6 X6 r Y" f
- while ((LPUART1->ISR & 0X40) == 0);* e: _! ~: Z" O1 l
- LPUART1->TDR = (uint8_t)ch;
. r7 g B+ k( Y2 q6 I) A - }
: U; b2 p8 C# W$ O Q0 K- [* l
' X) _* B- U8 h- void LPUART1_Send_String(uint8_t * s)" l) ^1 _3 J$ S" X3 ^
- {
$ ^2 r& U# D" d% u% e! t - uint32_t i;
3 Q& G, J5 G$ _& Y - for(i = 0 ; s != '\0' ; i++)
; V5 D- n: k2 I( {9 ~( i" I+ |7 E - LPUART1_Send_Char(s);- Q- Z3 T3 `9 A# H: e! A
- }! _7 H$ {. G8 M& V6 \
! [* R& ?2 u) @; k. F$ I- void GPDMA1_Channel0_IRQHandler(void)
2 C, ^2 P) F, I. Y6 d - {% m; c* D0 Q2 o8 H. C
- HAL_DMA_IRQHandler(&handle_GPDMA1_Channel0);
) M* _ I/ X$ N2 g$ [. P4 I( ` - }
: ^5 i* ?) Y+ F1 `: G. M0 f0 j9 s/ d; V
( O2 p$ [" @' L, U- uint8_t aRxBuffer[RXBUFFERSIZE];
; B9 D- I# O: s4 }# {: s& z - 0 v# P- r* e% N0 S v
- void LPUART1_IRQHandler(void) 3 b H8 M0 j6 Y0 u6 x1 F; Y
- {- j6 Z/ y8 s$ l
- // int temp;
, Z, D4 d$ ? ^( o2 {7 X - if(LPUART1->ISR & UART_FLAG_IDLE)( @1 p$ p4 \, X3 i* N3 Q; f
- {1 u3 p, x" |3 {5 S- X' q( B
- __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);
% o6 p1 K! C. i* Y0 B1 | - printf("LPUART1_IRQHandler. %d %s\n" , GPDMA1_Channel0->CBR1 , aRxBuffer);( k7 n* `4 ~) ]1 f/ l0 ^
- </font> <font face="微软雅黑" size="5">
6 c. D/ x* R& ] - HAL_UART_DMAStop(&hlpuart1);& n, `3 n2 v; ]! \ v
- HAL_UART_Receive_DMA(&hlpuart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);
A* V+ }1 M* F- a& d/ r - // rx1_len = BUFFERSIZE - DMA1_Channel5->CNDTR;
9 e9 f+ ^8 Y, D4 v: b+ B - // uart1_recv_end_flag = 1;
5 ]1 H2 N9 e9 @6 r. E z - }
4 c( ^6 Y, {+ }8 z) I - }</font>
复制代码 在ST的新系列里面,有个特殊机制,使用任何形式的DMA通信必须要打开DMA中断,这个在F103系列是不需要的,是F4以及之后的大部分系列都需要,另外,在F4之后的系列中,对于外设要用的DMA,可以自由配置通道Channel(流Stream/节点Node)等,其实是一个东西,就是DMA通道的意思,不同系列的名称不同,只有F103和F4系列的特定外设是绑定在特定DMA通道的。像本帖子,就把LPUART1的RX功能设置在在GPDMA的通道0(后续还把SPI1的TX功能设置在GPDMA的通道1)。
+ Q& c7 [2 C/ a' S/ k
* S! K8 T" m) e
* p6 H0 ~9 o0 V0 y
6 i* j. q4 [; f7 G看看运行效果,使用两根typec线分别连接开发板的STLINKV3接口以及用一个USB转TTL模块接在PA2 PA3引脚上:& n0 x' t2 a c# `/ @6 F
( {! e$ D5 a* S, C
首先上电之后UART1和LPUART1都会打印信息,然后,对LPUART1发送数据,UART1会打印接收到的数据以及接收长度(100-DTR寄存器值)。 |
你好,板载ST-LINK电脑可以识别不到吗?
没看懂你的表述是什么意思
就是把板载ST-LINK的C口接入电脑,电脑可以识别到ST-LINK吗?
[md]那肯定可以识别啊,不识别怎么下载代码发帖子😄
使用的是全功能的Type-c线吗?
没听说过typec线还分什么全功能不全功能的,我直接用手机充电线来接开发板的,一端是typeA的HOST,一端是typec,把线连接电脑和手机,能识别出手机的存储卡,那就肯定可以给开发板用