写在前面 S/ o& L! c E+ f( k
芯片型号:stm32f030c8t6
7 t# M/ h5 A% q1 Z说明:便宜,用量大1 |0 l" b d, t8 R8 P2 w9 W
要点说明:初始化、主函数调用串口接收callback、串口接收空闲中断,串口接收中断1 y9 ^& \* r9 C8 ?
这种API封装方式可以拓展到其他单片机,但需要注意单片机是否支持接收空闲中断& n4 A0 n7 e+ m3 V1 ]( b
本文注意介绍空闲中断的应用,这样就不用在定时器中计时来检测接收超时中断了
$ S; y; x7 a! |) f8 }' l% V- o* g) `+ g' [- j: q; e
一、应用6 h1 @, J% q7 V" X6 C9 e; p
外部定义串口接收回调2 h7 `4 Z2 H! T! g5 i4 u5 x
当串口数据接收完成后,在该回调中处理串口数据即可
$ S/ G8 W8 o9 S& t- k- void Uart_recvCallBack(void *buf, int len)- A7 t7 c' S+ G3 G6 {. w5 `, m( m
- {' \& `# M' u7 g0 X4 m
+ E9 X2 r" A6 ?- Q- }
复制代码 ; n, @6 y% F2 q8 g
外部初始化串口
, c4 y- I" c; D6 _$ [ u" G. q' }, G- myUart_initialize(115200,
8 P. H3 Z3 o" b7 Z! J. @ V - USART_WordLength_8b,& }8 m) \0 n& X$ D
- USART_StopBits_1,
% x d4 s3 m" E# M d - USART_Parity_No,0 N' @% R. y8 l; e; H& G
- Uart_recvCallBack);
复制代码
8 M R* w9 z+ M! o# ^二、源码
" T# j* E% M& N" [; G# s8 WmyUart.h
6 F5 m& u9 C& K9 l+ b1 b- #ifndef __myUart_H+ j: H2 E" s5 S. u
- #define __myUart_H
- T: x2 r5 v# R- V( A3 @
* n i2 A: { m- #include "stm32f0xx.h"8 M$ A1 x4 ^6 C) F& \0 N! f+ z
- #include "stm32f0xx_usart.h"5 X- r! ?/ p S2 A
- #include "stm32f0xx_gpio.h"
6 @* B: r* g/ `& r" P! }- P - #include "stm32f0xx_rcc.h"
! H- L7 u- X7 f9 n6 n - #include "stm32f0xx_misc.h"
* m* |- Q3 q0 Z - 2 ^/ F8 ?& Q8 K7 m5 S6 Z
- #define USART_REC_LEN 200 //定义最大接收字节数
; {- w. z6 t7 P6 C1 c& U - 1 }* N- K# j0 n# m3 M; s. L& \$ u
- typedef void (*myUart_cb)(void *buf, int len);
2 G0 T$ ~( o/ T9 B
0 @4 ]5 m/ S S, }- void myUart_initialize( uint32_t USART_BaudRate,$ S/ T( \! a5 w6 a) L
- uint32_t USART_WordLength,) M$ _, x: h9 \
- uint32_t USART_StopBits,
; f3 N* f* Z$ i8 C* c - uint32_t USART_Parity,
2 v5 M1 y: @) {) D$ b/ W; C - myUart_cb cb);. M+ G" u. L3 E4 q% l1 ?5 D4 _; e" D! A
- void myUart_setBaudRate(uint32_t USART_BaudRate);: w& \4 }4 Y; y3 g/ e
- void myUart_sendByte(uint8_t byte);2 {8 Q+ e/ r g9 T/ Z$ v& Z
- void myUart_sendBytes(uint8_t *Buffer, uint32_t Length);
$ u: K. k6 v& E - uint8_t myUart_recvByte(void);
# k) i4 ?. _) y) t7 N - int fputc(int ch, FILE *f);& A' {- L& x7 `
- ) @, S7 t2 J1 j4 U: d: c, \7 |
- #endif /* __UART_H */
* q6 h+ C+ j& Q+ K* q4 T8 d. {; D
复制代码
1 c9 C$ }4 }, a1 | vmyUart.c
/ w, P M( A8 N+ \; O- #include "myUart.h"6 {$ C1 ?4 R2 C
- 2 `, H0 D3 ]. @* y7 \
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)' s4 I: {+ D- P+ a& V# t$ l
) J! q1 x7 b! O1 z- uint8_t USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
$ U) l: X3 X4 ^5 k, r2 B - uint16_t USART_RX_count = 0; //接收状态标记
" x" F. O5 X2 y# k- `: g6 a4 Y - myUart_cb myUart_callBack;
- {( o& L; Q* y6 m' ^ - /* Private functions ---------------------------------------------------------*/
: }: Y9 z/ [6 x, a- l3 E- t9 U7 y
1 A# I9 g' V8 J* y( z- USART_InitTypeDef USART_InitStructure;& j5 F& T$ N+ \- E; J
- # @% r' q! x* y' {5 M! w: i; N8 N
- void myUart_initialize( uint32_t USART_BaudRate,
0 Y8 H) d8 ~0 y6 ^ - uint32_t USART_WordLength,
* E# o- Z2 G t6 o+ I* e* u - uint32_t USART_StopBits,
* a- P# x p% N - uint32_t USART_Parity,
2 d( `9 U, d8 b8 e0 S$ I: d - myUart_cb cb)2 k$ R& X0 J) v# Q, A' I/ [
- {
3 T7 q* ~; Q2 x) n7 T7 a5 T - - ?$ ^: H6 c8 W0 H$ `5 y
- GPIO_InitTypeDef GPIO_InitStructure;# x* O2 b! a& n) H$ t: x0 r- Z
- NVIC_InitTypeDef NVIC_InitStructure;4 J$ R7 Z0 @. _' Z+ t/ y
- B4 p; c; {2 w$ _4 A/ e- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE );
, j& q6 v+ m. A5 `4 }: V6 g, w
0 Z, W: H6 l- e- GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1);
" F& O6 |: b, b& e) o& r - GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1);
1 o8 \5 V9 i. `* Q& j1 n Z9 Q2 y - /*
6 |# |& t, y$ }* z* k* G - * USART1_TX -> PA9 , USART1_RX -> PA106 o4 H* _8 z. A# S7 A& |/ ~6 J: P
- */ * c9 a5 ^; D4 p
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10; 6 T* `+ _4 c) Y: p/ D1 a
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+ l0 R# z; p* |& o7 J' `# h - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
5 a0 E4 v, F) z# |% ~% `7 U( @- Q' Q - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;( F U8 S( p8 y; A
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
2 f1 I9 L9 R7 q! Y5 V- X - GPIO_Init(GPIOA, &GPIO_InitStructure); / Q8 M# E9 ~+ y
# q& I6 ?4 E8 O- //Usart1 NVIC 配置
% D! x0 ?8 M: e' g" v5 [( ? - NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;. c z: ^- e+ q, H7 z
- NVIC_InitStructure.NVIC_IRQChannelPriority=1 ;//抢占优先级3
/ w) v4 G. V- F0 D0 _ - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能7 c/ {/ T' M* U: v5 q
- NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
4 r, R+ g5 w4 m7 _' F
, K& ?3 [5 U. g; m4 H% }2 b9 Y- USART_InitStructure.USART_BaudRate = USART_BaudRate;//设置串口波特率* b, t! ~, | h+ J- t
- USART_InitStructure.USART_WordLength = USART_WordLength;//设置数据位& Q3 R5 y- ?, o
- USART_InitStructure.USART_StopBits = USART_StopBits;//设置停止位
; I" i. @0 `+ y' z: ]1 r - USART_InitStructure.USART_Parity = USART_Parity;//设置效验位
) Z/ c, X, S7 T4 \7 Z% [ - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//设置流控制
, w. b( z/ P9 s7 R - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//设置工作模式
+ x" J9 U+ e9 _ - USART_Init(USART1, &USART_InitStructure); //配置入结构体* K5 ]/ L" t4 ?% n) V6 G
% [$ n Q& U1 A; | | b' N+ f- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断. c) R7 M9 @( o* E: \
- USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口接受超时中断
3 m. |. y" g9 }, g$ p- s( N2 u - USART_Cmd(USART1, ENABLE);//使能串口1' B% ^$ U. H- g8 }( O2 u
* _. K% ~, a6 ~- myUart_callBack = cb;1 Q, x8 E# X X! u, O3 u
- }
3 a' B: a/ H9 C1 w: N - void myUart_setBaudRate(uint32_t USART_BaudRate)6 I6 c4 |% u8 Q/ D; e& s- Z4 I# D
- {
' G, r X4 \1 m - USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);& \& r/ y1 Y; w+ k; l/ y6 c9 O
- USART_ITConfig(USART1, USART_IT_IDLE, DISABLE);
- g* ?9 j/ L9 S/ E" |5 y7 V3 T - USART_Cmd(USART1, DISABLE);
$ M4 U! d* n# K2 T: P: n7 \5 a
7 A. _8 d$ u+ f- USART_InitStructure.USART_BaudRate = USART_BaudRate;//设置串口波特率. R4 {4 x2 F& X3 x
- USART_Init(USART1, &USART_InitStructure); //配置入结构体
! L7 u6 [9 D, T! Z - + q) [5 @5 x2 l( ^4 L# c) }) e
- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接收中断
8 g+ {7 O) e% o$ V - USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口接收超时中断
, H& i7 Q, _- E/ z+ ~/ a - USART_Cmd(USART1, ENABLE);//使能串口1
$ d+ U) s! O2 J! ^$ g! j# C' B - }' s% _8 l" ?. G, Z; ] g5 s' L& W
- void myUart_sendByte(uint8_t byte) //发送1字节数据" {3 ~$ [ `7 b1 g! q& r
- {
( `1 S! _- s/ }% K& d - while(!((USART1->ISR)&(1<<7)));( M; a2 f9 {* k# H, o9 C" G* R
- USART1->TDR=byte;
% E2 i- {# I L' p - } 1 T* g5 ]7 C! b: h8 l2 b7 S# y1 z8 ]
# u( c1 Q/ l2 \1 H4 _: i( u- void myUart_sendBytes(uint8_t *Buffer, uint32_t Length)8 Z$ a- I9 F- z; d/ c
- {5 T/ K$ ?! P* t9 N' F& M( g
- while(Length != 0)
' @, I& I/ x" Y6 } - {
# E4 v+ w1 @! f5 A, d: [% C- Q - while(!((USART1->ISR)&(1<<7)));//等待发送完
! h& ~# J3 C. i - USART1->TDR= *Buffer;
* H! d6 r! {/ ]- G* F4 F3 h - Buffer++;
# a9 ]% V* h( _9 J - Length--;
" l9 a- b- r8 |5 v3 J2 @ - }1 `" O* t6 P% y3 w* ]3 E* h! ~' ~
- }# u, R9 x5 V- E7 w7 ]6 @. K/ r
- , z2 U! r, |4 P6 c4 C" a
- uint8_t myUart_recvByte(void)
% [4 r( P) H) B2 ^& N1 \ - { ( K' f- m6 K" |$ R! u) S
- while(!(USART1->ISR & (1<<5)));//等待接收到数据 A) w Z, ~$ _7 R9 l/ {; {+ A) W
- return(USART1->RDR); //读出数据
, {5 d9 G/ l1 C8 C- v9 C" X# K+ q' D - }4 A- j/ c* |! f4 k! f8 A' l& w- K e
- 5 Y! R% R- L0 S2 `% c7 U/ }
- , `4 d- {5 _/ b* P$ V
- PUTCHAR_PROTOTYPE ! K- V. ~5 k& J$ ?" y1 s
- {
8 J) v- j# ?* i1 B2 O4 ] - /* 将Printf内容发往串口 */
5 C6 R: ^! v- W R5 ` - USART_SendData(USART1,(uint8_t) ch);8 ?6 K B2 W# m- Q4 ~( u+ h5 K, h
- while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
# I; L3 r% f0 x1 e4 ]$ g* q - {}
6 c ?$ a( Y$ u: j - ' X& a' A# T: r6 w
- return (ch);* ~9 P( @% ?% A; N* U8 Q
- }1 P2 i. i1 r6 t3 _# J
- " F4 L& Y8 v( t; t7 J1 Y. @
- void USART1_IRQHandler(void) //串口1中断服务程序7 i9 u" t& n2 ^5 t! ?, D' l
- {1 h( X5 z& Q8 T# E" I( x* W
- uint8_t Res;
" z+ z9 R* E z( L6 c- l& P. U - 6 X7 p" ` w4 k( _9 i4 Z
- if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
& o3 J3 O$ |: D6 f8 m+ H( G$ Z - {
S6 m$ u: R1 P8 \ - USART_ClearITPendingBit(USART1, USART_IT_IDLE);//USART_IT_IDLE需要手动清除, o4 [9 T4 v) z2 i& B3 M
- if (USART_RX_count)0 W: ^4 V. @# U9 L' W
- {
8 P& r J! y: O W: _% e - if (myUart_callBack). V3 E" P+ ^ U
- {
5 W7 \) j" c! X$ `( ? - myUart_callBack(USART_RX_BUF, USART_RX_count);
+ {2 H2 d; |0 P" z - }
) p7 V. O& v/ _. @ - }' J7 e7 d/ O6 T/ `: A q1 w9 d
- USART_RX_count = 0;/ S9 c# A0 u, E
- }
# H, W* W- L) e# W5 k k, ] - if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
( K0 g% Q D' ]6 r0 B - {& c7 o. K+ H; _2 g5 M
- USART_RX_BUF[USART_RX_count] = USART_ReceiveData(USART1); //读取接收到的数据,自动清除USART_IT_RXNE中断标志, |( V- {$ l! v3 x* v
- USART_RX_count ++;
" P+ I5 d) ], q - }
/ p6 W. \% f1 Q$ s( o/ d* |, y - }
' ~$ E! X! B- @7 b; B, y - 8 S0 @/ ?& F. ]
复制代码
/ ^" ?5 ?: Q$ ~7 Q2 I6 K |