写在前面
% d; M8 c4 o7 w! F$ S- ?9 b& o芯片型号:stm32f030c8t6+ _6 \( F* x* x! L" s0 I" J0 w
说明:便宜,用量大2 p- P) D7 r8 L) ]1 }# ~$ t% R1 I. G) R
要点说明:初始化、主函数调用串口接收callback、串口接收空闲中断,串口接收中断" E8 c. ^' D! Z/ H- H
这种API封装方式可以拓展到其他单片机,但需要注意单片机是否支持接收空闲中断4 `$ y+ y: x: W* a9 b
本文注意介绍空闲中断的应用,这样就不用在定时器中计时来检测接收超时中断了
: U, @" \1 p' P: p8 N9 w" j) J+ ^( z/ p% N
一、应用
' O( y }7 K* c+ @外部定义串口接收回调& L! I* @2 j) E$ H7 @' }
当串口数据接收完成后,在该回调中处理串口数据即可: H; B+ l, T% |) a' }5 O9 e7 K
- void Uart_recvCallBack(void *buf, int len)
8 g( ^: T- K% g! o! f4 G - {3 ?* t3 s: j0 l8 \
$ c2 M- d: b* P$ b+ y2 ]- }
复制代码 5 ]3 d& a2 ~$ I Q# O' ?3 ^
外部初始化串口* I% N2 C) d, }! u+ O5 u( r! T
- myUart_initialize(115200,% h8 p+ f8 Z5 E4 e
- USART_WordLength_8b,. y& i# y* h: v3 ^% I
- USART_StopBits_1,6 b" {3 S# e$ n* W4 H/ [7 c
- USART_Parity_No,
0 a5 a7 J( C$ h+ M: V# N7 C - Uart_recvCallBack);
复制代码
% k: T/ F v" F. n二、源码7 M% F( N, S" b4 g9 B
myUart.h
* `& Z/ q D( K4 h1 \1 h- #ifndef __myUart_H
4 U4 E8 F/ }& i- @% q% J* s/ A - #define __myUart_H# a9 C8 m% r# `1 x& Y
- * ]) N- V. j6 L! t
- #include "stm32f0xx.h"; F2 l. k6 s. f% Z" \/ C' |
- #include "stm32f0xx_usart.h", a/ l$ R7 {, U: j9 R( Y
- #include "stm32f0xx_gpio.h"8 s. b% e' n3 b/ R
- #include "stm32f0xx_rcc.h"
+ ?6 M6 {- b5 q, d" h - #include "stm32f0xx_misc.h"
1 e: [0 t% f1 d0 k8 |
[+ Q. f% V# \2 s- #define USART_REC_LEN 200 //定义最大接收字节数
' |0 F3 t( n# U% e7 ]# |7 x
9 n! V% Z4 p, i- typedef void (*myUart_cb)(void *buf, int len);$ ?6 D) F+ V! p) q$ o5 `9 c
- 9 V( [* s" m2 X/ r: r
- void myUart_initialize( uint32_t USART_BaudRate,
3 H6 W6 K1 s5 {) i5 I5 Q4 F - uint32_t USART_WordLength,. k Z: A$ K! W( Y( i1 \
- uint32_t USART_StopBits,
1 q {0 N0 d1 b7 F( [/ Y - uint32_t USART_Parity,
! ^2 q$ ? b5 `8 z. H0 L - myUart_cb cb);
2 u/ N- X. R9 c/ o* y - void myUart_setBaudRate(uint32_t USART_BaudRate);/ q* T# t' e+ M& D6 [# \+ ~
- void myUart_sendByte(uint8_t byte);- \2 a" ?/ l% L+ C& G1 L7 j7 D
- void myUart_sendBytes(uint8_t *Buffer, uint32_t Length);# J) c5 K8 p* s; w5 _, X( {: ~2 ]7 ^
- uint8_t myUart_recvByte(void);4 _9 t1 h; B) B! v! l
- int fputc(int ch, FILE *f);+ J8 r3 i p# g" A
! Y6 o" t3 H# o- #endif /* __UART_H */% C8 l. Z! {9 r8 L
复制代码 . a9 u8 Z' Z. q
myUart.c7 C8 x1 T$ k/ B! Z
- #include "myUart.h"/ ]0 n, F# i2 b4 [8 N; b% `* F
/ V0 g+ Z$ f. x- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)! `7 V/ x6 {; Z" j7 k' y9 k
- 9 r% @7 r' `- v4 k7 F
- uint8_t USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.1 g! l- ^0 `/ V4 p, v$ n5 q
- uint16_t USART_RX_count = 0; //接收状态标记
R* X; {8 h' Y3 w! b7 { - myUart_cb myUart_callBack;* q5 h# C2 l2 {) J5 u1 g
- /* Private functions ---------------------------------------------------------*/. s9 ]& N. S9 U5 K2 s% s4 f1 `* y( y
1 \% M2 j; y+ `/ w: a- USART_InitTypeDef USART_InitStructure;; W9 L8 y, B1 v
- $ H0 q# ^6 O& x4 o! i: ~" Z5 ]2 D
- void myUart_initialize( uint32_t USART_BaudRate,4 B1 E! [3 j- G, n6 e/ J& K
- uint32_t USART_WordLength,
p' L/ T/ t& E2 ?) }2 \2 o - uint32_t USART_StopBits, Q* F0 P7 b. e* e, K7 F
- uint32_t USART_Parity,% ?' d2 [% {3 X2 j7 D; V9 Q7 l
- myUart_cb cb)) D' j# }7 T" B& h
- { ) S' w. J2 `, d! l+ }. u. J
0 Q9 E5 ]) u0 g' W- GPIO_InitTypeDef GPIO_InitStructure;
, `; p7 s) q! z o& J - NVIC_InitTypeDef NVIC_InitStructure;
) x) I% O* j) W0 I7 I
' U% i8 C8 Y+ Y1 e+ X- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE );
* S. G9 V; D4 _, U
/ m: ?. o* X' a- GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1);( f, V- r6 B% L" [1 y
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1); 0 X, _: M. W+ x3 z# P5 I
- /*% r# {- r0 p! z* g) t0 m
- * USART1_TX -> PA9 , USART1_RX -> PA10
6 _0 w. s# Z* `2 ^! Y8 Z - */ 6 ?# M9 h* P$ u# a
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10; 2 W7 |2 f' s" I, Y5 B/ t; p
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
. I( A- }- @# w ]4 L6 J- ~ - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
# H; t7 x" f/ T- ^' A8 K - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
9 k: b; n& v8 W* S- f" V: B - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; ! p* F) r( M- T6 ]0 j$ f0 P5 F
- GPIO_Init(GPIOA, &GPIO_InitStructure); 2 k! q% a8 F8 U u
- ! U8 F# _6 s# z
- //Usart1 NVIC 配置
8 W) f3 Y! s5 w" O" C: [ - NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
; s- n+ l4 J- Q! @. e e' w/ o - NVIC_InitStructure.NVIC_IRQChannelPriority=1 ;//抢占优先级32 _: j" b5 R- J% T/ R7 H) N
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能' O- y. c e8 _0 G+ _
- NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器) I1 B5 G7 r& y i5 w: L
- ! X( _& G$ G! Y/ @+ |
- USART_InitStructure.USART_BaudRate = USART_BaudRate;//设置串口波特率) E8 ?; U4 A ]3 C8 M9 |' m# n
- USART_InitStructure.USART_WordLength = USART_WordLength;//设置数据位4 G2 ^2 q4 o( n! w8 w8 ^
- USART_InitStructure.USART_StopBits = USART_StopBits;//设置停止位. a) A$ ]. r) D! Z
- USART_InitStructure.USART_Parity = USART_Parity;//设置效验位2 M. Y* }+ l7 a9 T" O
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//设置流控制* Y" u! k& I4 C3 B
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//设置工作模式
6 N9 v8 M8 w; o5 X+ S; g - USART_Init(USART1, &USART_InitStructure); //配置入结构体- W4 |. m. W5 D/ A3 ]! r
- ( a9 s8 Q" g+ X3 A" l( u
- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断7 @' H1 }6 M7 E& E7 i! i
- USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口接受超时中断0 o7 ]( @" |+ z% m; \+ x
- USART_Cmd(USART1, ENABLE);//使能串口1
! v5 d/ Y% ^3 e0 F% z* R - 6 S' j; l" e0 A1 U
- myUart_callBack = cb;/ n4 E9 l: V) B& \
- } * O, T- ]4 f) Q. T! Y, M0 i
- void myUart_setBaudRate(uint32_t USART_BaudRate)9 n# t; R. J; t5 V5 L' ?
- {) h$ d8 m3 V7 d2 v
- USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);2 a' O2 f# I. c* ]5 D4 C2 g l# Q
- USART_ITConfig(USART1, USART_IT_IDLE, DISABLE);. `% C- h) j0 `" l
- USART_Cmd(USART1, DISABLE);
1 Z, {( Y# X; ? - B4 l& Q1 n9 H$ \% K" O5 n; {% i; T
- USART_InitStructure.USART_BaudRate = USART_BaudRate;//设置串口波特率% Z1 b+ Y& m) M! h2 h
- USART_Init(USART1, &USART_InitStructure); //配置入结构体0 l) P z& u6 N
- $ d/ }: N) H3 |- k
- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接收中断' W, O3 Z) O0 i' l4 P U9 U
- USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口接收超时中断
( o; w. e: f1 p6 v2 o8 K$ ? - USART_Cmd(USART1, ENABLE);//使能串口11 ]* W1 M6 F" _4 K! S. V f/ @
- }
+ E% ^0 H/ w9 J7 n6 d* [. q2 j - void myUart_sendByte(uint8_t byte) //发送1字节数据
& x# {* ?6 o- ^- ~ - {
, z. P7 A8 @0 i) y3 o - while(!((USART1->ISR)&(1<<7)));
* b: [% h; G0 B! y( C9 {* P8 g - USART1->TDR=byte; 6 B- {' Y) _9 P# r
- }
* c; O1 E- ~2 u n. R' L# y - - }- e k2 u: s/ k. U
- void myUart_sendBytes(uint8_t *Buffer, uint32_t Length)
0 j# N: y8 W' F* \! L9 N- E - {) }4 G# b% j3 U- w% T! B. N
- while(Length != 0)* s1 T+ @4 y" p% m' A4 C$ C
- {! Y. N* Y* s& h
- while(!((USART1->ISR)&(1<<7)));//等待发送完
6 Z. y1 I8 {% R* M, {- m8 e2 N0 ` - USART1->TDR= *Buffer;& T+ a; D# b$ b6 A$ ]0 O
- Buffer++;9 Q/ o4 H) I4 c: k$ W9 B
- Length--;
9 @' ^5 O9 n) G( l4 c: Q - }# x) X( _- t/ I6 m
- }' t4 T/ J( Z; a- D8 _2 |+ v- t+ e
- " a/ W: o+ T, P# I1 B
- uint8_t myUart_recvByte(void)
# \, @4 K+ i/ }: T" ^ - { # F; D8 z7 `' l$ [- G8 D- \
- while(!(USART1->ISR & (1<<5)));//等待接收到数据
) _2 {) b0 l+ s5 K( C& Y - return(USART1->RDR); //读出数据
}$ W u6 ^9 j - }, {' H$ `; t( _. w: _6 q. @! @
. t$ E+ A1 Q" r7 e- 8 P2 e }' x, x& V- n+ R4 o
- PUTCHAR_PROTOTYPE 5 Y. l4 R! S2 D2 {5 E* p
- {
( J1 A h& z. s3 i - /* 将Printf内容发往串口 */' ^9 b6 a+ n; X4 R. E7 m
- USART_SendData(USART1,(uint8_t) ch);
: @( u4 F" n) T - while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)6 N) E4 `( n1 B4 T8 f* h0 l
- {}
: a: e6 _8 i9 h
7 n" I# z; c: A6 M d2 D- return (ch);' k! z7 z) w P* S9 k
- }
\. ?( k. r/ v3 H9 b' Z! z
& R' x& I! |1 C: ]- void USART1_IRQHandler(void) //串口1中断服务程序
9 q0 H9 w$ ^) ~! A( V4 O5 v - {
2 s- l- G3 J2 }0 J# Z - uint8_t Res;5 y" b% M! |/ b* J% }2 s
- 2 y! d6 n7 B G9 K6 B6 r
- if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET), }+ u% k; I! a" S, N, W& f
- {; U2 ~0 ~, Q8 P* i
- USART_ClearITPendingBit(USART1, USART_IT_IDLE);//USART_IT_IDLE需要手动清除- o. K! C1 c, Y, o0 i' t( P0 i
- if (USART_RX_count) c8 }4 y% `. P$ e: ] q( N
- {
% ~0 S! c- j4 ^6 ` - if (myUart_callBack)
q: K0 G1 ?) R( a: E4 d0 D - {
z% y0 r% h! n4 a2 f - myUart_callBack(USART_RX_BUF, USART_RX_count);# i0 `5 P7 j1 d! [
- }
' f) q' Z& [5 t+ y- r! I- \6 N - }
9 a- Q: M0 s7 r. ]1 a# X* h - USART_RX_count = 0;
. Y- l4 }8 Q' K2 v0 F+ I& [, w - }
5 D* B3 L" E* [$ ~6 e3 e1 Q - if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
, u0 P6 F9 J5 w6 n. t7 m - {7 o8 J. g# A, ]1 C8 b; a
- USART_RX_BUF[USART_RX_count] = USART_ReceiveData(USART1); //读取接收到的数据,自动清除USART_IT_RXNE中断标志0 B- V; F& @$ v3 Z3 |0 g
- USART_RX_count ++;/ C+ ? |% M6 W4 W0 Z; `- D+ Y
- }
- n! ?# P" t+ Z h/ T - }
. O3 m& P* o5 d8 j - # _+ ~8 j% j7 E2 L9 x4 x0 H
复制代码
8 i+ }5 `' _% j |