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