拿到了nucleo-U385开发板,在KEIL环境下编程,需要下载CubeU3支持包,在ST官网即可下载,并且在CubeU3支持包内还有KEIL环境所需要的pack安装包,这个应该是最近才做的一个方便开发者开发的一个机制:
( I8 x4 B% [9 W+ W1 t% W* p
( s' f ]. x6 j我直接用点灯的例程来改串口例程,方便省事:/ X9 s* i6 B5 {9 W: y1 z
& Y2 d) H5 [5 i$ w# s# w
整理好的例程结构如下:
. v% E5 Y8 ^5 g( e* `3 d! x, V
1 ~' n% k) c4 P D根据原理图可以得知,开发板的STLINKV3 VCP连接的串口是UART1,即PA9 PA10,可以直接与电脑的串口助手进行通信,另外开发板上还有PA2 PA3引脚,这个引脚被复用为LPUART1:8 N4 w; c- ]! t. ?/ M. z, |
4 p' a9 {! q7 q! z我这个帖子就实现UART1和LPUART1的双通道串口通信,其中把LPUART1的接收功能打开,使用空闲中断和DMA进行接收,先看看UART1的初始化代码:- <font face="微软雅黑" size="5">UART_HandleTypeDef huart1;
0 J: y2 J- O2 L" `2 q& j4 I
. Z( o! c6 k" H q _- int fputc(int ch , FILE *f)- }/ J+ Y3 i2 s- O4 @! }
- {
& D3 l! u4 k0 U! A - while ((USART1->ISR & 0X40) == 0);! W m9 r7 r' i( E- ^2 e
- USART1->TDR = (uint8_t)ch;. l" `0 Q( D' } i# V
- return ch; g1 ?4 J; L! e. L
- }4 Q& Y) Z8 X- T! P
/ t* s* d/ [9 }- void UART1_Init(uint32_t baud)0 G1 E( L; a8 e; L( Y3 K9 F
- {
$ @( K U+ L% k9 @ - GPIO_InitTypeDef GPIO_InitStruct = {0};
- k( _/ j$ O+ X$ J" q& @ - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};6 X, U6 h( |9 V2 W
" r# J& c% h5 c# y( S. P* P5 t- __HAL_RCC_USART1_CLK_ENABLE();$ |# \( E3 H0 e2 k" _7 P `
- __HAL_RCC_GPIOA_CLK_ENABLE();
9 U$ `2 P8 z: `$ h% d! {( y% b - 1 j8 N( e2 i7 E- R- v1 H1 K" b
- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;7 Y V& s8 l* {; R3 T G( O; q
- PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
9 V- }- t+ \. u F% w- c* o - HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);! C- D& p, i- [" x' f
. Q* S N$ G* i4 Y! x7 [1 c- GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;1 B0 d: ^ l6 e( W1 I
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;( |( D# x! M2 o A4 g
- GPIO_InitStruct.Pull = GPIO_PULLUP;
0 a7 i& V. K: Z# w# [* B - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
5 Y6 x4 E" ~. ^ - GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
6 _+ {( ]! A+ `. I' o: h, \7 z8 ^ - HAL_GPIO_Init(GPIOA , &GPIO_InitStruct); z$ _" V7 ^1 Q1 h: n Y
- </font> <font face="微软雅黑" size="5">
, n8 L; \) f5 {( r9 q l - huart1.Instance = USART1; K* u' o' N. _* ?( ]
- huart1.Init.BaudRate = baud;
& h: w n0 A% U8 Q N- H - huart1.Init.WordLength = UART_WORDLENGTH_8B;2 d" ^# a( p& q6 f' Y" b
- huart1.Init.StopBits = UART_STOPBITS_1;" L3 c9 C4 r" d2 T* m/ b4 D. r$ o, i2 C
- huart1.Init.Parity = UART_PARITY_NONE;6 B: L/ S+ B, u! i6 J7 r+ {
- huart1.Init.Mode = UART_MODE_TX_RX;
* r8 { u, R; }% D4 s' r- Q1 k - huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;" H) d& A( y2 n8 }4 n7 g4 o
- huart1.Init.OverSampling = UART_OVERSAMPLING_16;0 |2 q$ P+ s! Y5 [- ^
- huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
; Y* U' @/ F% F" a& S - huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;9 `/ ^1 a) X% J" ]$ S6 U
- huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;- o a, |, n+ @3 r& ^
- HAL_UART_Init(&huart1);1 n' s' I* V. O$ [, m% T# E
- }</font>
复制代码 非常简单,只要熟悉STM32编程的没有一点难度,然后是LPUART1:4 p" |- J" C( v- _$ e
- <font face="微软雅黑" size="5">UART_HandleTypeDef hlpuart1;
# |; { w9 F' E6 g: q - & f5 R7 J8 {8 L4 w
- DMA_NodeTypeDef Node_GPDMA1_Channel0;/ J* m+ l. y2 V2 \% h3 T8 D# [
- DMA_QListTypeDef List_GPDMA1_Channel0;
% A0 v1 T' \* Z - DMA_HandleTypeDef handle_GPDMA1_Channel0;
; d1 z0 \' Z7 E# c( f: `" U% N1 @ - ' T; I" E2 Z' p
- void LPUART1_Init(uint32_t baud)
4 h! d1 k0 F: t ]' R X w: G! j& A) Y - {7 `, g* Q8 D' B# u7 d6 {& C
- GPIO_InitTypeDef GPIO_InitStruct = {0};8 p& ~3 E9 E6 H! q3 O( v
- RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};4 y6 d$ s+ ~' G' M
- DMA_NodeConfTypeDef NodeConfig; u3 k3 }% H; t9 S! q' B
- . ^6 O* b: c9 S: w- G3 L
- __HAL_RCC_LPUART1_CLK_ENABLE();( Q& G% h8 S1 x5 `! a
- __HAL_RCC_GPIOA_CLK_ENABLE();
8 I* |' H/ y9 m- W6 [: K. e% m - __HAL_RCC_GPDMA1_CLK_ENABLE();# J: ^9 F' I; S6 w/ {4 `
9 E" Z! K4 Z5 J: V- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;
! t/ G# Y/ p* c. b9 c J - PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK3;3 v4 Q) b. y! {2 {" V
- HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);: R, J) k) ?( h
4 ]; M3 V: \$ n- D/ O6 T( p- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
: U: i0 Z+ _$ l - GPIO_InitStruct.Pull = GPIO_PULLUP;
* N# Y! R1 J! {- Y" @* C3 n - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
( ^* t! Y- \ z5 X' y3 J. c - </font> <font face="微软雅黑" size="5">' Z: \3 ?* e- ~: V
- GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;2 A) V+ T3 a5 X/ a: m @7 O- T
- GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
- T& d1 s9 k! {1 h3 h: j - HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);1 ` L! ?4 c( k% p# f1 {
- </font> <font face="微软雅黑" size="5">* O I" J! E- V- \
- hlpuart1.Instance = LPUART1;
1 u( e$ J! b6 d - hlpuart1.Init.BaudRate = baud;
) ?' p8 D- U" a; F, h - hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
' k3 Z3 v: x& s2 g' d3 E - hlpuart1.Init.StopBits = UART_STOPBITS_1;/ M7 y# m/ f" b4 s4 Z3 z
- hlpuart1.Init.Parity = UART_PARITY_NONE;( u2 o2 C! P( \! Z
- hlpuart1.Init.Mode = UART_MODE_TX_RX;
$ j E3 \2 z# D Q - hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
b# ?: l5 |/ z+ F; O6 U - hlpuart1.Init.OverSampling = UART_OVERSAMPLING_16;
. U5 L% n1 A8 d5 r/ J - hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;* o3 B0 A9 Y+ d1 t* ?0 r5 ~7 N
- hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
( P1 \4 B$ v" u' D0 C% C: C - hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
* N8 Y& l6 r7 Z- J - HAL_UART_Init(&hlpuart1);: W2 W f% Z$ s; w
- </font> <font face="微软雅黑" size="5">
- G3 A( f/ b* q - __HAL_UART_ENABLE_IT(&hlpuart1 , UART_IT_IDLE);
( M. m; y8 L6 @& N9 M4 U" _ - HAL_NVIC_SetPriority(LPUART1_IRQn,1,1); n! T6 |$ P- j6 |$ U% w8 T
- HAL_NVIC_EnableIRQ(LPUART1_IRQn);+ y0 C. Q2 e4 v. I/ S
- </font> <font face="微软雅黑" size="5">; a2 R/ q( A& E/ z/ k! u* [
- NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
7 n y! H) g) {* i3 ?; v5 Q( W - NodeConfig.Init.Request = GPDMA1_REQUEST_LPUART1_RX;: Z. K6 O& u; E% x' u6 k" B: Z9 _
- NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
8 c3 j3 x# h7 Z/ R1 S5 l1 z2 y - NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;. F% b9 J+ i G6 K) H& X7 A
- NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
- a: P3 W! |: [2 p* Y- D' k5 ] - NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;* c. ]. ]# D1 p# {
- NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;) E0 r: N5 i5 Z- y1 J3 C* w' }
- NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
: f v' \+ o0 Z" T* I - NodeConfig.Init.SrcBurstLength = 1;
) [. g, k B( _/ F: B' k - NodeConfig.Init.DestBurstLength = 1;
! [5 O' A6 v |' @/ ~1 X7 w - NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
' W' p- x6 R# _- B - NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
; E& v# ?: w6 I5 ^2 s- ^- d: s - NodeConfig.Init.Mode = DMA_NORMAL;
9 y5 _6 x0 d5 R# } - NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;! ?- ~! P G, L/ ^( q# i' J
- NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
" N' o H% C6 I( M" T8 P) ~ - NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
( W+ l# ] U5 @; i6 |* Y - HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0);
- t; c9 N* T! i. h - ; `* q* r% u/ S2 G
- HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0);; [) P$ \& V. [' r
- / j i+ L" O, |+ z1 P3 b$ W
- HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0);0 e+ O2 s1 U& t& O
8 V R4 }+ d2 N# m+ m" y' g- handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;) ? |! F8 b' P) w: i
- handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;8 @5 a" ^7 v! [, r
- handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
. k. l- v3 N- L; h! r/ b - handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;, Z3 H2 G$ Q) q w: p
- handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
5 Y/ A7 g8 c. x( M% t - handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
) _. H2 f. }) c' ] - HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0);
2 T" l- f- G2 p( |; U
0 @3 N3 K. \& |( H7 l# ^- HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0);6 l* \6 T; T' v) h' S2 f
- , \- Q# }9 m5 g1 a5 b' x
- __HAL_LINKDMA(&hlpuart1, hdmarx, handle_GPDMA1_Channel0);
/ } A9 K$ E" n( L
8 p( t. d- K( x) w- HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV);: O! y: h9 h* I7 X4 t& M
- </font> <font face="微软雅黑" size="5">. [1 |* W: m# ~
- HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0); z A6 Q! t/ V3 N! @$ r
- HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);4 D \8 f7 G0 [
- }
$ q r' k: S# B9 a4 y4 M
4 K9 V |' [5 |9 [0 Q0 d! ]- void LPUART1_Send_Char(uint8_t ch)3 B* o7 E$ W3 a0 x
- {
3 [3 B' Y* z3 N& P - while ((LPUART1->ISR & 0X40) == 0);
' J: M; s5 D4 R7 e+ n. w9 e - LPUART1->TDR = (uint8_t)ch;
9 i6 {( z6 M2 @. L0 h- y - }5 }9 L9 h" q: Z1 }) O+ G( a
, l' F( c; ^# `' H. g( v- void LPUART1_Send_String(uint8_t * s)9 {3 j; f4 Z* I g! y- t
- {# n4 o4 @4 @3 H; m
- uint32_t i;
1 w0 r' S, t; S7 N5 a- S! l9 Z! z* F0 @ - for(i = 0 ; s != '\0' ; i++)7 P" d9 U: m* }0 @/ w
- LPUART1_Send_Char(s);9 F4 }7 O# s) b0 K& n; Z: Q7 P! d2 D
- }! `+ J4 T# s$ B( Y
- 1 i! M0 r- J. e8 k% H7 W) A
- void GPDMA1_Channel0_IRQHandler(void)8 F9 M+ J4 P) L3 m' ^4 \0 A9 X
- {. L* I/ Z" Q* _- k: C" f6 g& b
- HAL_DMA_IRQHandler(&handle_GPDMA1_Channel0);
# S/ n" Z# A% V - }
( u; q/ b6 C3 {, i - 1 t: P$ y6 `8 M
- uint8_t aRxBuffer[RXBUFFERSIZE];
; @3 }" Z# s$ E4 J) J- T2 Q - ' o/ K% o2 k1 @' x+ T1 J
- void LPUART1_IRQHandler(void) 4 ~" i* d A4 V# I `3 f
- {
$ Y6 ~+ r# U8 @( o1 i - // int temp;
5 `3 i2 Q0 u) M4 y$ m - if(LPUART1->ISR & UART_FLAG_IDLE): ]. z% D3 l7 G* H
- {, y1 W+ ^, ]6 |! h( n1 h Y
- __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);2 H6 b4 h* C' f: w4 F% g- H
- printf("LPUART1_IRQHandler. %d %s\n" , GPDMA1_Channel0->CBR1 , aRxBuffer);
, a3 h2 J$ k- ^, _: W/ _/ ?0 X - </font> <font face="微软雅黑" size="5">
& {, ]$ c7 p$ G5 J; N - HAL_UART_DMAStop(&hlpuart1);8 j7 I7 ?2 e4 [
- HAL_UART_Receive_DMA(&hlpuart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);
0 e9 S( Y) S; p6 l - // rx1_len = BUFFERSIZE - DMA1_Channel5->CNDTR;, S- v9 U/ {! ^5 Q! E' B
- // uart1_recv_end_flag = 1;
2 h, y4 E9 U. O o/ k& O) C/ D% f - }
! p1 V5 e- B+ f! Q( `( \$ G - }</font>
复制代码 在ST的新系列里面,有个特殊机制,使用任何形式的DMA通信必须要打开DMA中断,这个在F103系列是不需要的,是F4以及之后的大部分系列都需要,另外,在F4之后的系列中,对于外设要用的DMA,可以自由配置通道Channel(流Stream/节点Node)等,其实是一个东西,就是DMA通道的意思,不同系列的名称不同,只有F103和F4系列的特定外设是绑定在特定DMA通道的。像本帖子,就把LPUART1的RX功能设置在在GPDMA的通道0(后续还把SPI1的TX功能设置在GPDMA的通道1)。
7 S& `$ j- {* H, K. Z) Z4 S7 d9 G8 a" ? P a& l R/ A/ u' u
, t: { D8 |" I+ H4 d
2 G9 J) r3 a, S: ^) o8 B# G看看运行效果,使用两根typec线分别连接开发板的STLINKV3接口以及用一个USB转TTL模块接在PA2 PA3引脚上:" g0 A; g. A/ h, y; z E! Z, a
% O# G( X, c! X& B X9 ?
首先上电之后UART1和LPUART1都会打印信息,然后,对LPUART1发送数据,UART1会打印接收到的数据以及接收长度(100-DTR寄存器值)。 |
你好,板载ST-LINK电脑可以识别不到吗?
没看懂你的表述是什么意思
就是把板载ST-LINK的C口接入电脑,电脑可以识别到ST-LINK吗?
[md]那肯定可以识别啊,不识别怎么下载代码发帖子😄
使用的是全功能的Type-c线吗?
没听说过typec线还分什么全功能不全功能的,我直接用手机充电线来接开发板的,一端是typeA的HOST,一端是typec,把线连接电脑和手机,能识别出手机的存储卡,那就肯定可以给开发板用