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