写在前面
( a+ z% J; `4 `+ \芯片型号:stm32f030c8t6
I5 l$ Z* z; @6 C说明:便宜,用量大
9 A% M; r7 E, s# z要点说明:初始化、主函数调用串口接收callback、串口接收空闲中断,串口接收中断0 s+ B$ O7 m( ^9 o# j+ {9 d4 g& k
这种API封装方式可以拓展到其他单片机,但需要注意单片机是否支持接收空闲中断) k4 p# Z5 A z- ^# L1 g1 X; ]- t
本文注意介绍空闲中断的应用,这样就不用在定时器中计时来检测接收超时中断了
g% R' ^8 _# b% |# \1 w" M: J
" Z# w1 n" |7 C4 b4 S i6 J# h- P }' T s一、应用
! F' w! j; x+ l9 F$ L1 D7 T外部定义串口接收回调
_6 S, y, {2 j3 T A6 ~/ V当串口数据接收完成后,在该回调中处理串口数据即可
g3 i u, R$ [; [7 W# e- void Uart_recvCallBack(void *buf, int len): S& p3 `7 d _( }2 u
- {# z4 \* a/ q& Q: l: ~" D8 }
- 4 F4 p+ e" w3 B( w8 }
- }
复制代码
; ^( w) T d3 Z8 K# [- y外部初始化串口) W+ x: J* c( Z. k
- myUart_initialize(115200,
/ h; u) F6 t; J: ]9 d - USART_WordLength_8b,+ P' M& _) Z9 Z* w7 q& }7 ]
- USART_StopBits_1,
7 P2 F& W5 G' `* k! h1 c - USART_Parity_No,. o8 P3 t6 o E, `
- Uart_recvCallBack);
复制代码
% E) L9 s8 k8 v1 K d ?6 ~+ R/ G二、源码
o7 N1 V2 C9 c6 Z! QmyUart.h. o/ B9 ?# X- V" M6 L6 k8 W% @
- #ifndef __myUart_H) u, z Y0 u( c9 v$ Y
- #define __myUart_H
, g" ?/ P8 E& _5 P
. u2 E& ^* j- w; H- #include "stm32f0xx.h"0 U5 ^1 j" ` W8 H1 E$ \
- #include "stm32f0xx_usart.h", f; f5 d9 v) x4 Z( H" m9 ~6 {
- #include "stm32f0xx_gpio.h"
: T ]8 ]0 ?. L1 {. o - #include "stm32f0xx_rcc.h"
' x; t2 O1 G9 _6 T - #include "stm32f0xx_misc.h"
; E% o+ r3 z% M D
0 H' T5 y* Q: x4 v( {' @0 t- #define USART_REC_LEN 200 //定义最大接收字节数4 t/ k3 |, R& ]- I
/ `; q4 r& }* b/ f8 f# ~2 @* E- U( g+ y' H- typedef void (*myUart_cb)(void *buf, int len);; P9 Q$ a2 F. k
- 7 g! q$ F: b: S- Q. R! e) |* Y) S
- void myUart_initialize( uint32_t USART_BaudRate,
; X4 |# ?: J- G9 L: C7 V! D - uint32_t USART_WordLength,
0 L8 c9 C$ s2 ~) @: M - uint32_t USART_StopBits,0 e# O6 M% o* x) f2 u1 x% ~" L
- uint32_t USART_Parity,, M7 q/ x9 p0 E" f4 R
- myUart_cb cb);
6 g/ A- F5 N% |4 ? - void myUart_setBaudRate(uint32_t USART_BaudRate);8 b* {# g# y4 O3 } u
- void myUart_sendByte(uint8_t byte);" M$ a1 B, G3 t8 a1 O7 N
- void myUart_sendBytes(uint8_t *Buffer, uint32_t Length);
% d$ w$ z2 A. \$ d - uint8_t myUart_recvByte(void);/ a3 a) i& y, n' R; Q' R. N0 M
- int fputc(int ch, FILE *f);7 G& W. D4 u: N6 e8 _$ }, X) y
; ]! K- |0 l( P+ r5 y" ]- #endif /* __UART_H */+ T' C- H' j1 I3 `, b- C; P* _
复制代码
5 g& ~4 c3 H$ r: [9 }) E" YmyUart.c
, p+ g4 Z# s8 R: N6 L- #include "myUart.h"
4 T8 \) K ?2 y. S' p
2 e. s! e. s. V- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
0 b) W" B- M6 e( x
' ?8 ^$ E( F4 E( {1 N0 N- uint8_t USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.9 q- w: h* w) p, X
- uint16_t USART_RX_count = 0; //接收状态标记
! I2 q. z3 K1 {& m - myUart_cb myUart_callBack;
9 `! Q; g6 c8 @8 d8 a( [3 t9 P/ c5 l& G - /* Private functions ---------------------------------------------------------*/3 q: b' C0 j9 E
2 v4 Q( L3 B* _) t- USART_InitTypeDef USART_InitStructure;. g% f" i& O3 o2 j; D1 i
- / f1 K @4 ?8 K
- void myUart_initialize( uint32_t USART_BaudRate,% B4 ?1 N3 P* C; A* t8 l8 ?6 Q
- uint32_t USART_WordLength,- }6 H ?+ v; W' w1 c- q
- uint32_t USART_StopBits,
6 K" E: j: k7 _1 a3 R, C - uint32_t USART_Parity,
1 g: {( _( i4 Y; _- J3 |5 I - myUart_cb cb)
7 X. D' q7 Z) _- u, \7 g6 _ - {
) h5 }- N! n4 k! |5 f# c
5 @6 D# R) |$ ^% s+ n- GPIO_InitTypeDef GPIO_InitStructure;
: ^6 J, l$ ~" A2 G+ X) p - NVIC_InitTypeDef NVIC_InitStructure;. r7 S6 U5 u" d% r; u7 v5 U* ]" L
- 7 r) d' v( h. |6 C6 ?
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE );
8 [" o+ H/ A6 K6 _# @8 i - / W, a G: Z. ~! }3 \9 E9 M: ^; `
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1);
0 ?8 U! i8 M+ U! ~7 W - GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1); 8 R4 f! h1 o8 g5 ^) T( |$ q
- /*+ ~) w5 H0 t: E0 z( W2 S! ?
- * USART1_TX -> PA9 , USART1_RX -> PA10
9 u2 {2 Z, K. L1 X - */
3 k( O& W! d4 @" Y, n% \ - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
: ^) t- ^8 m$ m" G- m0 } - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
( Z5 Q9 L) k. V9 B* ^+ V) f2 E# Q( ? - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
, ]8 D) Q4 W$ A0 j1 n4 B8 J - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;- |1 a5 t. N: ]. z
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; ( e. B( W: i: F6 J( u
- GPIO_Init(GPIOA, &GPIO_InitStructure);
" Z2 b" t- u7 r. Q" Y" T8 O
& U0 D( n- L2 D3 \- //Usart1 NVIC 配置
+ S1 |% ~5 e" F3 }" l - NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
% d. d/ m8 f( Z. j3 ` - NVIC_InitStructure.NVIC_IRQChannelPriority=1 ;//抢占优先级3) F: k) c4 B9 t+ y* l, B
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能6 E0 s, V* R( }& F
- NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
5 R% V E2 c- z, q, R
: @4 ~/ P9 i3 i7 w) w% L/ @- USART_InitStructure.USART_BaudRate = USART_BaudRate;//设置串口波特率+ I9 Q5 E* Y( j! G% ]6 o; {
- USART_InitStructure.USART_WordLength = USART_WordLength;//设置数据位
' E4 F! ]" s8 @3 V0 ] - USART_InitStructure.USART_StopBits = USART_StopBits;//设置停止位% g' C) X9 N* d, O3 b% }* Y
- USART_InitStructure.USART_Parity = USART_Parity;//设置效验位
# K4 G! P2 F/ q - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//设置流控制
0 I9 K- `& L" J/ `3 h - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//设置工作模式
+ G+ V3 F7 f# P8 e- o - USART_Init(USART1, &USART_InitStructure); //配置入结构体
6 g T7 o4 l; N ]9 \* q
9 S$ O; m& X3 v. v k+ ~- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断/ v2 O, A! b, o
- USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口接受超时中断
. D, b" N% H k' g; a1 r7 W - USART_Cmd(USART1, ENABLE);//使能串口1
$ Y' v$ a( Y$ G- }1 }7 H
r w5 b9 z& d* O' N- myUart_callBack = cb;
8 _4 O. \/ k, d$ {/ ] - } ' E5 @% o) C# n7 h: o9 U
- void myUart_setBaudRate(uint32_t USART_BaudRate); s& [/ S2 h: b# J( V5 i
- {
9 b8 a5 S6 @5 Q% F( ]- [ - USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);4 ?5 k- \6 g0 j8 s
- USART_ITConfig(USART1, USART_IT_IDLE, DISABLE);9 ]3 O+ S z0 w1 ^5 h5 S
- USART_Cmd(USART1, DISABLE);
, J; `; s. p: p8 i5 Q
5 j6 }+ t7 F& _7 Y+ K; y- USART_InitStructure.USART_BaudRate = USART_BaudRate;//设置串口波特率6 D) i, U- r; R) H' S: K @; @; t
- USART_Init(USART1, &USART_InitStructure); //配置入结构体7 X. X3 Z( T9 V9 a% P7 B* J
0 Z0 F0 r Q+ ~* I- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接收中断) ^9 [3 i6 Q" A' S. x4 F
- USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口接收超时中断. g, F( q& N# J% a0 C
- USART_Cmd(USART1, ENABLE);//使能串口1: V5 A3 u E) g6 w$ _
- }
) O7 p+ A! m |1 p5 U1 V - void myUart_sendByte(uint8_t byte) //发送1字节数据
2 ]% b$ W6 f2 d( b* I7 X H - {3 w/ n( [6 u" _. P& m2 T0 m
- while(!((USART1->ISR)&(1<<7)));
# w. S$ X% Y5 R5 I- | - USART1->TDR=byte;
J& e1 x8 ^+ B! X; D - } 1 T7 M- z3 A+ D* Z7 G. `- h( g
* G, C R: u* l2 n, f w. y5 L; b- void myUart_sendBytes(uint8_t *Buffer, uint32_t Length)
! b# e8 T/ |& ~; g7 ^: \ k1 z- B - { d. }: q/ ^. r* M5 V6 `
- while(Length != 0)
/ N! X) a! g/ m% \: j X2 N - {+ @9 b }' t c& ?
- while(!((USART1->ISR)&(1<<7)));//等待发送完' J3 [& b0 G# _* T" v* Y% B
- USART1->TDR= *Buffer;+ ?) s; a& N* `! |
- Buffer++;
7 G2 ~" M; n; {! X - Length--;
" L$ d/ J8 h' \- e( M2 q" G$ ^$ s, ] - }
2 S+ O* H) b4 q7 G' Q1 x - }
$ r6 l! V/ a- h# c' Y# E - , R1 F: M9 ?7 A. W) L" P0 s
- uint8_t myUart_recvByte(void)& ^% m4 F0 l; s5 C6 ~
- {
9 O" [4 B9 [$ x" S. p4 }+ J/ B - while(!(USART1->ISR & (1<<5)));//等待接收到数据/ s9 i9 j7 y2 k7 s# `
- return(USART1->RDR); //读出数据
% ]6 v8 W9 X2 X9 i8 p9 b - }, ^* Z# a) v9 t9 N$ |9 B
R/ g8 T$ g7 V. Y& O- 0 O9 \& [5 k" f8 h8 z
- PUTCHAR_PROTOTYPE + N: ~& A' @ ]
- {7 l7 ], J J5 c ~
- /* 将Printf内容发往串口 */
7 \, e" K! l* n$ [ - USART_SendData(USART1,(uint8_t) ch);
* o1 A: Y1 e2 Q - while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
( e( n% q( N5 e - {}
$ t# o3 @0 ]1 ?) @3 `
0 i; ^: N4 x* i2 |+ S- return (ch);
- B% L4 c- H% r0 C8 J- O, r - }
$ g6 M& U# M4 r+ r- P5 Q
5 {3 e, ^* W; w+ v4 U' x |9 @' m- void USART1_IRQHandler(void) //串口1中断服务程序6 T$ c4 S& M7 R: n
- {6 X/ r5 F8 X: F3 L1 E1 C
- uint8_t Res;6 s3 }' v' Z2 }1 n9 z
: r! C* ]' M8 U9 V: p6 Q3 O- if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)% K+ u/ R* D( O7 |1 s! @- i' Z6 o
- {# S! ~ t6 l. V' ~
- USART_ClearITPendingBit(USART1, USART_IT_IDLE);//USART_IT_IDLE需要手动清除
; ~- ?# ]0 X$ O; q1 b: [ - if (USART_RX_count)0 [9 h: g, t! h# b
- {" `1 L4 v7 C& t
- if (myUart_callBack)
6 ?6 x) X/ \( h - {) C( `* f! I1 u j3 M8 T! j
- myUart_callBack(USART_RX_BUF, USART_RX_count);4 `0 g+ h% w# _- ^) T
- }& f8 Z! M7 A) y& L1 d
- }
4 u: l7 E4 d2 C! F' _ - USART_RX_count = 0;7 v, E: ~' F- n! c9 N# K: [
- }1 {( q5 i4 ?6 n+ Q3 w
- if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断1 I* h/ x) `! ?3 z" A
- {
7 _: C3 D( B2 X4 d* Z+ f* P - USART_RX_BUF[USART_RX_count] = USART_ReceiveData(USART1); //读取接收到的数据,自动清除USART_IT_RXNE中断标志; q2 Q6 e. V" O) Z# H- S% q" m
- USART_RX_count ++;+ \7 Z5 \) H# Q7 E+ X7 Y( x f
- }
2 i" j, O5 N6 E6 O/ d+ D - } ' a' L& u3 u1 |# h0 o9 _
- 1 h1 z7 n9 s' i# n1 f: }
复制代码
' T% ], N: w2 f9 m6 n- h |