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