拿到了nucleo-U385开发板,在KEIL环境下编程,需要下载CubeU3支持包,在ST官网即可下载,并且在CubeU3支持包内还有KEIL环境所需要的pack安装包,这个应该是最近才做的一个方便开发者开发的一个机制:1 l1 A- p0 n/ x- X/ j
6 r( k! {% ?, n7 l
我直接用点灯的例程来改串口例程,方便省事:! R. K7 d } W# l$ S9 a# M) Y: v9 F
# t& P0 l9 V/ x整理好的例程结构如下:
# f$ x# I. y L( t4 D1 g# Z% G
, i& j9 m; g8 F
根据原理图可以得知,开发板的STLINKV3 VCP连接的串口是UART1,即PA9 PA10,可以直接与电脑的串口助手进行通信,另外开发板上还有PA2 PA3引脚,这个引脚被复用为LPUART1:% m& M; A! `9 x/ V6 C4 ?$ T
5 F, X, y! ~5 _$ ?/ F4 ~6 ~7 A我这个帖子就实现UART1和LPUART1的双通道串口通信,其中把LPUART1的接收功能打开,使用空闲中断和DMA进行接收,先看看UART1的初始化代码:- <font face="微软雅黑" size="5">UART_HandleTypeDef huart1;
, X1 n% E4 X1 z6 h
: i3 D, \4 p' b- int fputc(int ch , FILE *f): x, k; y+ g6 L% @9 g
- {
- j1 |) t1 g5 t7 o, ? - while ((USART1->ISR & 0X40) == 0);
@% Q3 u) D4 y - USART1->TDR = (uint8_t)ch;( j3 i4 P6 _/ M& g3 k
- return ch;
" J/ g) b/ L. v- x8 O9 T" S - } {+ d' m% v1 `8 k& p
- 5 Z+ k: L. t3 B. d
- void UART1_Init(uint32_t baud)
7 H! @8 T$ r' }7 ?) c ^/ c; V - {
" H2 d/ m; i) J+ L - GPIO_InitTypeDef GPIO_InitStruct = {0};
M7 m/ u; c1 F7 O* I5 H* G0 p - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
; \& K6 J' j3 [+ ^' o/ \& b) S - 3 ?$ k0 X1 @0 e! O
- __HAL_RCC_USART1_CLK_ENABLE();+ X6 c- i+ l$ G9 h- p
- __HAL_RCC_GPIOA_CLK_ENABLE();
: [9 } d) e% n4 W$ J) v) A9 N - y0 H5 }$ f. h0 s
- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;+ ^! G. h" x: R$ L) s8 U' r/ h
- PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;" f) i, B# d, m; P B; S
- HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
& n, n" ~! H% x$ ]& S: y- E - ' A$ S) g( j" F( i g( M
- GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;8 Q- Y( I( {( p1 I) c
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;6 \$ }8 ~. w; `
- GPIO_InitStruct.Pull = GPIO_PULLUP;
. w3 V; e- f. G9 I$ ?, @ - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
( I. w' ^" {7 F/ Z0 g - GPIO_InitStruct.Alternate = GPIO_AF7_USART1;' j4 h+ @1 V" T( o, K6 j v4 t/ d& G, \
- HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
2 C: ~9 F2 ` }7 G6 q$ b7 q5 } - </font> <font face="微软雅黑" size="5">
0 w. D2 \" v+ z$ z - huart1.Instance = USART1;& {% c: j' v3 m
- huart1.Init.BaudRate = baud;0 C# D# X4 [1 O
- huart1.Init.WordLength = UART_WORDLENGTH_8B;! H' ~ B) Y5 m$ q+ }) L# j% ? ^
- huart1.Init.StopBits = UART_STOPBITS_1;% y% K1 s8 U5 h z3 J! q. V
- huart1.Init.Parity = UART_PARITY_NONE;
, h' Z1 o4 b+ K% V - huart1.Init.Mode = UART_MODE_TX_RX; l/ ?+ \/ r# H& ?) R8 m! P0 S3 d
- huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;6 K$ R0 Q, t1 k( }% C$ l+ P
- huart1.Init.OverSampling = UART_OVERSAMPLING_16;) v7 v4 {! s R6 y. n+ n
- huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;8 _$ U" J7 x, Z2 H
- huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
; X2 T4 _! a+ M9 k - huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
" E: M9 Y# \" e* j8 X8 B - HAL_UART_Init(&huart1);. L0 D: Q# L( H9 c
- }</font>
复制代码 非常简单,只要熟悉STM32编程的没有一点难度,然后是LPUART1:6 K( y% k. x3 Q" W; l, l% o! @7 p
- <font face="微软雅黑" size="5">UART_HandleTypeDef hlpuart1;
3 c5 r( _# b5 p4 i6 x0 U - 6 U) S1 R# z& Y9 L
- DMA_NodeTypeDef Node_GPDMA1_Channel0;
2 f/ K( A% s) b - DMA_QListTypeDef List_GPDMA1_Channel0;
! W4 C; p4 D5 u, v! d: E- V+ a - DMA_HandleTypeDef handle_GPDMA1_Channel0;
1 F) t z4 e2 t3 Q. w/ a/ B q
! X8 A) |- E& T) T4 r- void LPUART1_Init(uint32_t baud)
$ Z5 ?; t g5 V( T8 X5 g - {
3 ]( T$ F5 K! k* M, V1 G7 X7 n - GPIO_InitTypeDef GPIO_InitStruct = {0};
1 V- X/ H, R! T6 w n8 N4 p - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};1 n* j6 @" F, M) U. V7 T$ w
- DMA_NodeConfTypeDef NodeConfig;7 l2 c2 e q, V% Y
* u: E) }7 G. h; i8 z$ I% W# H- __HAL_RCC_LPUART1_CLK_ENABLE();7 @. h: E1 F; y; G( p2 |# K
- __HAL_RCC_GPIOA_CLK_ENABLE();4 N5 g! s$ X# D# \& ~
- __HAL_RCC_GPDMA1_CLK_ENABLE();
4 V& X1 v( q% c
7 E8 H: b; @$ D$ [- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;' h, w, c" ~/ Q
- PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK3;( ~' v) A7 k6 o( a6 I- x3 \- {" g
- HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);5 g) S* N& v$ N
& p- o$ W7 ?2 E) q# ~! D/ X- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;1 s# [1 I( W9 h' |
- GPIO_InitStruct.Pull = GPIO_PULLUP;" ^/ c% w/ R) F5 Q
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
; E7 {+ |( U& D9 ^* b' E - </font> <font face="微软雅黑" size="5">3 W, K; t" ?1 }. p4 O0 d
- GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;" W! ?" w1 p0 |# I# q
- GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;* k% O5 J- @; l9 O8 m) B) I9 R
- HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
6 q4 c7 e6 q3 {/ A+ z+ ^! ]: \( s - </font> <font face="微软雅黑" size="5">
' C2 I. H: n- |+ V - hlpuart1.Instance = LPUART1;$ m# a* C) Y4 T* i4 D5 e7 m- z
- hlpuart1.Init.BaudRate = baud;$ ~% b1 h: b' a' I
- hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
# }" e7 Z& q, M - hlpuart1.Init.StopBits = UART_STOPBITS_1;+ p! s1 a9 ?8 S0 m" A4 Y
- hlpuart1.Init.Parity = UART_PARITY_NONE;6 E( X0 e k4 V$ B% S
- hlpuart1.Init.Mode = UART_MODE_TX_RX;
. [/ t/ u& N e. @ - hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
U$ S2 O! y& {6 D. U3 _7 \- R - hlpuart1.Init.OverSampling = UART_OVERSAMPLING_16;
% `$ j) i( c0 E6 p; H - hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
K. T" f( b+ r* N5 r8 d- s- ] - hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
& ?( ^" K5 p! e6 |0 {, U5 @* J( Z3 m, A - hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;% x9 j, M. u5 D' a# X( c
- HAL_UART_Init(&hlpuart1);
+ o: K8 m( @% j6 M( U1 x& I# Y - </font> <font face="微软雅黑" size="5">9 f; j( S! q/ k- k" v+ O, w
- __HAL_UART_ENABLE_IT(&hlpuart1 , UART_IT_IDLE);. a& v3 D+ _7 U2 r9 \: X u
- HAL_NVIC_SetPriority(LPUART1_IRQn,1,1);% V! [& t2 q @ m3 _
- HAL_NVIC_EnableIRQ(LPUART1_IRQn);( Q% ?" \" M) e: u% d
- </font> <font face="微软雅黑" size="5">
- W# \( d6 _; G7 W$ r+ d - NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
; j( ]7 a% j0 p, ]5 l9 q - NodeConfig.Init.Request = GPDMA1_REQUEST_LPUART1_RX;
- @- f, c5 T# _ V% O - NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
; s5 Z/ g0 @2 Y" j - NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
% p. z: a) @' P) T$ Q - NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
/ x/ [" a H3 a! q* `; X - NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;9 I6 f; g3 i7 d
- NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;- K1 a3 [3 F+ f$ C1 E
- NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
/ w: D V/ \4 W0 ]: X - NodeConfig.Init.SrcBurstLength = 1;
& t- i; }& f6 P$ r - NodeConfig.Init.DestBurstLength = 1;+ m1 l- o2 E6 b: l/ {4 N
- NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;# |4 Q& a/ w, c" k! ~
- NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;$ q- X/ V$ [& T" x
- NodeConfig.Init.Mode = DMA_NORMAL;6 b/ y$ v3 Q, d
- NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;( i' P# T" d1 m" M
- NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
# t* H0 j/ x$ Z; x1 v8 O7 m9 R - NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
! S; l6 v3 g9 u6 w$ E/ e2 h3 g - HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0);5 T. P# E3 n; \4 V; S6 {" N
- ; r4 h; K* f3 Z y8 N. v) S( f9 d' P
- HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0);) @! p( R7 b9 j! u3 W9 [
- # h: b( E/ A( R u/ c j9 u3 e
- HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0);
F) p" h4 y. i* I; P
$ Q* J1 W; \4 V" s H; i- handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
) o5 R7 ]) K4 Y! F/ f' f - handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;0 z! B3 h& B8 t) E% w- \( o7 C
- handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;# w6 g3 |7 Z3 g6 j8 R& i! \' H6 y
- handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
9 x$ v: N2 a' P0 j - handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;0 Z5 [. M1 `% H2 J4 x" N! X
- handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
# }0 J" i6 }# W2 ^& U+ u: Q - HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0);) Z( @' R( C: C
, [5 x G/ a7 S& b- HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0);# n4 P s( G+ g+ X; }0 z* S
- - e! ]2 i6 Y1 }! w3 o: l' s
- __HAL_LINKDMA(&hlpuart1, hdmarx, handle_GPDMA1_Channel0);
+ n% E0 S5 s$ c9 Y
3 J: N" I9 v5 t# _9 ?- HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV);: o _4 [( E+ n/ M" b3 b d
- </font> <font face="微软雅黑" size="5">3 {& z w( n+ e0 t) u9 M
- HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);) W R/ E1 P- E) v X) g6 |2 g1 q
- HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);5 ?9 a: P2 x" A
- }
7 N9 |8 Q: g8 `( v, {( N9 q - 3 w0 T) d q7 ?6 Y+ H
- void LPUART1_Send_Char(uint8_t ch)
9 K( Q# A" o, R }2 ` - {2 o1 o4 q, l. Y/ X" u6 L4 V( f
- while ((LPUART1->ISR & 0X40) == 0);
* z+ ^5 e, |( }! f: C/ P* y1 s - LPUART1->TDR = (uint8_t)ch;
. ^) L8 } i0 {5 B - }
% ?! ^) n- z1 t) A( E - ( F- H t9 @1 a4 l2 b$ S h* N/ t
- void LPUART1_Send_String(uint8_t * s)$ g2 ?6 ~/ K, V5 F2 B+ u
- {# i- |! Y1 s" _! V
- uint32_t i;
- B$ \/ y7 @& f1 z8 g: N$ H - for(i = 0 ; s != '\0' ; i++)
' E' ?* M- n) [) ] - LPUART1_Send_Char(s);$ e" p8 N' i. a( |0 [
- }
1 p/ f: W% g- u, m5 o - ) h. A/ _* o6 r
- void GPDMA1_Channel0_IRQHandler(void)
, ]. Y% E" X* z1 [! m - {
# @/ M2 L, n8 @' R - HAL_DMA_IRQHandler(&handle_GPDMA1_Channel0);
h L6 g9 _: y: ~. U5 D6 } s$ q - }& }; E( M0 R! h1 X
7 P! b7 {4 M& ^* a- uint8_t aRxBuffer[RXBUFFERSIZE];2 U. D. j- a3 G0 H5 x
6 `7 ]1 {; g8 A" p2 Q3 V& P- void LPUART1_IRQHandler(void) ) g! }, E, W8 d$ \7 P
- {2 D7 D: F/ R& G) E/ {: Q
- // int temp;; y/ }2 I0 v7 y+ ^3 F3 R* l
- if(LPUART1->ISR & UART_FLAG_IDLE)
# E/ l; j" H* J0 O7 A+ Y7 j - {
3 H8 i% r4 E, ~+ R* V: ?- C - __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);6 h* @; u, S' G. l/ |
- printf("LPUART1_IRQHandler. %d %s\n" , GPDMA1_Channel0->CBR1 , aRxBuffer);8 V2 ^' k, G6 `, J2 |; m2 R0 p# ]& m
- </font> <font face="微软雅黑" size="5">) p2 L+ c; n4 ~! n( N" |
- HAL_UART_DMAStop(&hlpuart1);
6 r& J# D" L3 ]# T3 I - HAL_UART_Receive_DMA(&hlpuart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);, K4 m& j$ {; @2 R4 j
- // rx1_len = BUFFERSIZE - DMA1_Channel5->CNDTR;
1 P0 a* I2 N6 q0 q+ k - // uart1_recv_end_flag = 1;% }9 a8 j# s B: i! E# m
- }
% B ]& f4 K6 W% n! i - }</font>
复制代码 在ST的新系列里面,有个特殊机制,使用任何形式的DMA通信必须要打开DMA中断,这个在F103系列是不需要的,是F4以及之后的大部分系列都需要,另外,在F4之后的系列中,对于外设要用的DMA,可以自由配置通道Channel(流Stream/节点Node)等,其实是一个东西,就是DMA通道的意思,不同系列的名称不同,只有F103和F4系列的特定外设是绑定在特定DMA通道的。像本帖子,就把LPUART1的RX功能设置在在GPDMA的通道0(后续还把SPI1的TX功能设置在GPDMA的通道1)。5 f9 z, G8 z3 r* M$ e- o3 C
9 d) R5 h& V& n5 `3 G
! F% _$ X. @$ h6 P* d C, w
, \ q, e. b- J$ z) h! H5 j看看运行效果,使用两根typec线分别连接开发板的STLINKV3接口以及用一个USB转TTL模块接在PA2 PA3引脚上:
/ V2 @' J) ^% w3 }0 }
/ i5 q5 {: r/ I/ A首先上电之后UART1和LPUART1都会打印信息,然后,对LPUART1发送数据,UART1会打印接收到的数据以及接收长度(100-DTR寄存器值)。 |
你好,板载ST-LINK电脑可以识别不到吗?
没看懂你的表述是什么意思
就是把板载ST-LINK的C口接入电脑,电脑可以识别到ST-LINK吗?
[md]那肯定可以识别啊,不识别怎么下载代码发帖子😄
使用的是全功能的Type-c线吗?
没听说过typec线还分什么全功能不全功能的,我直接用手机充电线来接开发板的,一端是typeA的HOST,一端是typec,把线连接电脑和手机,能识别出手机的存储卡,那就肯定可以给开发板用