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