拿到了nucleo-U385开发板,在KEIL环境下编程,需要下载CubeU3支持包,在ST官网即可下载,并且在CubeU3支持包内还有KEIL环境所需要的pack安装包,这个应该是最近才做的一个方便开发者开发的一个机制:- C; s) h3 j. T5 R; Z$ K, |& X
5 P N$ L2 P' ]! g8 E9 V. t5 i我直接用点灯的例程来改串口例程,方便省事:
t* b" _- J2 N4 j$ J
0 D, v: [$ W1 ^0 B3 N
整理好的例程结构如下:8 w/ w& Y( K* W* w* B- s: p
2 `5 V# w. }% B3 O. E
根据原理图可以得知,开发板的STLINKV3 VCP连接的串口是UART1,即PA9 PA10,可以直接与电脑的串口助手进行通信,另外开发板上还有PA2 PA3引脚,这个引脚被复用为LPUART1:" p4 ]" ]* ~5 X9 u
, _, @ C! m4 v: ^8 q& u3 v: D我这个帖子就实现UART1和LPUART1的双通道串口通信,其中把LPUART1的接收功能打开,使用空闲中断和DMA进行接收,先看看UART1的初始化代码:- <font face="微软雅黑" size="5">UART_HandleTypeDef huart1;" D1 l! F8 M4 p- \1 `' r$ I
! V7 X3 |2 y4 _" d- int fputc(int ch , FILE *f)
' h/ l1 e" ^" v V% V8 P - {
3 F$ z# t% K h1 }, k - while ((USART1->ISR & 0X40) == 0);
) k% }; S' j2 Y" ^% v1 ~- O3 {) m - USART1->TDR = (uint8_t)ch;
% o+ V: u- y n+ X; P" m8 x% n - return ch;( P/ z- n& _" Z" K
- }' c1 v; y' T% [# U {
- 9 S B# U, v: y" M& k& ~
- void UART1_Init(uint32_t baud)
; f8 {* j4 y- ]0 Z7 F - {: ~' M2 \$ W4 } q( h; i& ~3 q
- GPIO_InitTypeDef GPIO_InitStruct = {0};. t) Y2 }! X2 b. |" i
- RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
$ e, l( }" f# y7 F9 h3 r$ h% m - 8 \/ y' K2 e8 e! A) M3 F% T! K
- __HAL_RCC_USART1_CLK_ENABLE();
5 |# l+ s2 D+ r, ^ - __HAL_RCC_GPIOA_CLK_ENABLE();
5 z# Q- y% W1 ]& H6 \ - 0 _# K# L0 c* U, E# C. d7 R
- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;6 y) w1 e: z' c1 j b) v" I
- PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
m5 n! C$ `4 I u, i2 }" m - HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);1 V! y* R- m4 m- x! H I5 V
- ) D+ e4 |! B$ B2 p2 H7 w |
- GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;. W7 E, F ?9 O0 f$ h
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
9 x( o/ s [# L ~9 Y& o1 _( _ - GPIO_InitStruct.Pull = GPIO_PULLUP;/ O+ m+ p4 R" E, X. W% h6 N$ F
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
: a9 ~7 z: j- L j9 J& ?6 V - GPIO_InitStruct.Alternate = GPIO_AF7_USART1;0 s2 z) |; M$ ^
- HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
6 \" o; t5 A- _ - </font> <font face="微软雅黑" size="5"># I% Z$ \: b( N$ g/ M
- huart1.Instance = USART1;1 a+ t5 A) q M* M" K Q6 v
- huart1.Init.BaudRate = baud;
' \/ _$ Z2 J* E6 `% B. E' O" j" v - huart1.Init.WordLength = UART_WORDLENGTH_8B;
7 H- G% m& c' W4 P: S - huart1.Init.StopBits = UART_STOPBITS_1;+ O0 f5 Q: c, L8 ~3 t
- huart1.Init.Parity = UART_PARITY_NONE;1 {, B. ?( o* u" a
- huart1.Init.Mode = UART_MODE_TX_RX;
( x% Y U3 W5 m! O) m- T7 @$ O: c - huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
" O# d, J6 a5 O4 ~& l5 G5 E - huart1.Init.OverSampling = UART_OVERSAMPLING_16;
) k4 o* P% \5 P1 F- m - huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
3 @( o. f5 S m, _2 H - huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
% ]! [9 c P- Q& u" h% K - huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;/ o7 ], n" j% X7 Z3 g- h# A) x
- HAL_UART_Init(&huart1);
2 O1 g' b/ O9 C2 [* o& g3 _ - }</font>
复制代码 非常简单,只要熟悉STM32编程的没有一点难度,然后是LPUART1:* o J T/ ?( j2 M
- <font face="微软雅黑" size="5">UART_HandleTypeDef hlpuart1;- V/ Z, R& C |7 [ m% G! e
: o- Q. p' ^) C D1 m, e- DMA_NodeTypeDef Node_GPDMA1_Channel0;
* \5 i' L" g" h - DMA_QListTypeDef List_GPDMA1_Channel0;
# K* Z4 O& b @3 a% s - DMA_HandleTypeDef handle_GPDMA1_Channel0;
* `6 b2 b- n: N
5 M* j4 {+ z. g8 P( L" V2 W l- void LPUART1_Init(uint32_t baud)
: ^9 }2 t% f; m( Y - {
" c2 x% a6 T$ P& S" B% I" G - GPIO_InitTypeDef GPIO_InitStruct = {0};
# i3 b# g4 E' s" r9 f - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};9 K6 w2 |( z3 e6 T0 E
- DMA_NodeConfTypeDef NodeConfig;, B7 [% G. t/ L) H/ L! O6 t; ]# I
- ! r2 F1 A- N. P5 Q
- __HAL_RCC_LPUART1_CLK_ENABLE();: p% c8 m7 }' `' {6 |4 x+ H* B( r
- __HAL_RCC_GPIOA_CLK_ENABLE();: x. T `3 b* e# V# K
- __HAL_RCC_GPDMA1_CLK_ENABLE();0 [$ e$ [: G2 D: \4 D
- ; \: y6 F5 j' t9 u. ~+ V! N2 d6 {
- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;
/ }9 Q; v2 {( p- w) ^6 a2 c# T; l$ E - PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK3;, H, m8 l$ U2 v
- HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
) k/ [+ G8 O3 _$ B0 Q! l* b: j
/ L( @! q/ H( u. K- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
! l! I! }' u. d6 ~4 W! K - GPIO_InitStruct.Pull = GPIO_PULLUP;1 _' L" k* W. m( k
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;2 Y+ P2 r! B; x
- </font> <font face="微软雅黑" size="5"># {; T) V8 @) Y' C
- GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;
4 u/ N; e- L/ O- v! {5 R - GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
5 T6 Q9 a0 Q* b - HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
0 K- p0 ~- b2 b9 v - </font> <font face="微软雅黑" size="5">
7 H7 A, R0 f1 @* k - hlpuart1.Instance = LPUART1;2 X/ a @+ a4 s: k! S5 W
- hlpuart1.Init.BaudRate = baud;
& z8 ]* t6 Z& s+ Z3 \# g% v - hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
; |" N7 v) q- k0 e - hlpuart1.Init.StopBits = UART_STOPBITS_1;0 m- q/ O) j' r( \; G
- hlpuart1.Init.Parity = UART_PARITY_NONE;+ h* ?- ?+ D& ^9 V5 @7 G
- hlpuart1.Init.Mode = UART_MODE_TX_RX;+ `/ ^3 ]: y9 a( w+ @5 O) p0 S
- hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;# `( t' P& t! V2 r3 Q. \/ V& `
- hlpuart1.Init.OverSampling = UART_OVERSAMPLING_16;$ y, c) ~, T8 z
- hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;) P8 Z ^% s8 ]8 d
- hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
: u |5 M6 I& {8 M3 e% X - hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; N% ^; m8 p; ^% e k/ B1 Q
- HAL_UART_Init(&hlpuart1);
6 J( q7 ?6 N6 Y, T! T2 ` - </font> <font face="微软雅黑" size="5">8 @% t, w2 ]8 [9 ]: W
- __HAL_UART_ENABLE_IT(&hlpuart1 , UART_IT_IDLE);
' t; W, j# I/ t0 l: k6 \7 j* Z. J - HAL_NVIC_SetPriority(LPUART1_IRQn,1,1);
' |$ l) K- |# ?+ `& ` - HAL_NVIC_EnableIRQ(LPUART1_IRQn);* E* V; _( F1 ?. F+ z
- </font> <font face="微软雅黑" size="5">4 y; o) A! x3 ]# d6 \
- NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
3 G) R+ l7 }6 A7 b9 e - NodeConfig.Init.Request = GPDMA1_REQUEST_LPUART1_RX;
, f1 W5 Q9 U! O" B - NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
; [* L& ^3 S' @ X0 ` I5 m2 s6 h - NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
0 A0 f, n! j' T - NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
+ y* R2 }/ P, M - NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;! C+ h8 i9 {" h! s8 l
- NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;! p- y0 M( t y+ @
- NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;) x3 k. H" y1 d, o8 h
- NodeConfig.Init.SrcBurstLength = 1;% R: D7 @) n# B% W9 T \! \4 R
- NodeConfig.Init.DestBurstLength = 1;
3 _( J4 G% G9 z - NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;& J7 h& d9 W* i' }1 f
- NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
f9 L6 ] h1 E) K- m1 Y* B - NodeConfig.Init.Mode = DMA_NORMAL;
( I4 f* v% i; f! k3 R6 i: [5 Z# e - NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;! t1 ~( T* B* D1 g* E
- NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;7 G3 O! |9 [ Y0 l) E% i9 O7 t* u9 `
- NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
+ w y P3 }0 _: @" z: G - HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0);
2 ^, \% o# I* E9 q
2 `- g0 b9 b' L- HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0);
1 Q# M6 j6 D8 D) B% @* \
# c" ]. o: Y7 g+ Q* ~% ^- HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0);4 J* U/ I0 E& S; h: m
- - s0 a2 I. ]2 w5 ^5 O
- handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
2 Z) r- X5 k$ V - handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;0 G3 p6 v6 p1 R- f( W7 C
- handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;) ?+ A/ ^* T9 L0 f0 c6 h
- handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
7 k/ @4 }! L3 S9 g) V' M - handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;; ?: G5 t: d* a
- handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
9 C1 E: R- Q1 q; j8 ^" r6 r, s$ e - HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0);
; Y1 X1 v3 D! b - . V. l3 ~ \7 o
- HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0);
0 [$ |8 |/ x$ D5 j
+ }' g( g1 T2 @- N6 f* {* ^- __HAL_LINKDMA(&hlpuart1, hdmarx, handle_GPDMA1_Channel0);" I6 ]: g6 i8 b
- % y4 S' X2 C" x* @3 Z8 M
- HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV);, D7 _2 h6 i* T3 ~2 |
- </font> <font face="微软雅黑" size="5">
' _8 w+ W" n1 n1 R4 D* I1 X- F* e - HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);7 Z+ D$ j, F9 @" b' S, l6 L
- HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);
8 q9 j4 e0 n" e- d, T - }& B9 m& F$ }' Q8 w5 s r
- - n5 p+ ~9 y# @3 |9 @
- void LPUART1_Send_Char(uint8_t ch)
% ^ T9 t4 k6 L. F1 u5 | - {+ w+ w3 ]' ?4 ^
- while ((LPUART1->ISR & 0X40) == 0);
# d2 K, S0 J& \, [ - LPUART1->TDR = (uint8_t)ch;
1 e0 l/ w" D! {4 b, X - }2 _/ Y0 f9 c1 i8 ^6 L
- 9 d* S( a% P2 Z8 e- g/ \
- void LPUART1_Send_String(uint8_t * s)
5 h7 z% v, Z% A2 ?& @5 j - {
' O+ x! ?/ Q3 m& @% e - uint32_t i;/ ], x, @$ ?' @3 j1 F# Q
- for(i = 0 ; s != '\0' ; i++)
( M7 x5 T1 a$ G - LPUART1_Send_Char(s);
# ]4 b8 A9 g/ y( e7 V - }, @) V, j3 O3 Y& M! Y H
- 7 U _0 T1 q) D% A- d
- void GPDMA1_Channel0_IRQHandler(void)
0 p* {$ R5 l. e4 Q, d - {
8 W# p% l. a- l! w3 |$ v8 q! X - HAL_DMA_IRQHandler(&handle_GPDMA1_Channel0);
, L+ ^* j+ O; A4 @1 z. f - }
8 M. Y1 u: n9 E
# P6 \ [7 d0 C! Y, _& G# r4 ]! b* s- uint8_t aRxBuffer[RXBUFFERSIZE];
5 _; l: Y, B. u* P O+ `
2 i( f6 F( E a4 l; d1 r( J+ y; Y- void LPUART1_IRQHandler(void)
3 O) b# P! s8 |6 g/ ?- i: P# N - {: B. g% R" k% P" ~$ z E
- // int temp;$ _' D4 f- L+ j! C% E4 A, Q
- if(LPUART1->ISR & UART_FLAG_IDLE)$ o- e. W% i3 W1 @1 B
- {1 R7 |. A* _* e0 ?$ h
- __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);9 P2 L2 ]# ~! J( G2 j3 W
- printf("LPUART1_IRQHandler. %d %s\n" , GPDMA1_Channel0->CBR1 , aRxBuffer);% o! r' d; p4 m: W/ c: o+ m4 M3 E
- </font> <font face="微软雅黑" size="5">
2 J, b/ D& f/ X; o - HAL_UART_DMAStop(&hlpuart1);
! H: O: a# X0 l. Y6 Y1 l* ^ - HAL_UART_Receive_DMA(&hlpuart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);
/ U S3 T0 U9 F2 ~5 Z - // rx1_len = BUFFERSIZE - DMA1_Channel5->CNDTR;0 c& b' J" Q* a! h; f4 k
- // uart1_recv_end_flag = 1;
5 H0 U) h# @. t! v) Y: z# r! X" M - }
: |4 k/ w! _, `6 q7 q6 x3 x - }</font>
复制代码 在ST的新系列里面,有个特殊机制,使用任何形式的DMA通信必须要打开DMA中断,这个在F103系列是不需要的,是F4以及之后的大部分系列都需要,另外,在F4之后的系列中,对于外设要用的DMA,可以自由配置通道Channel(流Stream/节点Node)等,其实是一个东西,就是DMA通道的意思,不同系列的名称不同,只有F103和F4系列的特定外设是绑定在特定DMA通道的。像本帖子,就把LPUART1的RX功能设置在在GPDMA的通道0(后续还把SPI1的TX功能设置在GPDMA的通道1)。1 H8 l9 X8 o* w4 |
- ~7 h1 N/ H6 U
5 X3 K7 ]% K* p* i }& G% P
3 V( a2 U% ~$ T' M看看运行效果,使用两根typec线分别连接开发板的STLINKV3接口以及用一个USB转TTL模块接在PA2 PA3引脚上:& b+ @( h+ F k8 V
& |/ G6 x' V& l+ H
首先上电之后UART1和LPUART1都会打印信息,然后,对LPUART1发送数据,UART1会打印接收到的数据以及接收长度(100-DTR寄存器值)。 |
你好,板载ST-LINK电脑可以识别不到吗?
没看懂你的表述是什么意思
就是把板载ST-LINK的C口接入电脑,电脑可以识别到ST-LINK吗?
[md]那肯定可以识别啊,不识别怎么下载代码发帖子😄
使用的是全功能的Type-c线吗?
没听说过typec线还分什么全功能不全功能的,我直接用手机充电线来接开发板的,一端是typeA的HOST,一端是typec,把线连接电脑和手机,能识别出手机的存储卡,那就肯定可以给开发板用