一、串口初始化过程
' R7 {0 b7 k+ O4 o& D& z1、时钟使能;
% `0 x" T* V, ]4 s) P% ]# f9 M8 O8 `4 i2 R# v
2、GPIO初始化;# x4 W' g7 D0 W
. C$ E( u. j# L4 |' c, @( K3、串口波特率设置;
: B/ V% Q' l( B" Q! n- |. Y- ` } d" ?( d' Q2 y
4、串口控制;6 t1 ^* \" z4 l. u
7 ~( N8 M6 c( Z
5、数据发送与接收: j5 }. w7 U; i# g2 @
$ p V) \/ A* a* m) T8 @2 L. d# l
# P4 ^. S6 T9 O$ B$ E7 i
二、几个重要的串口函数
( o+ n3 z+ e: R( K N" \2 v- HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart); // 串口初始化
! h/ l6 D; x- r# B& F! t - " i6 d, [2 R; e- x% J7 c
- HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); // 串口发送
1 G1 R" j1 E( o# e) k' } - : o: m2 {2 g, c2 h# V# {
- HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); // 串口接收
3 p& T$ R2 }& t8 A( y7 ~* L* @
- ]/ N. X$ E( f6 s: C; C; h9 y- __HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__) // 串口中断使能
6 L$ j; S7 n$ j2 M% a/ ~ - 1 I1 u+ |: ^% h$ K1 B9 R8 X/ p7 Y- O
- void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority); // 设置中断优先级( o* Z; m" P2 X/ C& K% E3 y9 ~! M0 h
H, U P- x% ^- void HAL_NVIC_EnableIRQ(IRQn_Type IRQn); // 使能中断
复制代码
: M0 c' d- w* e: H1 M- o1 O三、几个重要的结构9 V$ |% U8 Q9 ?; P, b
- // 串口初始化结构体 包含了串口句柄 波特率配置 发送接收缓存 dma等! l! C# u* k8 ^' ~1 g
- // 我们只描述前两个基本功能,对效率要求极高可以使用DMA。, C, J3 y! ]4 Z/ ^+ @4 Q1 h
- typedef struct9 o' k8 D4 i4 K; f# w7 M
- {2 O; g, n2 q# s b, O/ O5 X- ?
- USART_TypeDef *Instance; /*!< UART registers base address */
2 _$ \; c& u' k/ L - , v5 X8 U2 t" `3 N2 i7 g
- UART_InitTypeDef Init; /*!< UART communication parameters */
+ ^& K- S& j$ g5 C7 h6 Y - 7 W D( E# I( u% q
- UART_AdvFeatureInitTypeDef AdvancedInit; /*!< UART Advanced Features initialization parameters */
e: p0 n! {; n1 q8 u& ~
! Q; G- T* W- u5 a- uint8_t *pTxBuffPtr; /*!< Pointer to UART Tx transfer Buffer */8 E% k9 B! r& A5 [" y' V) l8 x3 N ?
- . s. l. g! i4 U1 M8 }( I0 G+ v1 @
- uint16_t TxXferSize; /*!< UART Tx Transfer size */
& ]4 e# Q( d: W& d' y1 n, u - & t) y3 D( G# A5 C# J3 z
- uint16_t TxXferCount; /*!< UART Tx Transfer Counter */
! {" V$ l" l2 `, K - 0 b! ~3 e1 }8 f5 ^5 q4 @( v
- uint8_t *pRxBuffPtr; /*!< Pointer to UART Rx transfer Buffer */4 }% s; l, e9 v6 s) k
. P0 n/ s/ F7 W' T5 i- uint16_t RxXferSize; /*!< UART Rx Transfer size */4 m2 |/ r( Q4 r0 z+ a; s
- " V9 }: g) a; S0 v
- uint16_t RxXferCount; /*!< UART Rx Transfer Counter */5 }% a) h) ^/ p; w8 d* Q
, D# q8 k2 O+ c U6 h' Y$ z ^- uint16_t Mask; /*!< UART Rx RDR register mask */1 `7 y/ y! A2 k2 y8 o+ t5 f4 A; o+ `
- + h) B3 v) l& q
- DMA_HandleTypeDef *hdmatx; /*!< UART Tx DMA Handle parameters */
+ C! T3 J0 Q. \9 j; L$ ]
4 S, v9 M9 s I+ P( s6 B- DMA_HandleTypeDef *hdmarx; /*!< UART Rx DMA Handle parameters */+ j. H R! [4 t. U$ W. }
- 8 z& \) Z" W ^6 m5 ~
- HAL_LockTypeDef Lock; /*!< Locking object */
+ {8 R; d/ i- Y ^7 Z9 u
, ]4 J# f7 z. m- __IO HAL_UART_StateTypeDef gState; /*!< UART state information related to global Handle management
; R" @' W# ]' ^0 }( h - and also related to Tx operations." v, o. j8 n% U
- This parameter can be a value of @ref HAL_UART_StateTypeDef */2 J* F5 B6 s5 {: ?8 ^
- ) f* E% ~" v7 d3 J4 j0 U
- __IO HAL_UART_StateTypeDef RxState; /*!< UART state information related to Rx operations.
" [1 F) t& E8 [. r! E% L" H - This parameter can be a value of @ref HAL_UART_StateTypeDef */+ f1 z2 R" U. g" t( Q
l& s) o+ @+ F( o! P1 f( t v$ x+ n- __IO uint32_t ErrorCode; /*!< UART Error code */
+ j/ r) e ?2 w \ - " r% x9 q. s" V1 x% e
- }UART_HandleTypeDef;
复制代码- // 串口的操作句柄 如 USART1 USART2 USART3等
9 Z8 W" f7 u" a! y0 A9 w: l) O - typedef struct( s* U& u6 z+ X9 }
- {" `5 n* S. d' N& @/ D
- __IO uint32_t CR1; /*!< USART Control register 1, Address offset: 0x00 */ L& l3 P3 W6 Q4 H1 d+ u, f' D7 y
- __IO uint32_t CR2; /*!< USART Control register 2, Address offset: 0x04 */ " t3 ^) I- U. c1 v, \
- __IO uint32_t CR3; /*!< USART Control register 3, Address offset: 0x08 */0 h: S1 G2 |5 T! f( ]
- __IO uint32_t BRR; /*!< USART Baud rate register, Address offset: 0x0C */
' R6 c, v* `4 P& i$ ` @. k% j - __IO uint32_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x10 */
% H! G- R W+ x1 g7 p - __IO uint32_t RTOR; /*!< USART Receiver Time Out register, Address offset: 0x14 */
/ a, Q# h. }( z# g1 o) @ - __IO uint32_t RQR; /*!< USART Request register, Address offset: 0x18 */' c) h3 f' t8 {( W; n3 P
- __IO uint32_t ISR; /*!< USART Interrupt and status register, Address offset: 0x1C */! p( Q6 E- F3 j
- __IO uint32_t ICR; /*!< USART Interrupt flag Clear register, Address offset: 0x20 */1 {2 d- V; }8 ` ~9 L0 ?! `
- __IO uint32_t RDR; /*!< USART Receive Data register, Address offset: 0x24 */# m( K. L! s( O: [: F. f
- __IO uint32_t TDR; /*!< USART Transmit Data register, Address offset: 0x28 */1 L/ a0 e7 K+ q& `7 p: o. j
- } USART_TypeDef;
复制代码- // 设置串口的各个参数 波特率 字长 停止位 奇偶校验 收发模式 硬件流 过采样; P! \: x2 l3 y+ W; J+ |/ Z
- // 字长:8位/9位/ ]1 J q! b8 L) b6 M
- // 停止位:1位/2位7 V3 G; [& W a" _( {- }
- typedef struct. E* V+ k* X. K- _
- {# l5 s" y7 `* i8 D% J" D
- uint32_t BaudRate; /*!< This member configures the UART communication baud rate.
. x& E, S$ U8 v& ]1 p* b/ F - The baud rate register is computed using the following formula:7 r- t. P5 j& b6 b
- - If oversampling is 16 or in LIN mode,
5 g8 B1 F( z$ J& Y( A: i* T' w+ l. |, l - Baud Rate Register = ((PCLKx) / ((huart->Init.BaudRate)))3 u2 P6 C9 Y9 Y0 _
- - If oversampling is 8,
+ C0 s4 {( w$ U' O- }( S - Baud Rate Register[15:4] = ((2 * PCLKx) / ((huart->Init.BaudRate)))[15:4]" F1 G; Z* s. n# U& V
- Baud Rate Register[3] = 0
4 y+ n4 \* s- m* Q. m - Baud Rate Register[2:0] = (((2 * PCLKx) / ((huart->Init.BaudRate)))[3:0]) >> 1 */: A0 Q, f: b; P: }! Q
M: A2 C- L, ]; G* W* H- uint32_t WordLength; /*!< Specifies the number of data bits transmitted or received in a frame.
& P$ M; H; X, d! k - This parameter can be a value of @ref UARTEx_Word_Length */9 V/ _: t6 q* p! D' O$ l
% Q2 V- }4 {# x1 X9 B4 e7 H( t$ N- uint32_t StopBits; /*!< Specifies the number of stop bits transmitted.
5 q: Y5 o; o) S+ N5 u) a9 g% y - This parameter can be a value of @ref UART_Stop_Bits */+ f) l' L0 I& G5 e; n
- 5 W0 S& O/ c! h$ j( G
- uint32_t Parity; /*!< Specifies the parity mode.
* p1 ~- }% i* Z. K- _' m/ L8 m - This parameter can be a value of @ref UART_Parity2 N7 F. g7 Q. \$ d
- @note When parity is enabled, the computed parity is inserted
7 d" g7 H3 k4 s% _2 ^ @ - at the MSB position of the transmitted data (9th bit when1 i K5 b7 [# `5 b+ j
- the word length is set to 9 data bits; 8th bit when the1 E; [7 `7 q+ u0 _; P
- word length is set to 8 data bits). */0 K- T9 y4 u7 G7 o* v
- ( Z) S; R) O8 |' z5 N6 _
- uint32_t Mode; /*!< Specifies whether the Receive or Transmit mode is enabled or disabled.
8 i' G! c# m y% x# q5 } - This parameter can be a value of @ref UART_Mode */3 C" H/ o9 B" d& j8 }* o( Q
, h1 b( R" e( c6 }& m5 B- uint32_t HwFlowCtl; /*!< Specifies whether the hardware flow control mode is enabled
5 {+ K, F7 T( }* k8 e1 z - or disabled.
' X2 j; _# u% I+ G" q - This parameter can be a value of @ref UART_Hardware_Flow_Control */2 ~8 P! V! m J% U; D
- $ N9 ~- S. h9 n
- uint32_t OverSampling; /*!< Specifies whether the Over sampling 8 is enabled or disabled, to achieve higher speed (up to fPCLK/8).4 P& A. @ ~6 t$ Q
- This parameter can be a value of @ref UART_Over_Sampling */# O- O/ ?" i) U' J+ s
. N1 U- q1 r8 N0 n9 x. s- uint32_t OneBitSampling; /*!< Specifies whether a single sample or three samples' majority vote is selected./ R3 w1 m5 t' b e: ~
- Selecting the single sample method increases the receiver tolerance to clock, ^( @/ C# G, \/ Q
- deviations. This parameter can be a value of @ref UART_OneBit_Sampling *// p; m5 ^' D+ P$ s. F
- }UART_InitTypeDef;
复制代码 四、基本接口设计, w. @4 ] b8 X* \- c, l. W7 k
我们使用中断接收,普通发送。中断接收到的数据放入队列中,在外部可配置每路串口的功能。9 y; Q/ Q5 F" U' k+ `
! J/ g( ~* }8 P* S6 i
- // 抽象出一个串口设备结构体8 t8 p$ K/ t6 A, B
- typedef struct7 c% q! E- [/ S& l$ t, h p) p
- {' K& V+ e) ~& o! u
- UART_HandleTypeDef handle; // 串口句柄
: R% g$ m, C+ y5 R+ z. S1 g7 C - uart_queue_t recv; // 接收队列: X5 p8 x' n& U7 d& W# Y3 q% l
- uart_queue_t send; // 发送队列( T) P ]0 `& Q3 U$ Q
- uint8_t ret; // 接收的值
: C0 D6 K* e+ n* n - } uart_dev_t;
' p3 h# ?; k4 b. }! { - 5 `# z2 V& l2 i3 [$ Y4 [; _2 N
- static uart_dev_t uart1_dev;# c; U- t3 V J* I' e
- static uart_dev_t uart2_dev;
复制代码- // 对外只有通道 不再包含USART1...
+ u+ ]" \; ?7 W: A: i* M - typedef enum
E, O' w( M- b4 Y. N - {. z( X: g0 z, Z( B0 D9 x7 _* U
- UART_CHANNEL_NONE,! H0 h. m3 c7 O4 p
- UART_CHANNEL_1,
# S4 Y8 b3 U7 t( a - UART_CHANNEL_2,2 g% o# F$ j8 v5 @7 _4 I8 I/ X! [4 r) o
- UART_CHANNEL_NUM' h6 Y) o4 j7 C& t" b5 P, t H4 @+ g
- } uart_channel_t;
& s- F6 W& s* a
- c' p! x4 g+ c- // 宏定义串口的基本信息 之所以这样写,方便移植修改. H+ g8 s, J$ V
- #define UART1_CHANNEL USART19 z3 M# Z4 P5 ?0 E q( r# L
- #define UART1_PREEMPT_PRIO UART1_PRIORITY* \0 L# ]- n- D' t( B- j9 E
- #define UART1_IRQ USART1_IRQn' p. P9 A! E2 }* X g) A5 I: n% Q& ?
- #define UART1_IRQ_FUNC USART1_IRQHandler
X$ c q+ L- j% x9 U - #define UART1_CLK_ENABLE() __HAL_RCC_USART1_CLK_ENABLE(). ^$ R5 `, D R/ @5 e; z3 y
- #define UART1_TX_PORT GPIOA8 a7 `3 e6 t, b. X5 O) z: G9 c5 `
- #define UART1_TX_PIN GPIO_PIN_109 f8 @( N' S+ v
- #define UART1_TX_AF GPIO_AF7_USART14 H# s; m- E# I: Q, p
- #define UART1_TX_CONFIG() GPIOConfigExt(UART1_TX_PORT, UART1_TX_PIN, GPIO_MODE_AF_PP, GPIO_PULLUP, UART1_TX_AF)* w* d9 x7 q' V" H7 T( z0 j$ m
- #define UART1_RX_PORT GPIOA7 z& a% Y6 e1 F6 ]( @" ]
- #define UART1_RX_PIN GPIO_PIN_9
) q3 X& ?4 k4 I: [ - #define UART1_RX_AF GPIO_AF7_USART1) x6 U2 v: p$ ^. c3 T5 }
- #define UART1_RX_CONFIG() GPIOConfigExt(UART1_RX_PORT, UART1_RX_PIN, GPIO_MODE_AF_PP, GPIO_PULLUP, UART1_RX_AF)7 h( F, X3 C- {" `
, u% R( G$ O/ T; i, S: Z- #define UART2_CHANNEL USART2; a1 I7 h1 |. x* ^5 t
- #define UART2_PREEMPT_PRIO UART2_PRIORITY
' a; S+ {5 T1 k" ] - #define UART2_IRQ USART2_IRQn
+ [9 c# c. p5 T, G+ O: q2 c - #define UART2_IRQ_FUNC USART2_IRQHandler
( L. ~+ D) p; X6 k; X3 i/ ^$ f) v2 @ - #define UART2_CLK_ENABLE() __HAL_RCC_USART2_CLK_ENABLE()+ I+ B: X: }. R1 ^% A X
- #define UART2_TX_PORT GPIOA
2 |5 ^( z& J( a% x - #define UART2_TX_PIN GPIO_PIN_2
& C1 v- C8 F, f9 m: L1 @; V8 y - #define UART2_TX_AF GPIO_AF7_USART2
0 C8 Q5 ~. f* |* u9 a - #define UART2_TX_CONFIG() GPIOConfigExt(UART2_TX_PORT, UART2_TX_PIN, GPIO_MODE_AF_PP, GPIO_PULLUP, UART2_TX_AF)! C- W( P# H+ a0 A+ n0 s; D
- #define UART2_RX_PORT GPIOA
, r4 z6 m8 G: R) U4 B8 J - #define UART2_RX_PIN GPIO_PIN_38 ~- c( Y& T$ a9 w4 q1 T
- #define UART2_RX_AF GPIO_AF7_USART2+ c% s$ i/ t0 [0 L8 v
- #define UART2_RX_CONFIG() GPIOConfigExt(UART2_RX_PORT, UART2_RX_PIN, GPIO_MODE_AF_PP, GPIO_PULLUP, UART2_RX_AF)
复制代码- // 串口的基本操作 ! u* J' p Z# H8 ]' g
- // 串口10 F# z: r" h% v' e' n) I
- static void uart1_var_init(void)! s4 O' y: g7 f5 b) k
- {
. R, C/ W" P# s: N# \8 h1 c - uart1_dev.recv = uart1_queue_recv;
( W1 U! {) q/ f$ x7 r - uart1_dev.send = uart1_queue_send;
* E4 E4 D- J+ {. _
- x6 ]* n5 O$ T! ^- UartQueueInit(&uart1_dev.recv);- ~2 N: O- v8 k/ H
- UartQueueInit(&uart1_dev.send);6 r4 Z- [6 s$ s/ L) k
- }" P1 u& W c; S8 c
- : T* K p U: P, b! m" v {1 Z
- static void uart1_gpio_init(void)+ Y! p% L& {8 ^9 g8 O
- {
2 U. k1 m: z# L a' b2 b - UART1_RX_CONFIG();
% k9 @- m2 G0 m) b# L+ d c$ y - UART1_TX_CONFIG();- v6 w- q) g6 I- O2 F
- }/ O, Q0 @6 d( w. g
- 5 K0 O3 _4 z+ D# v4 F0 P
- static void uart1_mode_init(uint32_t bound)
7 Y# f& s* G3 C4 i% M, J6 y9 \- B3 T - {1 z- |' L" l: L& h2 ]) u
- UART1_CLK_ENABLE();) o+ f9 Z* s& Q( d: I% G) H) P; ~
- 9 ^: [4 n; ^. L+ w* w9 j
- uart1_dev.handle.Instance = UART1_CHANNEL;- K+ W/ Z- m) T5 z
- uart1_dev.handle.Init.BaudRate = bound; // 波特率
% `* \5 q- {, y9 C# P1 U - uart1_dev.handle.Init.WordLength = UART_WORDLENGTH_8B; // 字长为8位数据格式
, s. h' j3 _8 S: N1 I8 H - uart1_dev.handle.Init.StopBits = UART_STOPBITS_1; // 一个停止位
' K9 }& s- [: a# _# r. T) c - uart1_dev.handle.Init.Parity = UART_PARITY_NONE; // 无奇偶校验位
, d5 C3 m4 W, c, D u - uart1_dev.handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; // 无硬件流控
& h: h, l. T2 W* u% X1 h8 c' _ - uart1_dev.handle.Init.Mode = UART_MODE_TX_RX; // 收发模式5 z! m. L/ I/ Q f+ b
- HAL_UART_Init(&uart1_dev.handle); // HAL_UART_Init()会使能UART12 a: u1 b2 |& I# I: ~0 H% p
- }& `( ~- ~4 [& v6 e$ \
% C& R7 K& H0 l! R( m- static void uart1_nvic_init(void)6 N$ s! _4 ~3 t, p2 _
- {. r# I( M6 Y& _) m" }: W; y
- HAL_NVIC_SetPriority(UART1_IRQ, UART1_PREEMPT_PRIO, 3);+ y- k: [( L$ _! t; h
- HAL_NVIC_EnableIRQ(UART1_IRQ);
1 P6 K- C; V; [9 T4 S2 f - ! [% L! G, i8 R8 E" ?. f* {
- __HAL_UART_ENABLE_IT(&uart1_dev.handle, UART_IT_RXNE);$ E) a, Z e2 B1 z; C
- }
9 e7 z1 ~- _8 l3 R- z8 X! f
( v8 x$ x$ g2 d( H/ G0 P- // 串口2
& g+ V) W, L; J, b - static void uart2_var_init(void); M. c& n! ]. ~6 V
- {) S; ~8 E8 M# y4 M& O" p
- uart2_dev.recv = uart2_queue_recv;
4 U1 ]3 h# H$ s. r# | - uart2_dev.send = uart2_queue_send;) t) K0 x) m5 _) f, T
7 a1 S* m% r1 U6 s) u0 k% k" k% R/ }- UartQueueInit(&uart2_dev.recv);$ Q; R( K# Z% ^( T5 h- ~
- UartQueueInit(&uart2_dev.send);1 d5 \ z( n% Y3 D
- }
, W7 H$ K: M$ f& ]% \- b" G( a& C
4 U2 s3 a/ T( |% [. O4 u1 w& w- static void uart2_gpio_init(void)' b( ?) M; {; p* i0 x" E
- {0 w) h: q8 O& Y+ |
- UART2_RX_CONFIG();$ ~/ `' }# ~% q. X3 u2 ?
- UART2_TX_CONFIG();4 w" x. {3 q" R3 ^% y1 x0 s$ o
- }
9 g8 {" P2 m( u! q g
$ _/ q. V! @# V8 `" ~# H- static void uart2_mode_init(uint32_t bound)& R% f7 v& m% w. Z; g/ T: t- v
- {
9 f3 Y/ b/ n) i" H& a: t/ C" h7 H - UART2_CLK_ENABLE();
" u2 Q; t2 S5 n! i* s z - y3 L( l( b5 a/ G, m
- uart2_dev.handle.Instance = UART2_CHANNEL;
) z: N* y9 q$ c, p6 m W - uart2_dev.handle.Init.BaudRate = bound;, \0 C/ L. p$ ^# y% N- a
- uart2_dev.handle.Init.WordLength = UART_WORDLENGTH_8B;, D$ m" ]: p1 a: }# g4 D, t8 B8 d
- uart2_dev.handle.Init.StopBits = UART_STOPBITS_1;
) ` m" u" x& R! [9 s5 y - uart2_dev.handle.Init.Parity = UART_PARITY_NONE;
! n# U5 C4 W' c. h; H - uart2_dev.handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;; J$ p7 i( g/ H' L- }0 z5 X1 J
- uart2_dev.handle.Init.Mode = UART_MODE_TX_RX;
+ B- |1 Z: V: z5 }9 A" f( y9 d - HAL_UART_Init(&uart2_dev.handle);3 W+ D0 h# K% s/ [5 _
- }
/ K/ D+ P1 r. w - 7 X# e) F, v% y4 |
- static void uart2_nvic_init(void)
) ?% L7 P. z# n; ^& V - {
. Q2 d! c9 W: ]% p0 ~1 J# F; E - HAL_NVIC_EnableIRQ(UART2_IRQ);
8 ]9 X3 |7 \: x( _* M - HAL_NVIC_SetPriority(UART2_IRQ, UART2_PREEMPT_PRIO, 1);) D8 T& l" D6 b. b1 U3 l, r5 K
2 G7 o+ U' {, k- v6 w- __HAL_UART_ENABLE_IT(&uart2_dev.handle, UART_IT_RXNE);
3 V1 H+ c% e$ n N" o, Q% P2 |3 M - }
复制代码- // 抽象出一个初始化的结构体 每个串口都有的操作6 p+ V" r/ m+ t
- // 定义一个串口的列表
. \- o- Q. F8 u% C - // 下面的函数就是扫描列表 到这里为止,这些接口都是给内部使用的,外部文件用不到。$ k) i$ r% u% M
- typedef struct& o0 U( m& \) s- }- C9 Y* h
- {
) a- X9 q9 \9 g1 } - uint8_t channel;
2 d! c) g2 P% |2 \ - uart_dev_t *dev;. n1 F1 J C Q( F: p! }$ O" g8 A" F+ W
- void (* var_init_cb)(void);
# k8 o$ i8 y! y- v0 y1 n, E - void (* gpio_init_cb)(void);
4 j' [* E- q9 ? - void (* mode_init_cb)(uint32_t bound);
# p1 r3 H5 k! {- | N% X - void (* nvic_init_cb)(void);( Y0 D# V5 a1 D& ?
- } uart_config_t;& c0 |+ X/ D0 `+ {
/ x. Z& }* Q+ }, l- static const uart_config_t uart_configs[] =
3 G3 u+ r% J9 u# _ - {
0 I9 z+ d9 J1 l+ h6 I - {UART_CHANNEL_1, &uart1_dev, uart1_var_init, uart1_gpio_init, uart1_mode_init, uart1_nvic_init},) E* S; J l! p) A+ B
- {UART_CHANNEL_2, &uart2_dev, uart2_var_init, uart2_gpio_init, uart2_mode_init, uart2_nvic_init},+ Y4 U0 s8 e- f r7 g
- };
2 _+ T7 j+ d2 H6 _' W6 Z
2 a5 B j; o, E- static uart_dev_t *uart_dev_get(uint8_t channel)
( q+ `2 \5 P, I2 ]" \" B - {) ?! U& D3 E% p
- uint8_t i;9 |3 |- e# B: Z/ h
7 M1 j3 f- Z' ^7 y! {- for(i = 0; i < ARRAY_SIZE(uart_configs); ++i)) y U6 {0 |* f6 S" m8 M$ V: E
- {
7 S# Z8 f* ?1 N! m - if(uart_configs<i>.channel == channel)
) f* U9 k, s7 b7 r# V - </i> {4 s7 Y) f# Y) s
- return uart_configs.dev;
' T j- l: Z W w* ~ - }) g% [3 a" f Z' s
- }7 |5 o/ ^4 D) B, k( z: G8 l/ r* X
4 Y/ q# Z& |3 `! Z( v; w- return 0;
6 U1 g( p9 p, [6 G( P, J - }
( A3 h6 T% C5 c
+ y* w# r! S2 b/ k1 M+ p- static void uart_var_init(uint8_t channel)4 Q1 K/ n0 h% A0 e$ y) C% e
- {
* Y! H; d, V3 g. p" x) W/ } - uint8_t i;
, ]8 Q" G: w; J( a- J - 1 S% |# b& ^8 p7 b
- for(i = 0; i < ARRAY_SIZE(uart_configs); ++i)
2 R% d r& d2 e6 c0 |& u, Q - {# b9 h" N" n$ ^' C
- if(uart_configs.channel == channel)
C' _* J, f( V5 [$ Z* z: ` - {7 t) b1 D' v, { ?- ]: o: p
- uart_configs.var_init_cb();
2 t% _ ~/ `# E" d2 W6 j - break;- g, j' u, k3 o3 Z, K! t2 ^" K
- }7 R3 U, @) H8 u4 y
- }
9 ^, a9 _' K3 e. b4 A3 |5 w - }
9 z7 V# d2 Z% Y2 T: {/ N" c/ g- N
- i/ T; q7 t$ G2 x5 g- static void uart_gpio_init(uint8_t channel)" |* Z# t1 }* z( N
- {
$ O! v7 ^# o, l - uint8_t i;0 _5 M0 ^6 D" f6 Q, t, ~# l' D
6 P; D, M1 y1 D0 m- for(i = 0; i < ARRAY_SIZE(uart_configs); ++i)
7 C3 `* h% ?- ~) S7 K0 y" T- Z. j0 I - {
' n0 w$ U) d3 H - if(uart_configs.channel == channel)9 v: I; V8 a7 s3 E
- {
" @% Y0 Y: [5 U3 x+ W7 Y8 \* b: s+ U - uart_configs.gpio_init_cb();
8 y% `$ ~& X, e* w - break;) J7 w9 S* Q& x0 t3 N; s, ?( v. w
- }7 U! P0 n" S6 W' b
- }
/ R f* k( z: n5 m: i. v @ - }6 o6 Y; \: w* z* T4 K
- 5 m& u* P2 m; x6 Y& S+ q
- static void uart_mode_init(uint8_t channel, uint32_t bound)
3 e2 u/ H6 @2 b6 b. y - {9 W1 i* I5 @, x+ h+ B' m8 G" m- `) z- j
- uint8_t i;5 O! q% ^, n4 ]3 i" ?6 v
, _/ w. H$ V; y, `% j0 ]: z( J2 d- for(i = 0; i < ARRAY_SIZE(uart_configs); ++i)0 F* r) c; |$ H/ x: B
- {& x" y% F! \1 h& s" w* x5 J
- if(uart_configs.channel == channel)4 }+ H" l/ j7 h) }8 f* J# @
- {( J7 V9 Q6 M# u8 k
- uart_configs.mode_init_cb(bound);" w; W# o- ^, i5 W
- break;. ?: r# l; m$ y# k
- }
6 r, S" W3 Y$ r. L6 T8 ? - }$ {5 m, ^! L" X [0 \! i
- }- q: C* r, ~) p5 j$ D
- 2 H' j4 j, X6 F- N5 D" J
- static void uart_nvic_init(uint8_t channel)9 j" z9 a; f5 }9 A' z
- {
5 L" Q% O# K9 J) S& F - uint8_t i;
2 C8 c$ r9 d" T Q! V
. g* R+ ]" @3 r- for(i = 0; i < ARRAY_SIZE(uart_configs); ++i)+ A7 W c; L! [+ N
- {0 E0 j9 L F5 r Q8 B7 F- U
- if(uart_configs.channel == channel)
( C' U: t) L% q$ O - {
3 C3 n7 @4 o ^, n7 u# o3 }) t - uart_configs.nvic_init_cb();
b9 {$ P0 W8 ?9 W% P - break;# O! S0 n0 B/ i- N& x' B# y
- }
/ T0 y! Q/ y2 G2 o s4 y3 n5 f0 ~ - }+ \- G- I, }- M1 {3 b' W
- }
复制代码- // 这里的函数就是非常重要的了,都是给外部使用的。* d: S1 Z2 E1 x" d; y6 H
- // 初始化函数,同步发送 异步发送 接收处理) H4 O# C4 ^! N) a' _
- void UartInit(uint8_t channel, uint32_t bound)) o: b" o8 C1 j1 K: l- P
- {
8 }$ v4 T( }7 [" _, k2 Q' | - uart_var_init(channel);% }8 x9 G( h G3 a
- uart_gpio_init(channel);$ I- ?; X; V9 h3 p5 h
- uart_mode_init(channel, bound);
0 m; H( G$ i7 x, E; G- f - uart_nvic_init(channel);
) |. v" J9 I5 X6 Y0 o( w2 b - }% k4 I u# t5 B/ g* T9 X4 v
- " i; [1 f$ a. u, E4 w& t% `
- void UartSendSync(uint8_t channel, uint8_t *buffer, uint16_t length)
C/ Y+ Q$ e, A' H7 ~ - {* t- Y! m2 D, R3 S/ v
- uart_dev_t *dev = uart_dev_get(channel);0 S2 U+ F* ]% U0 q0 u4 I, X! T n
$ W6 P9 ]" T) r! a' `- HAL_UART_Transmit(&dev->handle, buffer, length, 10);$ \5 u$ o9 G" ^( p
- }
) H3 ~, p8 x0 l8 @/ W4 K$ g
- t* _+ [/ d D3 E- void UartSendWriteAsyn(uint8_t channel, uint8_t *buffer, uint16_t length)$ @( D+ G0 |* X6 D$ k9 a
- {
6 L8 K) O0 \, i/ _) Z - uint16_t i;
( y- |. u7 e/ f9 ` - uart_dev_t *dev = uart_dev_get(channel);& v! F4 Y ?' u" E$ u
- - L# V: k' ?/ m) `* T' ^+ s
- if(0 == dev)" L! Q3 U4 j( |# N
- {% C) d/ Q$ e0 j0 @, R, Z
- return;, [2 S2 x5 n# @ o
- }
( t6 t8 w$ M% x - $ n# [) u% i. C( P" `' [) k5 R7 `9 y
- for(i = 0; i < length; ++i)1 i. M% s: w$ s l2 R% C" f
- {) ?, E* [7 ~8 L1 F6 u
- UartQueuePush(&dev->send, buffer<span style="font-style: italic;"><span style="font-style: normal;">);: v5 t- I2 z8 L7 c# ]! w
- }
: e0 ?( Q, ]: l3 f1 x - }- C. H$ @/ j, k8 ^* F& |8 r
- |1 A2 B& r9 _. B
- uint8_t UartSendReadAsyn(uint8_t channel, uint8_t *c)
& p) }/ _0 W2 s' Z2 u* m9 h# `6 I - {
% S- L2 l2 R& n) T - uart_dev_t *dev = uart_dev_get(channel);6 \' o6 `1 \) o7 v
7 v$ j, D4 V( g: Q, P3 N& m/ ]- if(0 == dev); @3 g5 T4 ^# Q& Y, ~
- {
& r7 ]! ]5 [0 F1 [7 Y - return 0;5 G: |+ U9 ]2 v$ t! E- d7 y
- }( b% `- [9 N( G n
& C$ k! v) x* j- return UartQueuePop(&dev->send, c);( J- N4 |& l+ C0 C% Z
- }+ g- l, ]3 \ e. N
- ( f% d7 b9 q+ X0 J; t
- uint8_t UartRecv(uint8_t channel, uint8_t *c)+ K8 @" y3 p& h4 k
- {
7 B: Y b! D- G8 O6 c/ a - uart_dev_t *dev = uart_dev_get(channel);
2 D6 r4 B" N$ C: S - 0 e4 v3 E( ?3 E. c8 z
- return UartQueuePop(&dev->recv, c);
5 d F, Y& t4 Z L2 t) A8 G - }
, g1 w9 v0 K( d - // 这里我没有使用串口的回调函数。6 j, c: c; s$ I0 T! x# W
- // 中断服务函数 接收到数据就加入到队列中。在UartRecv读队列数据并处理。
" `. H* f+ Z j: z: @5 w0 L - void UART1_IRQ_FUNC(void)
# b3 |6 O9 `/ r& H - {
! `4 K- C* t; h: Y6 N4 ^) Q# J - if(__HAL_UART_GET_IT(&uart1_dev.handle, UART_IT_RXNE) != RESET)+ ]; G& r! c8 W
- {! B, a- U! w; |' V% K! ]. G
- HAL_UART_Receive(&uart1_dev.handle, (uint8_t *)&uart1_dev.ret, 1, 1000);
p- _) Q3 B$ ~% p- B# y - UartQueuePush(&uart1_dev.recv, uart1_dev.ret);5 h ]+ G. k2 @* W
- }
# x$ _4 o2 s2 n/ V1 i( T4 Y - * v' \8 w( E' X
- HAL_UART_IRQHandler(&uart1_dev.handle);+ S8 `: E2 @6 Q7 l. O
- }& \. O+ q+ { w& a
9 s1 e. i8 U* \7 a4 u1 Z. u- void UART2_IRQ_FUNC(void)
7 b7 e' i Y- G; X b - {5 j6 W9 f: M: ? M. I* y! k
- if(__HAL_UART_GET_IT(&uart2_dev.handle, UART_IT_RXNE) != RESET)
6 I2 }, {, O1 u3 |) R - {
N& U$ S* O# L9 F+ ` - HAL_UART_Receive(&uart2_dev.handle, (uint8_t *)&uart2_dev.ret, 1, 1000);1 E/ f: e k' A) O
- UartQueuePush(&uart2_dev.recv, uart2_dev.ret);/ J) t1 P" j! B3 s9 N
- }' i0 m. y' Z5 f' m4 X; k* x5 L4 ^
- " j1 q+ k7 Z; Y9 m7 r# o" U
- HAL_UART_IRQHandler(&uart2_dev.handle);
5 ]- I+ T: ~3 V- B - }</span></span>
复制代码 8 r0 R& F2 e& f' t1 h; C$ z$ a
到这里,串口的初始化,发送,接收的接口就封装好了。! C2 w/ D& j2 P( L8 d
+ i1 \+ K+ a5 q
裸机:裸机就在while(1)中调用UartRecv扫描数据;
; c9 ~ P3 ^. e( l+ J- q" X9 D% F( a' M6 H. n) X3 q, z1 Y
系统:带系统就在任务中扫描并解析数据。(带系统可以使用信号量去同步数据 -- 这里只提出一种思路), X# U6 _* x4 f
4 c* \: M& e- V- V2 b8 F串口队列可参考:串口队列
9 l- S6 |) `+ A" Q1 C' y1 T" r6 q
6 n% w) h/ G' [6 x9 {/ b( X$ y7 |! l) p$ G& D
7 g" m, M) B1 Q8 v$ E5 i# U5 Y" y
- h2 R+ E* o* m" O! F5 q; j. |
1 s3 b- H& K/ Z" X, u, A |