拿到了nucleo-U385开发板,在KEIL环境下编程,需要下载CubeU3支持包,在ST官网即可下载,并且在CubeU3支持包内还有KEIL环境所需要的pack安装包,这个应该是最近才做的一个方便开发者开发的一个机制:
+ B+ x6 c. c, J& G" r
! Q( a* c( f' d; @我直接用点灯的例程来改串口例程,方便省事:& H J* s X2 L8 f
( F5 N! W- y$ m5 L1 c2 M整理好的例程结构如下:
6 s; p# F( F% h/ l1 F6 t- Y% l
; Y# {5 w& g4 e# H, ]根据原理图可以得知,开发板的STLINKV3 VCP连接的串口是UART1,即PA9 PA10,可以直接与电脑的串口助手进行通信,另外开发板上还有PA2 PA3引脚,这个引脚被复用为LPUART1:& |+ w5 f- O i# Y, {
. t$ q" b! T" ~) y! R" e: {) S
我这个帖子就实现UART1和LPUART1的双通道串口通信,其中把LPUART1的接收功能打开,使用空闲中断和DMA进行接收,先看看UART1的初始化代码:- <font face="微软雅黑" size="5">UART_HandleTypeDef huart1;( b0 j/ E* r7 i# E2 Q) a* ]( j
9 @: I) e% M' Q/ [- int fputc(int ch , FILE *f)
( n$ _. H: o/ z; W2 b$ e7 G - {$ t1 |% f( o- E4 i
- while ((USART1->ISR & 0X40) == 0);
* e! _4 ]+ z9 s0 z - USART1->TDR = (uint8_t)ch;
1 e* Y, z; d) e# {+ F4 I8 i - return ch;- i& [! E. K) f" _+ f) H
- }# R; h* j, _- l1 X9 [" p
- $ P! z- @0 C8 s2 G, I' o
- void UART1_Init(uint32_t baud)) d, `! Q0 f( t: X# \" Y
- {
/ o8 R7 L& h) v - GPIO_InitTypeDef GPIO_InitStruct = {0};
- \! z; M$ P. }- P. f, j - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
& @5 b7 s# k# z/ M, B; h4 f - " V6 \+ @8 r- x
- __HAL_RCC_USART1_CLK_ENABLE();
: w) M! p/ _8 ~! |6 z6 A- s- `: n9 X; W - __HAL_RCC_GPIOA_CLK_ENABLE();
) S+ B2 r* m: }. v# p
0 ^$ X5 }8 I) l) b8 P- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;0 A. {- A O6 g3 a7 w) k1 i
- PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
! Q V: v; W9 c L& D' l7 e - HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);: Y& ?0 e% U0 @6 n6 ^* _; J
, X0 z6 f* D, \/ F3 ^ m- GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
5 [+ J% a6 w! g7 R! X6 j - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;* ~4 R) {* H! d/ b. [# }
- GPIO_InitStruct.Pull = GPIO_PULLUP;
+ c9 @ }8 }3 `8 S0 V1 Y - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;/ N9 o' I4 S7 W# V# e: ]7 }! \
- GPIO_InitStruct.Alternate = GPIO_AF7_USART1;6 h5 m% A' r0 V% ?& K* b+ j: F, {
- HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);$ k+ m# z( s# K/ n" N) V. g
- </font> <font face="微软雅黑" size="5"> Q9 | `0 K! p) P# {
- huart1.Instance = USART1;
% i# h- Y# }! N S! f f$ e' \ - huart1.Init.BaudRate = baud;
. S0 J7 a+ O* T r8 S. Z5 I - huart1.Init.WordLength = UART_WORDLENGTH_8B;9 e- A' J9 S; d" _4 r W s2 Z
- huart1.Init.StopBits = UART_STOPBITS_1;, C( R, Y, K0 T. k- g
- huart1.Init.Parity = UART_PARITY_NONE;1 X! s- u: l7 ?' T+ d3 r
- huart1.Init.Mode = UART_MODE_TX_RX;5 T$ L- @$ I2 ]. U4 T) d8 s/ ^
- huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;- q% h# [0 G) ~) }! m/ P# N
- huart1.Init.OverSampling = UART_OVERSAMPLING_16;
4 f0 g4 k! r5 L1 z7 q5 q - huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;" O5 \. P2 P$ Y* R
- huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;/ y' K* i* G1 b; l4 c: Y& [
- huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;' Q1 y- j7 h( `4 F1 O
- HAL_UART_Init(&huart1);
- {/ l0 S* }, q - }</font>
复制代码 非常简单,只要熟悉STM32编程的没有一点难度,然后是LPUART1:
: n, J* t- Z- P1 r/ f! J- <font face="微软雅黑" size="5">UART_HandleTypeDef hlpuart1;
5 I, i6 Q' G6 G8 W4 ~
. V2 v4 Q6 L% K) I- DMA_NodeTypeDef Node_GPDMA1_Channel0;
$ W4 Z; o! I% E! A) U - DMA_QListTypeDef List_GPDMA1_Channel0;% Y* m3 X) H6 M- \1 M
- DMA_HandleTypeDef handle_GPDMA1_Channel0;: }9 k0 z: P* ?5 ]# D. V) f
- $ ~; D1 f v4 [# ]
- void LPUART1_Init(uint32_t baud)2 e N5 b) N' k) U: R; a
- {
6 y+ I: h' V. Y7 B) u - GPIO_InitTypeDef GPIO_InitStruct = {0};
1 }2 \# r& h0 K0 I$ ^6 L - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
' s1 ^9 G( T: j, m2 ]1 D( E - DMA_NodeConfTypeDef NodeConfig;
+ O& X3 v' B# h, X# B7 L$ z, i$ I
! M9 D, z6 t- S( c1 x- __HAL_RCC_LPUART1_CLK_ENABLE();
& n5 n# @+ Y2 k/ A; Y - __HAL_RCC_GPIOA_CLK_ENABLE();; z- l" z! L" ^) O ?; J( L
- __HAL_RCC_GPDMA1_CLK_ENABLE();
2 o }5 v/ w C& w
( H! C; q# K0 |$ t, R- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;6 t, r" d# U6 n9 ^# Y3 l8 m
- PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK3;( v6 w N/ r* Z, J# U9 n
- HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
0 C+ Q/ H* X! t - % d4 N ~# {) `9 N& L3 ]# V
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
3 B; N4 Z6 i: Y - GPIO_InitStruct.Pull = GPIO_PULLUP;- J2 l& k" _: }* i0 V3 L$ O3 {
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
8 h, J4 ^7 u7 E- b. ?/ w2 @ - </font> <font face="微软雅黑" size="5">
" j" z2 x* }4 C - GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;
% j7 O- K U; K/ h: P5 V9 I% j" ~ - GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;2 X0 i% [+ U( u
- HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
2 M- I$ j* t* N7 b - </font> <font face="微软雅黑" size="5">5 Y, A" \ `4 s2 \: z }( V! e
- hlpuart1.Instance = LPUART1;/ G4 v/ W/ |+ Z9 g- ~# K
- hlpuart1.Init.BaudRate = baud;) p# z) w/ |0 S! Q: o5 ~ J k" e
- hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;1 V& v* @* v+ n' D8 L/ b
- hlpuart1.Init.StopBits = UART_STOPBITS_1;
# J3 \/ Z- C* }9 K1 J& ~ - hlpuart1.Init.Parity = UART_PARITY_NONE;
# m: K8 S+ x7 X. Y, ?" x7 E) M - hlpuart1.Init.Mode = UART_MODE_TX_RX;
& N E/ ~! R2 o7 R4 |- l5 G - hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;$ ~; E$ B, T9 X. |+ C7 q
- hlpuart1.Init.OverSampling = UART_OVERSAMPLING_16;
( U- B' [3 \: U/ i# Z: @0 T - hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
0 A* x/ h- X) u- e% K, T - hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
, H$ n$ Q) ~ b- D - hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;* u/ V( b3 P6 L$ t
- HAL_UART_Init(&hlpuart1);
; }* J9 o4 a# j- F3 b - </font> <font face="微软雅黑" size="5">
5 o" t4 B1 C4 Y, H# U' e; _ - __HAL_UART_ENABLE_IT(&hlpuart1 , UART_IT_IDLE);# P o8 u2 K% ^& J2 F- u# O2 q
- HAL_NVIC_SetPriority(LPUART1_IRQn,1,1);
0 m6 b9 w9 x6 j0 q( E( k4 t3 l$ | - HAL_NVIC_EnableIRQ(LPUART1_IRQn);
' a* W J0 I: ~4 m: { - </font> <font face="微软雅黑" size="5">
3 f t' ^# U0 t* ~- \ - NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;& Y- _0 _4 G v" z
- NodeConfig.Init.Request = GPDMA1_REQUEST_LPUART1_RX;/ F7 I6 p$ Z, e' N1 U+ N$ h1 i
- NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;. w1 r+ I' O% h% ^- y
- NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
+ i; J* ?' Y6 d' m3 J# f - NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
/ h9 L Q, a) E, O# x6 n - NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;6 u1 ]) Q* L W9 ^& }9 S: k7 n9 L
- NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;* c5 [! u, ^/ @" X5 q/ f
- NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
4 d8 f7 @0 j' G- N" U- Y/ _ - NodeConfig.Init.SrcBurstLength = 1;! o# e! J6 R6 q9 l! l+ _
- NodeConfig.Init.DestBurstLength = 1;$ g$ S+ ]( m A; H; v. j9 Q6 @
- NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
- [2 y* d/ z& ~ L - NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
: H' O9 Y/ {/ Z! x8 ^3 E - NodeConfig.Init.Mode = DMA_NORMAL;8 m( A, B0 \& q7 m, p4 ]
- NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
& I' ?3 ]' ^& @+ W* L7 ~ - NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
5 x; t+ F" l' v5 D5 s# R - NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;, A1 u2 ?7 Y: |& N% Y' f) F# _
- HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0);
. I# a" g4 H) j9 B - ! c0 {- d7 y! {' U# `
- HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0);
; q- L) }8 H n
8 A3 o* \8 t1 t- HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0);: V, t4 D: {: {8 |$ \
+ s+ G1 Q' ]! O. G- handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0; Y9 I) s7 f0 I* k/ M
- handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;, t, K) u$ g8 @
- handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;- I5 d8 {' {: N
- handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;! x/ T( ~& e8 j
- handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;2 {6 x) b* q% ]1 R2 o$ G
- handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
' R) e! U7 r3 H5 R' K - HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0);
) s. V6 T6 |5 J |' t* h4 a - / J' y( z1 e2 z$ z3 g3 T3 I
- HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0);" V% d1 D! W' U0 h- r# b
4 [ J- E* T; T# g- __HAL_LINKDMA(&hlpuart1, hdmarx, handle_GPDMA1_Channel0);
; t1 v5 f1 c5 N: N0 w& V - ; l$ r. |# R' t1 p+ Z! W% f
- HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV);
3 j6 i$ u4 a/ I5 y - </font> <font face="微软雅黑" size="5">
$ l9 V% p: L2 \+ v# `, R - HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);/ V+ N# ]! p: _5 y* O
- HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);! q( ^9 f/ e$ T1 V( f
- }- A/ [6 g+ B% A j/ ~: M% R4 ? j
* Z7 I/ D$ N- T+ _3 X9 n) k- void LPUART1_Send_Char(uint8_t ch)
! W# @7 w& H. `8 L/ U - {
4 S [! o0 p" @) D1 _6 w - while ((LPUART1->ISR & 0X40) == 0);& z/ z' t; C' r* ?
- LPUART1->TDR = (uint8_t)ch;0 p0 q; s# X/ ~7 F# N3 H1 }
- }3 l4 X* F' ?/ t5 K& I E
) T2 I) Y1 }: |+ `- void LPUART1_Send_String(uint8_t * s)
/ [: m* m1 p8 H1 p- t* ^# f6 } - {
$ t% s3 @. ?9 c - uint32_t i;
7 P7 H* h0 E1 H8 Q! [ - for(i = 0 ; s != '\0' ; i++)2 ~/ d/ E* Q6 W' N, s
- LPUART1_Send_Char(s);
" E+ d3 s* ^ Y' F - }: d& u+ f& u! c- X1 q/ w' A5 T
- 4 s* d# ?' b, S* X2 g* n" ~
- void GPDMA1_Channel0_IRQHandler(void): F& b, ]5 O }8 Q7 u
- {
# T$ z6 k4 I3 L2 e - HAL_DMA_IRQHandler(&handle_GPDMA1_Channel0);
6 n$ R: i5 {4 }( m2 P& p - }
; f! S. N. P0 Q5 `7 W: r
5 D9 [9 @, H' k4 K1 v9 Z: y- uint8_t aRxBuffer[RXBUFFERSIZE];2 W z, W; X( q+ i1 A$ u
- 0 i, x+ S. Z/ _0 p' ]& m5 @$ G
- void LPUART1_IRQHandler(void) , P/ V& o' {& F2 l4 K4 r/ U- A0 h7 \
- {
. u& t1 Q1 v V, q - // int temp;6 ?* p Y8 V* Q. b L
- if(LPUART1->ISR & UART_FLAG_IDLE). G( u" W8 Q+ H8 \6 m5 d* @
- {
& z6 O) S* T. y4 l4 y' q: { - __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);
6 ^3 L5 y; m& ]3 G - printf("LPUART1_IRQHandler. %d %s\n" , GPDMA1_Channel0->CBR1 , aRxBuffer);% c1 q) t1 o8 _9 Y; X0 W7 l8 V ?
- </font> <font face="微软雅黑" size="5">
2 s% h. L" o3 @( n5 ?: ` - HAL_UART_DMAStop(&hlpuart1);6 ]0 G4 S# n0 }- [, N% J
- HAL_UART_Receive_DMA(&hlpuart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);
% q" M( O# A! k% \3 y! f& j - // rx1_len = BUFFERSIZE - DMA1_Channel5->CNDTR;) m3 l4 [ [* ]2 C" q' g4 E7 c
- // uart1_recv_end_flag = 1;0 k9 M0 ]) a8 r# r
- }: g S- a) n5 v3 U
- }</font>
复制代码 在ST的新系列里面,有个特殊机制,使用任何形式的DMA通信必须要打开DMA中断,这个在F103系列是不需要的,是F4以及之后的大部分系列都需要,另外,在F4之后的系列中,对于外设要用的DMA,可以自由配置通道Channel(流Stream/节点Node)等,其实是一个东西,就是DMA通道的意思,不同系列的名称不同,只有F103和F4系列的特定外设是绑定在特定DMA通道的。像本帖子,就把LPUART1的RX功能设置在在GPDMA的通道0(后续还把SPI1的TX功能设置在GPDMA的通道1)。
* G4 e' G7 A( q0 m0 _1 z
$ F: E, s, H, g. V. Y G) g
. P! Z$ T( y5 b6 Q: k9 y% I# d2 _" @7 i4 j
看看运行效果,使用两根typec线分别连接开发板的STLINKV3接口以及用一个USB转TTL模块接在PA2 PA3引脚上:
2 u7 c5 f. s6 Y
7 u' U4 v. B6 ~. r- q
首先上电之后UART1和LPUART1都会打印信息,然后,对LPUART1发送数据,UART1会打印接收到的数据以及接收长度(100-DTR寄存器值)。 |
你好,板载ST-LINK电脑可以识别不到吗?
没看懂你的表述是什么意思
就是把板载ST-LINK的C口接入电脑,电脑可以识别到ST-LINK吗?
[md]那肯定可以识别啊,不识别怎么下载代码发帖子😄
使用的是全功能的Type-c线吗?
没听说过typec线还分什么全功能不全功能的,我直接用手机充电线来接开发板的,一端是typeA的HOST,一端是typec,把线连接电脑和手机,能识别出手机的存储卡,那就肯定可以给开发板用