写在前面& l q! ^; g0 C" o& k
芯片型号:stm32f030c8t6" W; p- f- C# u5 ^: ~0 M
说明:便宜,用量大
1 K# ]# B! c0 q" J; r要点说明:初始化、主函数调用串口接收callback、串口接收空闲中断,串口接收中断& J1 |* K- E3 D6 |+ B
这种API封装方式可以拓展到其他单片机,但需要注意单片机是否支持接收空闲中断1 y# G$ r4 K4 B, E/ W4 F
本文注意介绍空闲中断的应用,这样就不用在定时器中计时来检测接收超时中断了
6 s4 x8 u8 _# r, j7 [' g
4 _& G7 h s7 P5 j8 W- P& U一、应用9 h- V$ j) V8 C
外部定义串口接收回调* f4 a& V9 C2 t. k$ J" D9 @3 L
当串口数据接收完成后,在该回调中处理串口数据即可" u2 W- z, }# ^: Z! c
- void Uart_recvCallBack(void *buf, int len)& X* L5 z0 H: {% c* l5 @4 i3 p
- {
8 n8 U/ r. P# j3 Z7 [" c+ L
4 l$ k6 \- n9 b1 S) w- }
复制代码
* B" b. O5 Y' ~4 X+ ~外部初始化串口8 i9 w$ \& D3 Z `3 }
- myUart_initialize(115200,
1 ~2 ~. e% Z, S0 E$ n. ~. U - USART_WordLength_8b, l Q* W( J1 z+ V! i& m
- USART_StopBits_1,; C% J# n* L2 B2 t! r8 B Z2 y
- USART_Parity_No,& ~0 H; a6 x7 p
- Uart_recvCallBack);
复制代码
/ J P( R* P( _% L5 E二、源码
9 j' m, P- o7 A8 S; i e6 Z, {myUart.h
7 A+ ^* U. q) q9 {4 x- #ifndef __myUart_H9 v1 w% O( _5 d) J$ S
- #define __myUart_H
0 ~! u0 q- H* ~+ p
- v) k6 V! z* l- #include "stm32f0xx.h"
# O' O% v( m) { - #include "stm32f0xx_usart.h"
v5 ?* r! \2 {, G+ j' [ - #include "stm32f0xx_gpio.h"
+ Q8 g8 S! |& l - #include "stm32f0xx_rcc.h"
2 C2 y1 q1 N% N9 a( Y5 b9 \7 X - #include "stm32f0xx_misc.h"0 A$ ]0 e) v8 k4 Q8 ? J/ p0 E) u
- 6 g! h! |' J9 o: z: `4 B
- #define USART_REC_LEN 200 //定义最大接收字节数4 Y* G" v( a# s4 J7 p3 x
& K; K" H. ?, O- typedef void (*myUart_cb)(void *buf, int len);3 U) x2 M7 V2 j8 O$ I1 a
3 h9 v2 g1 _( M B5 r# u$ r- void myUart_initialize( uint32_t USART_BaudRate,$ m( ~' Q d* y# N# A; C" l# w
- uint32_t USART_WordLength,
H( Q* i- q+ a# N/ O$ C - uint32_t USART_StopBits,
0 @& [+ E' _9 J! n2 F- Y - uint32_t USART_Parity,
4 S- y' [# m5 k& C - myUart_cb cb);
7 b. c7 Y: A( d u. \ - void myUart_setBaudRate(uint32_t USART_BaudRate);
* H2 M1 H' G' e0 N8 v - void myUart_sendByte(uint8_t byte);: j8 v: m" B- ?5 `$ ?
- void myUart_sendBytes(uint8_t *Buffer, uint32_t Length);, B$ g! E0 U' f# T& J# H
- uint8_t myUart_recvByte(void);& E: u3 c6 P6 Z# }9 ~- c3 g
- int fputc(int ch, FILE *f);2 s- F% i) a: k% v" D
- R8 U8 y) h4 ` O- W# o" T" \% t- #endif /* __UART_H */
2 |2 t8 @; W. f3 y' o8 K( M
复制代码
7 A/ W2 O7 f0 F7 K; x, nmyUart.c0 |. N% b5 | F* I
- #include "myUart.h"
1 W, d! j* T; r S# X/ U% g6 J b
: K0 g; e+ u7 Y; x- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)( q1 ^9 B* ~7 f# X0 m
- # e; T* A! k' W
- uint8_t USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.' R8 U- W5 q# {2 c4 V
- uint16_t USART_RX_count = 0; //接收状态标记
/ @4 W( d& y* f! V7 y0 I( \9 _! d - myUart_cb myUart_callBack;# H% R. z( F6 Y/ o. n
- /* Private functions ---------------------------------------------------------*/5 t, u& g* ^9 l+ V; W7 d
- ( M' x, g# J$ F
- USART_InitTypeDef USART_InitStructure;
5 H! @0 L( k, l2 b: }9 P0 ^ - - h5 o# O5 W" ~+ g& Z
- void myUart_initialize( uint32_t USART_BaudRate,6 x% x7 |7 u B5 r
- uint32_t USART_WordLength,6 D' b2 K4 C2 N* p) w) B5 K6 m
- uint32_t USART_StopBits,
* z \' Q: x3 {' z7 x! \ - uint32_t USART_Parity,4 N$ c5 v7 c' C9 M% J- `
- myUart_cb cb)1 ~% P! C* E W7 @
- {
$ _% Y6 T5 }+ G7 N; X - , `% m2 e$ ~% C
- GPIO_InitTypeDef GPIO_InitStructure;
4 M+ M/ l8 v7 O - NVIC_InitTypeDef NVIC_InitStructure;
; j( t# O6 y( n/ U1 T1 j - ' @4 j0 J7 r5 B2 E( a
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE );0 N$ M- D( f* C3 r/ V
- % |( P: T3 r% v9 J1 z# V r
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1);
* ~# z4 D0 @% r! ]7 h, r# X1 T% R - GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1); - L/ x# n3 X# Q6 X
- /*5 _1 `& Q3 |3 v4 P) k
- * USART1_TX -> PA9 , USART1_RX -> PA102 C- Z/ }! i3 p
- */ 0 [# k% f0 R6 I$ Z" @
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10; & I" I! @8 H5 E7 g* v
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+ s7 W6 J/ I; G* E: S - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;6 u" d1 s' \* F, v2 ?
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;( H5 Q! N! s2 ^6 t( ^. o. o
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
( r8 }2 L5 S( [# Q - GPIO_Init(GPIOA, &GPIO_InitStructure);
+ Z3 e& h, M! r. Q L S
) l; d$ w* a% Y- //Usart1 NVIC 配置
9 @: h$ ?& c3 s" u - NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;3 u1 X3 o6 M* d- A
- NVIC_InitStructure.NVIC_IRQChannelPriority=1 ;//抢占优先级3% V; [" E5 a! h* C6 ?
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能- E5 G. n7 x7 i: [( _+ [3 _
- NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
0 X+ C( `/ u; J* Z) ~4 Z - ' W4 W2 M. d. j( `! D" d- D
- USART_InitStructure.USART_BaudRate = USART_BaudRate;//设置串口波特率8 D# `$ L" g6 {! i- p. @
- USART_InitStructure.USART_WordLength = USART_WordLength;//设置数据位
, N y9 O3 }6 a; T - USART_InitStructure.USART_StopBits = USART_StopBits;//设置停止位
/ p, @1 s- I9 _' Y7 Z3 @ {+ P# z- c1 [ - USART_InitStructure.USART_Parity = USART_Parity;//设置效验位
: {: i E+ D! t/ F% Y$ ~1 C - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//设置流控制
- a3 I3 r4 @( E - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//设置工作模式& n$ G# k- Z& c) m; ]
- USART_Init(USART1, &USART_InitStructure); //配置入结构体
& }5 Z. B1 a* ~5 w, { - % q1 |% v. W4 Y
- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
9 S3 N {! W5 Q$ f4 h' R - USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口接受超时中断6 G, Y) {& g* k5 i7 m4 u4 `
- USART_Cmd(USART1, ENABLE);//使能串口1
- E9 p% b y# J+ O% `" s" z) ?
' }7 s8 z2 y7 w" e- Y$ G- myUart_callBack = cb;
% e& \7 P- m0 g9 }6 s) ? - }
8 _+ p7 N3 k' W% n1 z; ^ - void myUart_setBaudRate(uint32_t USART_BaudRate)
2 F% ?2 R' a6 E/ N3 @& f, b; @. @ - {
$ A0 n& M0 n. C- P, _) k - USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
) J. t7 Q2 e, ~ - USART_ITConfig(USART1, USART_IT_IDLE, DISABLE);
5 Y0 I, M; z8 G - USART_Cmd(USART1, DISABLE);) R7 e$ I8 w+ H$ @ O$ Y
- 6 h8 H N. O! w" e( F
- USART_InitStructure.USART_BaudRate = USART_BaudRate;//设置串口波特率# I1 T& @3 K- w
- USART_Init(USART1, &USART_InitStructure); //配置入结构体& F C( }, _ z; f
4 D7 J6 _* C0 e* I5 p& g2 x- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接收中断
) q# l9 S$ y9 I) ]; f) ~ - USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口接收超时中断
% w7 ~5 G1 e: e7 A# a s - USART_Cmd(USART1, ENABLE);//使能串口13 z3 L# s- Y' f' Y
- }
, B; m0 w' _( l$ v- i - void myUart_sendByte(uint8_t byte) //发送1字节数据
9 F* _$ _* k& w9 ` - {
& Z& h' j% x2 P2 r+ s - while(!((USART1->ISR)&(1<<7)));
5 G2 q8 ~. G3 w+ p% W0 N' w. k" { - USART1->TDR=byte;
" t r9 ? o6 P - } - P- E- T3 ~9 H8 A6 N5 w, t
- 4 s u" l+ f* A
- void myUart_sendBytes(uint8_t *Buffer, uint32_t Length)
1 J3 f( X9 U0 A- F/ L4 w! p) Q - {
- E- B9 W. F) ^" o& a, _ - while(Length != 0)/ T# E4 a7 f! }8 b
- {
+ A# c0 L8 b# }3 ~! F - while(!((USART1->ISR)&(1<<7)));//等待发送完
+ H( n n' F- @6 ]8 o0 s. R4 }% b0 @ - USART1->TDR= *Buffer;+ Q2 u$ U7 q$ A5 T
- Buffer++;
+ o) r" Q+ u8 o+ D$ @7 q0 Y - Length--;+ V8 W2 w& I' k7 {8 c
- }
6 N' e2 t2 {) D1 _, ~2 r - }# P7 T& o2 w% y
- : [) Z* a9 `8 L) }" [
- uint8_t myUart_recvByte(void)8 r5 B8 Z( U8 G8 Z4 p
- {
) n3 q7 O* k$ @; o9 H, \' k - while(!(USART1->ISR & (1<<5)));//等待接收到数据
3 T% r3 J s6 u3 c4 ^ - return(USART1->RDR); //读出数据
' @; T2 G I6 u/ v- ?" D - }- Y4 E; m9 L* ~
- % \0 _" K: `$ i! `
8 o; @0 @ `. T* c' R0 R5 G8 h- PUTCHAR_PROTOTYPE , U9 ]' ^( D' v5 n4 R T" L) ^
- {0 z5 [, p% J( ?! h5 t2 ~
- /* 将Printf内容发往串口 */
5 O# \$ Q2 w4 O# | B# W( e - USART_SendData(USART1,(uint8_t) ch);5 Z% \0 c! e( J3 X3 t7 u
- while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)% Y. G' L& O G& y- ^6 b1 p
- {}
6 |2 X2 y) K S' q3 ]* S8 B, q
& a3 |: l& w `6 g9 R) u- return (ch);* d5 P" w7 {2 B' l' n0 C, V" E
- }! v9 C. A# R6 t) f! k, [
2 _6 u' M K' a' ?7 ~$ {- void USART1_IRQHandler(void) //串口1中断服务程序
4 w2 P, M8 x, _& \: W0 T - {, v2 a6 ?% o1 e# R8 N; _% c: x9 s
- uint8_t Res;: A4 G3 |7 z8 E5 g
- 2 V" ~4 f7 Y: O
- if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)8 R! e3 O1 z! |4 E& V
- {" s; L( T+ z# x1 L) h
- USART_ClearITPendingBit(USART1, USART_IT_IDLE);//USART_IT_IDLE需要手动清除
" N f' ]9 H2 R: l0 ~0 a1 a - if (USART_RX_count)
$ P% {2 @9 t1 v) B3 v+ S - {
) `2 h5 T- a+ f8 D - if (myUart_callBack)
; L/ h. e; K1 F7 {0 r- H - {- A5 h3 j# d: X$ g! W1 p
- myUart_callBack(USART_RX_BUF, USART_RX_count);
* [4 C/ C; T8 v2 y- M2 F% h2 ^7 O3 P - }: a' y9 { e7 [! Y' G ?
- }
. t/ n+ I" q4 D) a. z) H( R - USART_RX_count = 0;
: R# ]" Y9 \ g+ \' e- ` \7 d* V - }7 n/ ~& M- H# \* u1 R3 `# J
- if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
3 _5 }) s6 U- y% q) E8 G% b w - { O) l9 o% J" ~9 }! z5 S3 T
- USART_RX_BUF[USART_RX_count] = USART_ReceiveData(USART1); //读取接收到的数据,自动清除USART_IT_RXNE中断标志! v3 _, P. X) C, G. H* C2 R6 d& P
- USART_RX_count ++;& }( [4 f$ w2 D$ C& }; P4 r: Q9 Y2 B
- }
4 [4 z" h& z0 }4 c; U - } ; G7 e& _+ K& y T! [ _
- . E5 T: _6 D. T; A
复制代码 & n5 S8 Y8 ]- P! n
|