拿到了nucleo-U385开发板,在KEIL环境下编程,需要下载CubeU3支持包,在ST官网即可下载,并且在CubeU3支持包内还有KEIL环境所需要的pack安装包,这个应该是最近才做的一个方便开发者开发的一个机制:
4 R1 R1 Z, y& M
A) ?$ \3 X) R我直接用点灯的例程来改串口例程,方便省事:1 C z2 L% Y0 ^5 O* Y+ V: e
9 h; U: i' a) l) h5 d8 C4 \% `" f整理好的例程结构如下:
, N, c. Y! ]: N/ b# }" X5 U, j8 ~5 W
9 X9 n7 \" z5 K$ o6 `
根据原理图可以得知,开发板的STLINKV3 VCP连接的串口是UART1,即PA9 PA10,可以直接与电脑的串口助手进行通信,另外开发板上还有PA2 PA3引脚,这个引脚被复用为LPUART1:5 \" k. Z' J2 O
* _+ H# N" l6 e我这个帖子就实现UART1和LPUART1的双通道串口通信,其中把LPUART1的接收功能打开,使用空闲中断和DMA进行接收,先看看UART1的初始化代码:- <font face="微软雅黑" size="5">UART_HandleTypeDef huart1;& C- y# Q/ x/ L& d0 k4 l0 ?
+ C* v2 d9 C7 ?- j( v. P, y% d* }- int fputc(int ch , FILE *f)
5 Z: w# V$ P: k# h( o - {
. y0 J0 O1 a( p( q$ c& l! Y - while ((USART1->ISR & 0X40) == 0);: I) {& c* }. \# v- _# F' Z$ P2 ^
- USART1->TDR = (uint8_t)ch;
V, \# b% M- D7 z* k - return ch;
" l/ r3 _8 \3 K( T/ i2 c* P9 `1 L - }
9 e+ ~, @# \0 e2 w4 \" r8 d5 O - ; I0 P l/ W/ _, H8 n0 u
- void UART1_Init(uint32_t baud)
4 T% g7 t; p6 G4 A5 Y$ t - {
; Y9 H7 e4 i( l - GPIO_InitTypeDef GPIO_InitStruct = {0};
$ q4 v+ g2 u/ I: L - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
) e; s3 h& ^; m/ r- `2 v3 X( { - 8 C' |" u+ B' I& U$ d
- __HAL_RCC_USART1_CLK_ENABLE();2 X5 i# M T2 s1 _9 ~ w
- __HAL_RCC_GPIOA_CLK_ENABLE();
3 G& i9 M* |; n - ( o. Z4 T7 j1 I2 A) y7 I! _
- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;0 S0 A k% X* a! Z; D5 Z5 ?
- PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
$ }" c1 b; U& C2 Z* \7 g - HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);* x# n% H/ B) g3 L' a
. m3 @" U& m4 _- L- GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;; r: [3 x$ l7 [, B R, b \9 F
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;# {* z6 M, P# j; G( `! ^4 Z V
- GPIO_InitStruct.Pull = GPIO_PULLUP;) T1 b) V1 l. r. G
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
/ s9 s6 }4 Q9 p; P8 v M3 O - GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
9 u- i' d8 q7 I f. \ - HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);& H+ G+ I6 d# C, z; S
- </font> <font face="微软雅黑" size="5"># t; O- z9 Y+ E8 p
- huart1.Instance = USART1;
9 G+ C5 c! O5 W) C1 s - huart1.Init.BaudRate = baud;
: W" G s5 J, D - huart1.Init.WordLength = UART_WORDLENGTH_8B;8 t6 l w2 \5 d% b6 c3 y7 i+ P; h
- huart1.Init.StopBits = UART_STOPBITS_1;1 Z- I2 q6 `; u+ Q+ D
- huart1.Init.Parity = UART_PARITY_NONE;
, O* d. U+ K4 B6 y5 M6 F - huart1.Init.Mode = UART_MODE_TX_RX;3 _* L# v/ g d! j3 S' ^: z
- huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;* u7 v2 B7 U7 L) D6 S/ }0 G ]
- huart1.Init.OverSampling = UART_OVERSAMPLING_16;
/ w4 j2 p( c7 S5 Z* x8 ^4 `9 } - huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;; C* Q) r P( C' D& ?5 I) q" H
- huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
2 ]+ z: w4 @& n - huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
" V9 O" o, F3 q! I5 X& \; @* e! L, J5 G - HAL_UART_Init(&huart1);( a/ L4 o; a8 Z* k
- }</font>
复制代码 非常简单,只要熟悉STM32编程的没有一点难度,然后是LPUART1:
( K$ h, a# z' r5 W7 M- <font face="微软雅黑" size="5">UART_HandleTypeDef hlpuart1;
1 Y' s8 A. b% O& V* S2 p5 m
1 W' s: ~& o; w: O5 R) r3 d- DMA_NodeTypeDef Node_GPDMA1_Channel0;' m1 z( ~+ U2 g! }8 V6 p
- DMA_QListTypeDef List_GPDMA1_Channel0; o5 I6 c* ]: _, s3 h& r0 Z3 @
- DMA_HandleTypeDef handle_GPDMA1_Channel0;
% T8 P3 k) x9 H" }1 } - - L! o5 W1 ]! q1 r; R/ }& G& |
- void LPUART1_Init(uint32_t baud)
# P" P4 Y5 k' K& y5 |% { - {# Q5 | O* o0 n3 g
- GPIO_InitTypeDef GPIO_InitStruct = {0};
! U/ g- A9 f6 B v" T1 F* @3 J - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
* u- k) Q# p8 M9 ^9 F5 X' ~ - DMA_NodeConfTypeDef NodeConfig;
: Z9 V6 }3 h9 u! M: T! D3 M' W
" d+ j& l( u- x& T5 b9 i- __HAL_RCC_LPUART1_CLK_ENABLE();
0 b0 }9 x6 P6 b$ T& Y; ] I - __HAL_RCC_GPIOA_CLK_ENABLE();
+ c# C a K# o- t1 v* E: X- x - __HAL_RCC_GPDMA1_CLK_ENABLE();
$ U$ [* ? [# {6 U, p0 v
3 a" t q( A$ y( I" ^- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;& b! u0 z/ G, ~% n- `" x
- PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK3;
& {& v+ s2 z. }9 P' Z- Q - HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);! `, F1 {: w j! v
- # N1 _& @) R0 v, h( G& M7 I
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
% a( } H1 C6 m5 C4 B; Q - GPIO_InitStruct.Pull = GPIO_PULLUP;
- T8 z, g6 S" d. T& {9 Y; n& w1 i( ` - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;2 Z1 A5 e3 @7 [% e t
- </font> <font face="微软雅黑" size="5">9 t1 s) `% b2 f4 w
- GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;5 O# K) t- S6 x. E: [
- GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
, g0 H2 H! C% d( {5 @( I# H - HAL_GPIO_Init(GPIOA , &GPIO_InitStruct);
+ U! n4 U- o8 \; R# Z" Q - </font> <font face="微软雅黑" size="5">7 j6 } \- Q8 g$ D
- hlpuart1.Instance = LPUART1;; q; d: e+ `$ y- g3 F: L
- hlpuart1.Init.BaudRate = baud;! b1 g: b) X c
- hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;2 Q2 U }: `' H, a! `+ ^7 F
- hlpuart1.Init.StopBits = UART_STOPBITS_1;
- B% Y3 g+ h' b7 a) G) E - hlpuart1.Init.Parity = UART_PARITY_NONE;
9 x' l; k, w) k - hlpuart1.Init.Mode = UART_MODE_TX_RX;( k1 @( H6 H. j3 n3 u
- hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;& |/ N; e9 n E
- hlpuart1.Init.OverSampling = UART_OVERSAMPLING_16;' K9 F) C6 n5 t7 e- m: t
- hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;, A% z6 T+ b! N, N" `0 o- z
- hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1; L6 O& g p& o' w: ]" Y) m- `
- hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;# Q! q. J7 ^* y# A* c
- HAL_UART_Init(&hlpuart1);
' U& r8 Z) l8 \, S+ j9 X( {$ C - </font> <font face="微软雅黑" size="5">
3 u. m% z& U4 G& q4 |7 T3 ] - __HAL_UART_ENABLE_IT(&hlpuart1 , UART_IT_IDLE);
* c( n; Z& M/ x0 z/ U - HAL_NVIC_SetPriority(LPUART1_IRQn,1,1);
$ O+ v) {( q3 d - HAL_NVIC_EnableIRQ(LPUART1_IRQn);, C* O& A8 w* ]7 {( T. V2 f
- </font> <font face="微软雅黑" size="5">: `5 R! Q9 E' o7 C9 V ]5 V' j0 t
- NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;1 c. ~9 A, W# [: Q9 ]
- NodeConfig.Init.Request = GPDMA1_REQUEST_LPUART1_RX;* S: X2 J2 M7 @. A9 ]( S
- NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
( i# L1 o; T* p* G - NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
1 l5 @6 e0 H% `! w2 @ - NodeConfig.Init.SrcInc = DMA_SINC_FIXED;% L- {! U6 B. A& X: K
- NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
! _3 a' l7 t# B# A6 z - NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
/ G* U v; _& `" S# P" R - NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;6 N, s" a& E. F! K+ ?- f: {$ D
- NodeConfig.Init.SrcBurstLength = 1;* r/ u$ Y; i! N1 Z M
- NodeConfig.Init.DestBurstLength = 1;
; U k3 o: M4 a3 Z5 V2 Z - NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;' X& e( `% o& r
- NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
. ^* h0 Z N; x - NodeConfig.Init.Mode = DMA_NORMAL;
3 {+ G& q& W- t2 N; |7 W - NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;2 P; |: S3 s$ k' d; \4 V
- NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
1 o2 P$ Y4 d" ?9 F' @+ E$ N - NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
, f, H8 f0 f" [4 Q - HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0);
, ]7 Y! J/ }5 X) Q1 I Y8 @ - 5 s! A, ^" b5 y/ O) y; U& Q* [
- HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0);# a: U3 [! q5 P( \7 F4 ^1 p
- $ S% U2 `- a, L
- HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0);
1 Z% \" p3 Q. u" T$ I2 Y) Y
% F3 N1 o5 _& |9 O5 Y- handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;# p4 p7 p2 U" a" t9 u4 @1 E9 j& ?9 R
- handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;6 j8 L8 `- ^1 D; j% E1 }, R
- handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
- L1 b! |6 r: J/ u, C - handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;* C. p, Z1 e* ~' {" g
- handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;* N% S' j8 F8 a' h+ l! r
- handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
8 _$ v+ G \4 {5 ^ - HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0);
2 q6 I. B% k, j( E- _4 a* A3 r
( Z/ G1 y P I6 s$ m# o- HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0);: y; _+ B$ b/ v. {" ~3 r' a* g
6 u( y! v2 C- [" b" c$ [, ?- __HAL_LINKDMA(&hlpuart1, hdmarx, handle_GPDMA1_Channel0);4 |0 @" g& p# x0 E( M2 G
- 5 D/ T" o5 r) s( z( a& t, m' ?8 w( v
- HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV);
. U" P$ |) z, B% ^. n - </font> <font face="微软雅黑" size="5">! E& o$ w* X& p; d
- HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);8 H" M. X( U- u) c3 w# {
- HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);; N0 A; L {# Z
- }
- G: v# `/ |1 h2 c$ d1 i - ' U. Q& H0 G1 {" t0 B
- void LPUART1_Send_Char(uint8_t ch)
! g( `" N s, W, O, a" i0 _9 O2 D/ r+ d& T - {
) |, j& L) ~* h7 @' x# q - while ((LPUART1->ISR & 0X40) == 0);0 S( V3 g% U! m* z
- LPUART1->TDR = (uint8_t)ch;
. Q* B2 c! L6 F( ~1 @! G& a - }
' {4 _8 y9 b/ J" A3 ] - 2 C- e, p. X+ W7 c6 l# n5 n
- void LPUART1_Send_String(uint8_t * s)
( ^) v& X! A4 `, k - {: L. R- ~7 Z9 R8 G+ K
- uint32_t i;
5 G0 E! ?( ]: ^8 A - for(i = 0 ; s != '\0' ; i++)3 b0 C# V; {$ Z* U( b. W! i" l
- LPUART1_Send_Char(s);6 D7 c/ M9 z) p6 A: @ J
- }
# u. z0 @4 F, Q6 \6 F9 j - & _$ H% |! U1 c5 E0 Z& R! z
- void GPDMA1_Channel0_IRQHandler(void)
) @" O+ z/ t; ~# t' n0 V8 _0 I5 o - {7 N$ H) r; b- V Q0 g+ |
- HAL_DMA_IRQHandler(&handle_GPDMA1_Channel0);4 u$ [# s1 B1 O; c# {3 A2 l
- }
) v% Y2 f$ g+ R7 x7 u: m( L- D/ `
b* u( g% l, `4 R/ X- uint8_t aRxBuffer[RXBUFFERSIZE];- g& C% e7 E1 j, z
0 f% s# Z( \5 O/ f; k- void LPUART1_IRQHandler(void)
8 u% Y# ^& y+ U" J$ }7 {1 P - {
2 Z' w0 q5 t1 K1 U5 s1 H/ B - // int temp;# E* t% Q+ T( X! V' H2 p* @
- if(LPUART1->ISR & UART_FLAG_IDLE)
& ?6 M' F0 Z0 l - {
" l* e) v* m* `8 a - __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);3 }6 @$ t# D- J& t' L
- printf("LPUART1_IRQHandler. %d %s\n" , GPDMA1_Channel0->CBR1 , aRxBuffer);
# `# s/ ?1 @& I9 b, L" ? - </font> <font face="微软雅黑" size="5">% W3 P8 R" @& ?) D" P) ?' A1 S
- HAL_UART_DMAStop(&hlpuart1);5 j O G2 \9 N* D- J! G
- HAL_UART_Receive_DMA(&hlpuart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);+ `; t0 m. V* U0 ]( P9 V# S8 V/ O
- // rx1_len = BUFFERSIZE - DMA1_Channel5->CNDTR;
4 P; z7 r5 X% N- p! h# u( ^ - // uart1_recv_end_flag = 1;
/ ~* p: N. r0 o - }8 x, d& V0 H& Q5 T6 ?
- }</font>
复制代码 在ST的新系列里面,有个特殊机制,使用任何形式的DMA通信必须要打开DMA中断,这个在F103系列是不需要的,是F4以及之后的大部分系列都需要,另外,在F4之后的系列中,对于外设要用的DMA,可以自由配置通道Channel(流Stream/节点Node)等,其实是一个东西,就是DMA通道的意思,不同系列的名称不同,只有F103和F4系列的特定外设是绑定在特定DMA通道的。像本帖子,就把LPUART1的RX功能设置在在GPDMA的通道0(后续还把SPI1的TX功能设置在GPDMA的通道1)。
5 T3 e; \( i- j0 P; D5 U
( k- R, o/ ^- u; g2 Y" f4 d; N' C
# h# A+ y% H0 w
1 B2 J9 y/ S! a* n! o
看看运行效果,使用两根typec线分别连接开发板的STLINKV3接口以及用一个USB转TTL模块接在PA2 PA3引脚上:
2 F, R8 G/ j8 {0 D6 \
% D+ Y+ @, _8 d# X0 X
首先上电之后UART1和LPUART1都会打印信息,然后,对LPUART1发送数据,UART1会打印接收到的数据以及接收长度(100-DTR寄存器值)。 |
你好,板载ST-LINK电脑可以识别不到吗?