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