拿到了nucleo-U385开发板,在KEIL环境下编程,需要下载CubeU3支持包,在ST官网即可下载,并且在CubeU3支持包内还有KEIL环境所需要的pack安装包,这个应该是最近才做的一个方便开发者开发的一个机制:& d. j. Q: s: Q9 V
$ z5 K6 _- i1 Z) O( d0 T% P) V我直接用点灯的例程来改串口例程,方便省事:6 H! k* c( D9 f8 W4 Y
4 j$ W5 o! [5 x+ a整理好的例程结构如下:
6 I; v' ?# A6 ^1 b r7 S2 l0 z
) z* }1 t$ }( z$ r. [
根据原理图可以得知,开发板的STLINKV3 VCP连接的串口是UART1,即PA9 PA10,可以直接与电脑的串口助手进行通信,另外开发板上还有PA2 PA3引脚,这个引脚被复用为LPUART1:
- { K1 {, ]4 h, c9 `: a9 Q0 O' D$ @; V
2 L& q9 V. _* M) p% b% j我这个帖子就实现UART1和LPUART1的双通道串口通信,其中把LPUART1的接收功能打开,使用空闲中断和DMA进行接收,先看看UART1的初始化代码:- <font face="微软雅黑" size="5">UART_HandleTypeDef huart1;% X) }; I& o1 ^0 f" m% e5 M
7 [6 l% j& i& F1 V# _* s% H% @- int fputc(int ch , FILE *f)
' `; E; }' h2 ^8 ^6 N5 | - {
( Z' r! D; |$ Y5 X# u - while ((USART1->ISR & 0X40) == 0);2 ~2 d. o9 T3 T8 _6 l
- USART1->TDR = (uint8_t)ch;9 _! v. m; ?1 C, k1 o/ j& p, G) Z
- return ch;; R, l E+ D4 ]+ W
- }. N2 N, [- _( r6 E0 b( R
- 1 `: B8 J6 f7 P5 R
- void UART1_Init(uint32_t baud)$ j0 B0 T* W( v E& f
- {' C% Q6 m& [9 A
- GPIO_InitTypeDef GPIO_InitStruct = {0};
$ L" F: n2 q/ L - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
+ D- R$ V! r' s# k( C. G; [+ d; q
7 ^' Z* C) i( T' o/ R: ? Y- __HAL_RCC_USART1_CLK_ENABLE();
" K* D: E, c2 L! A; M) h - __HAL_RCC_GPIOA_CLK_ENABLE();) x0 x7 m8 ?6 B2 e5 t+ X. }, d/ }! w
0 {; G; N( H( u, Z0 O* y2 d8 N/ ~- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;0 c: ~# c3 D* {4 F- B& _
- PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
# u$ ]; C! f# F, v - HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);; E8 ?7 _; T3 @( b
- 9 Y3 B7 F( i8 T. a1 V. @4 D0 a
- GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
5 I/ t. b4 I p! T( { - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;3 H$ i% q! U7 M' ?) g# X2 k4 K" E
- GPIO_InitStruct.Pull = GPIO_PULLUP;
+ ~. y& b; t" H4 ?/ n - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
# Q/ _6 M, g, W2 s/ v" R$ { - GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
: \1 S- d4 i( O. |* C - HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
( O4 Y) r. P9 l0 N/ b- Q) H - </font> <font face="微软雅黑" size="5">* v! f B7 O9 K
- huart1.Instance = USART1;
! Q3 I3 O; }; a8 R+ [- L, X - huart1.Init.BaudRate = baud;
# z0 E: ~9 r1 k. L+ l0 K7 J. x) e+ R - huart1.Init.WordLength = UART_WORDLENGTH_8B;
2 M4 ] o7 t* J( Q, H$ j - huart1.Init.StopBits = UART_STOPBITS_1;
) Z: \5 c$ D( N: \9 V9 X% m - huart1.Init.Parity = UART_PARITY_NONE;5 d8 u# [7 T: i _6 L
- huart1.Init.Mode = UART_MODE_TX_RX;
1 i g+ K: F6 i, H; ^ - huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;; S, w- z p# A
- huart1.Init.OverSampling = UART_OVERSAMPLING_16;$ v$ L. Y7 r" M8 f$ y! t( v5 F; N
- huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
6 ?4 }$ ^& _3 `" Z4 W! K/ f - huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
% \1 m! w* G6 w) ~. t - huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
- W T: C- R" g$ v1 A7 d7 `9 A! Y - HAL_UART_Init(&huart1);
; @! p- C: `( W/ ` - }</font>
复制代码 非常简单,只要熟悉STM32编程的没有一点难度,然后是LPUART1:7 O2 _! R! `% l! X! n: A# H
- <font face="微软雅黑" size="5">UART_HandleTypeDef hlpuart1;
8 F! s, f: W- ?2 Y6 r
G. |1 ~ H% w- A u& ?. V- DMA_NodeTypeDef Node_GPDMA1_Channel0;2 n$ S j/ w2 ?2 }" M
- DMA_QListTypeDef List_GPDMA1_Channel0;
/ ]3 H1 S! D @ - DMA_HandleTypeDef handle_GPDMA1_Channel0;
, ?5 M, O: T- X - , s7 }7 t3 d4 o" I
- void LPUART1_Init(uint32_t baud)
0 K6 \5 A. V% F% X - {
" d1 M {0 ]$ _1 u9 H! ?6 _- \( G3 F& E - GPIO_InitTypeDef GPIO_InitStruct = {0};
) J: d8 T9 y/ l' X! V3 `2 ^ - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
$ j7 G* _5 ~; u: Y - DMA_NodeConfTypeDef NodeConfig;8 `5 p( Q0 P( \
- 0 ], p" j% b# ]4 u! f
- __HAL_RCC_LPUART1_CLK_ENABLE();# J# R. j. v& s
- __HAL_RCC_GPIOA_CLK_ENABLE();8 q# `; i2 X" R/ o4 ^) V+ i
- __HAL_RCC_GPDMA1_CLK_ENABLE();
; D' o" ]4 A" ~+ F# R" Z7 `
" v% T1 F- l2 K/ w+ ~! @' @- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1; R) a9 c+ D# ^
- PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK3;
3 S; Q8 l( Z6 X/ w1 [: P% K. `6 R - HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);" Q3 \- B' f# [, c) h
D" N1 L- ? |8 x4 a* ]- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
" Z9 r( e! C, H% z6 q! z - GPIO_InitStruct.Pull = GPIO_PULLUP;& l) j" Y& }0 r7 j) e
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
" P5 v9 s% w1 s - </font> <font face="微软雅黑" size="5">
7 N9 X3 s8 }, |4 S+ o - GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;
1 V1 k8 Z2 d& y. j" K, t# H- z - GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
" ]5 y% B/ h- L- K8 t* K - HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);/ S! x# q; W3 B- m
- </font> <font face="微软雅黑" size="5">
9 l* P$ D% l3 f( S7 \; l6 N' X - hlpuart1.Instance = LPUART1;
2 r r- a: Y4 V( Y6 R+ H$ T6 {( y% i - hlpuart1.Init.BaudRate = baud;
1 J2 f' \# Y6 W: W* i - hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
1 O8 G# e1 b g - hlpuart1.Init.StopBits = UART_STOPBITS_1;1 t2 E K1 o2 o1 k E8 w
- hlpuart1.Init.Parity = UART_PARITY_NONE;
$ `8 Q. z; P5 ?' _- F z - hlpuart1.Init.Mode = UART_MODE_TX_RX;1 \) z" i. X/ Q/ @( `
- hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;" _" e/ k& ]: ]( u* R$ E$ _' l* h
- hlpuart1.Init.OverSampling = UART_OVERSAMPLING_16;
9 j! G$ ?2 ~+ w! x - hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
& \- h5 k% m( c+ w9 n - hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
# ]2 N6 @; y) Q9 x - hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
) T) C; {4 k8 O M - HAL_UART_Init(&hlpuart1);
4 @( g$ M, t6 S6 F8 ]6 K* w0 \1 x& w - </font> <font face="微软雅黑" size="5">/ [' G1 L4 W4 n
- __HAL_UART_ENABLE_IT(&hlpuart1 , UART_IT_IDLE);
/ C4 }+ O' T. I - HAL_NVIC_SetPriority(LPUART1_IRQn,1,1);
2 l. x/ T6 e; }& I( @: D/ C3 ] - HAL_NVIC_EnableIRQ(LPUART1_IRQn);% i: Z. h4 R, o4 P8 A% }
- </font> <font face="微软雅黑" size="5">
0 V9 G9 p" Y. P6 `9 d - NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
z7 Z: Q7 n( {4 e0 C2 i# k9 z - NodeConfig.Init.Request = GPDMA1_REQUEST_LPUART1_RX;/ m; V% m1 y( A+ X/ S4 C
- NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;6 w9 s) |5 K' W5 d9 k
- NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;( g- p7 `" h* B
- NodeConfig.Init.SrcInc = DMA_SINC_FIXED;) X$ x# F7 V+ K! v
- NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
! d8 h$ \3 ?5 E) b* B& ? - NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;+ S# H* d3 `- K2 n9 h) ?
- NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;. X; d) a/ [0 Y1 h! c$ _% A
- NodeConfig.Init.SrcBurstLength = 1;
, N- y- ~5 W# }& Q; p7 ^ - NodeConfig.Init.DestBurstLength = 1;
% u7 |2 }* b8 b; V6 M8 }/ M/ M - NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;) Q6 [0 V- V+ Q9 M1 i4 }) j: y5 v
- NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
5 o6 E& h6 g0 ]6 e - NodeConfig.Init.Mode = DMA_NORMAL;
+ C5 \. l) \$ N& y4 J j - NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
6 }9 E @6 o+ k2 H5 ^7 p4 P - NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
. \/ d6 f5 I+ Z' `+ H) U - NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;- D- O9 s! n; \
- HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0);% d* }: T) {" O! I
) F$ l# l+ C% Q g" L6 }) {- HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0);
3 w9 t4 A' t& ?' u6 ~ z. y0 X - : o0 e+ `+ \' V( a' t( ~9 d
- HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0);6 X. h6 E6 y% b! z. ?
- , R. s' N+ l# _) N u }+ r: A$ A" v
- handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
! p4 T. H7 `* Z& Y: a, o - handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;0 R( p: d9 z- m# R
- handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;5 g/ L1 P$ N% }1 ~7 o
- handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;6 J( N$ W6 Z6 }9 I
- handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;+ I: A8 D# E4 n. F
- handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;- g1 h4 N! k c4 g2 H* ]; G
- HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0);5 [2 Q- F! ] }2 v
9 A9 k+ b7 U2 r% k! h: K1 I- HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0);: G/ \3 w I; z0 G3 T
- 2 A/ N8 m' U9 p/ W3 i- A5 O) B
- __HAL_LINKDMA(&hlpuart1, hdmarx, handle_GPDMA1_Channel0);
2 ]: p! X6 C% I( q
4 ?+ \6 t) g J, t- HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV);
% E( B" d( S# z( b( X - </font> <font face="微软雅黑" size="5">0 h* r: {; P+ i7 D, G
- HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);/ y Y! b9 B; _( I9 M7 V: G
- HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);* Q& P6 J0 H8 I8 L# N
- }
' [' }6 S' a8 L$ d% ]: q
Z1 I ~4 c% V/ z! ~& N, m2 j& w- void LPUART1_Send_Char(uint8_t ch)
0 M/ A% ?- M: b! O, L+ O V - {
, k% \/ u" f, z' \" B: U - while ((LPUART1->ISR & 0X40) == 0);# o4 F- {. \. F4 c/ c5 J' m j
- LPUART1->TDR = (uint8_t)ch;
2 ]& T/ O! v3 d. u3 K- m7 q - }
: Z% X* M4 E" e7 X$ y X7 b. u
+ M2 d; d5 @* D! n5 F3 v- void LPUART1_Send_String(uint8_t * s)' I. Z7 N! x1 u! O) F( D3 C
- {
0 v+ n: r/ m I7 ~4 G+ o - uint32_t i;
: [5 e+ x) G' c8 w - for(i = 0 ; s != '\0' ; i++)
) W* C6 J, |' E9 L& Y2 E - LPUART1_Send_Char(s);
% h, t6 w( J: E - }3 I# l' }+ M. b' a, @4 C i
8 S- h- z X" f1 c7 a- void GPDMA1_Channel0_IRQHandler(void)
2 Z: R( t9 k/ W3 d: j3 }( S4 E - {# X, b$ [0 R* j/ `+ M7 y* o3 B- x
- HAL_DMA_IRQHandler(&handle_GPDMA1_Channel0);
$ f7 @4 R# O( X. {6 {. L - }0 r0 D$ f4 u; h4 B0 L
- + ^0 y' v5 R) w) u- z
- uint8_t aRxBuffer[RXBUFFERSIZE];
1 e/ O0 F8 X! q+ `' \$ c6 I
B+ C& b5 y, l0 y6 f1 _4 P; o- void LPUART1_IRQHandler(void) 9 ^! E9 H8 J5 [. R3 |8 n
- {
2 M7 c8 ?0 c; h8 m% S5 K - // int temp;
( W4 Z" L) y% k* v0 m0 A: I - if(LPUART1->ISR & UART_FLAG_IDLE)
% q" {( t$ H5 T, {# s2 J - {
" z T+ m6 O' k+ _" P# m - __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);
* R4 h( ~7 l% `: |, o - printf("LPUART1_IRQHandler. %d %s\n" , GPDMA1_Channel0->CBR1 , aRxBuffer);
) p) A' B* I1 } - </font> <font face="微软雅黑" size="5">; \4 Q% h* o V/ j
- HAL_UART_DMAStop(&hlpuart1);9 R: c" V* L- t, d
- HAL_UART_Receive_DMA(&hlpuart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);9 A: N$ K/ f# d" l- |5 ~
- // rx1_len = BUFFERSIZE - DMA1_Channel5->CNDTR;0 q( b: \- y0 v* I3 C* W7 k% s
- // uart1_recv_end_flag = 1; b6 m: k" ?; M8 A8 {: f! Y
- }) @ g% I u8 n g% d' V z e
- }</font>
复制代码 在ST的新系列里面,有个特殊机制,使用任何形式的DMA通信必须要打开DMA中断,这个在F103系列是不需要的,是F4以及之后的大部分系列都需要,另外,在F4之后的系列中,对于外设要用的DMA,可以自由配置通道Channel(流Stream/节点Node)等,其实是一个东西,就是DMA通道的意思,不同系列的名称不同,只有F103和F4系列的特定外设是绑定在特定DMA通道的。像本帖子,就把LPUART1的RX功能设置在在GPDMA的通道0(后续还把SPI1的TX功能设置在GPDMA的通道1)。
6 w. r0 Z2 G, _2 l2 f' m+ v- @+ L, h6 U4 f
. h* C- a5 f) r0 D8 k# e" d- ~
: P3 z: t/ E- W! X& t
看看运行效果,使用两根typec线分别连接开发板的STLINKV3接口以及用一个USB转TTL模块接在PA2 PA3引脚上:% J( I Y* e- P0 F. ]
/ u+ z: Q7 y0 T- b+ z/ H/ s
首先上电之后UART1和LPUART1都会打印信息,然后,对LPUART1发送数据,UART1会打印接收到的数据以及接收长度(100-DTR寄存器值)。 |
你好,板载ST-LINK电脑可以识别不到吗?
没看懂你的表述是什么意思
就是把板载ST-LINK的C口接入电脑,电脑可以识别到ST-LINK吗?
[md]那肯定可以识别啊,不识别怎么下载代码发帖子😄
使用的是全功能的Type-c线吗?
没听说过typec线还分什么全功能不全功能的,我直接用手机充电线来接开发板的,一端是typeA的HOST,一端是typec,把线连接电脑和手机,能识别出手机的存储卡,那就肯定可以给开发板用