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