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