写在前面3 j. q: ~! k: X4 U9 S
芯片型号:stm32f030c8t6
2 A; v# w# F E# b说明:便宜,用量大# v3 j( y* P+ b( I* @
要点说明:初始化、主函数调用串口接收callback、串口接收空闲中断,串口接收中断7 N% K) z' M2 u
这种API封装方式可以拓展到其他单片机,但需要注意单片机是否支持接收空闲中断
1 C. f& i1 m# @& P8 z D+ V本文注意介绍空闲中断的应用,这样就不用在定时器中计时来检测接收超时中断了
( Y/ V( ] G/ |8 _3 R7 n4 b" ~, H3 T5 K: m
一、应用
3 P- Z9 W! G* H& R1 P外部定义串口接收回调
% T+ o6 ]# g7 [7 }* o当串口数据接收完成后,在该回调中处理串口数据即可
7 c, q9 M/ b# @6 G, o9 c# Q; t- void Uart_recvCallBack(void *buf, int len)0 @ S" \4 U7 g
- {" J9 w6 A: a# @7 g! [
# ]7 a0 J' @" n! j1 |3 s; P- }
复制代码
! U8 r! W8 ]4 D$ p! D外部初始化串口
0 s8 Z! a8 w7 s7 f1 |- myUart_initialize(115200,# G' ]( i4 c2 i, O7 n: H
- USART_WordLength_8b,0 o4 ?3 u- |% C, h% y; r
- USART_StopBits_1,
& W+ B. X. q A$ t - USART_Parity_No,6 D8 V1 A- F6 J$ m* {# J% ~
- Uart_recvCallBack);
复制代码
6 E" V: j7 b6 N( J6 U0 n二、源码; b( _2 {3 j" F7 ]
myUart.h0 }5 i, ], o6 ?$ e9 x) S7 B q
- #ifndef __myUart_H0 V, r2 l6 p7 t/ c# }( n
- #define __myUart_H& M8 z, ? [& h( R
- ; U+ H# d. a' ~
- #include "stm32f0xx.h"
' e" d% s6 L+ O- o$ D ] - #include "stm32f0xx_usart.h". w- B) w, n; U6 @! a% s
- #include "stm32f0xx_gpio.h"- U& Z0 | u# O# R0 a& l4 o. H
- #include "stm32f0xx_rcc.h"
$ x+ a' b6 c$ @: y - #include "stm32f0xx_misc.h"6 `/ U! U% |+ @ N4 @3 T+ ?
- , i/ g5 Y. K/ Y
- #define USART_REC_LEN 200 //定义最大接收字节数
8 N% ]6 b6 i6 y8 h% O- F - O$ u8 S1 N7 \, }
- typedef void (*myUart_cb)(void *buf, int len);' m( \; W* O9 [
" d' C% @# R y. _: n- void myUart_initialize( uint32_t USART_BaudRate,
/ F r; w0 v X3 Y - uint32_t USART_WordLength,, ]' J* F z' ]) y- ^
- uint32_t USART_StopBits,# h8 k+ M. E( Q, o& `9 O) ]& y
- uint32_t USART_Parity,
; y! d* K' [% F$ e s - myUart_cb cb);
9 }' I4 e d- Q0 E. ] - void myUart_setBaudRate(uint32_t USART_BaudRate);. i) j. L! G( k2 u* f$ d
- void myUart_sendByte(uint8_t byte);
5 x7 x. [; s. z+ E% z' Z: a2 Y- z4 e3 R - void myUart_sendBytes(uint8_t *Buffer, uint32_t Length);. }/ S2 B% o( m
- uint8_t myUart_recvByte(void);
, W9 M( [% H' G+ _) Q# { - int fputc(int ch, FILE *f);
! X* C: d: Y! C5 q, H, D9 L - ( Q$ W6 I1 B( y5 q4 s0 ?
- #endif /* __UART_H */
" L! m1 v- m' f3 U" }* w
复制代码 5 Z+ j- ^$ y" g5 I
myUart.c
8 }" m0 t1 [) x- #include "myUart.h"% `: v; P- S" B$ h
- 5 A F3 ?# M' D! s! \ v( M9 s- S
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
; A: Z' u8 Y0 t - 0 _6 ?' _9 m. N+ H) t3 f
- uint8_t USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节. ~7 q$ o+ D; s- L
- uint16_t USART_RX_count = 0; //接收状态标记 + K- g8 j/ u2 x0 n2 @
- myUart_cb myUart_callBack;
9 J7 R e8 d; B/ |% u3 E - /* Private functions ---------------------------------------------------------*/& h# y8 p0 N4 y n8 E" B1 F
% y7 Z2 ]! w9 l( S- USART_InitTypeDef USART_InitStructure;
- L/ L9 Y5 A& D4 L* d
0 N: \# c. B9 Q! u; _" w5 N- void myUart_initialize( uint32_t USART_BaudRate,) H0 D( J9 b+ r. m [! C
- uint32_t USART_WordLength,
5 u1 |! u5 p( ~ - uint32_t USART_StopBits,$ g2 ]) O& T5 y5 H2 m) ]
- uint32_t USART_Parity,8 h b+ [. p v
- myUart_cb cb)
# n$ {" o6 S% |) n: s - {
$ p! z: z- v9 K$ Q
2 z% y/ M- s8 C& f. C8 A5 d8 Z- GPIO_InitTypeDef GPIO_InitStructure;. X# U& U5 l' k4 U/ w1 g2 @! b/ y6 ?
- NVIC_InitTypeDef NVIC_InitStructure;9 m! d" ?) S. m! d
- ! Q) @; W! x7 r' f: m
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE );
9 F8 u. x) h4 E5 q& F) n
: \" y8 l0 i2 i0 d" O; I" L6 J- GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1);
6 C6 ^ d3 ^+ o, p3 I6 b6 N& o/ v- U - GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1); : [5 Y/ U7 x4 O: b, p2 o" J4 v6 d! \
- /*
[4 d8 p3 b# K" z( b# N - * USART1_TX -> PA9 , USART1_RX -> PA107 p# [ Q6 ^2 R @& |
- */
# n) Z9 l9 Z4 ~6 W0 N. z2 | - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10; ! t2 }( m1 d7 c; M( b( c, }6 |
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; / O0 i% v' c& e. E m) f
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
o B' w' ? x: I) T# j - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
: ?- Z0 m+ ]0 E1 K# { - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
w% q3 N' O/ \% @1 Q- p - GPIO_Init(GPIOA, &GPIO_InitStructure); - d$ n! O3 j# I& s
0 s9 V" |2 Y1 g) a- h2 e7 ]2 x- //Usart1 NVIC 配置
! y+ \; M7 Z8 o- a. F( x" w- n5 A - NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;; A+ l. t! e+ k# c
- NVIC_InitStructure.NVIC_IRQChannelPriority=1 ;//抢占优先级3
4 t7 X" ^) ]+ J9 u! j( v3 l - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
$ h" y6 f! s# r# g& c - NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
7 F( I% o7 s1 k& }3 l - 1 z7 n9 B* X6 y
- USART_InitStructure.USART_BaudRate = USART_BaudRate;//设置串口波特率/ |, c% n% l$ d+ B& i( K5 J
- USART_InitStructure.USART_WordLength = USART_WordLength;//设置数据位- d/ p+ [/ |1 A: J* _
- USART_InitStructure.USART_StopBits = USART_StopBits;//设置停止位, j% B1 w/ @; w; h7 L
- USART_InitStructure.USART_Parity = USART_Parity;//设置效验位
+ ]0 Q, E. M# N$ { - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//设置流控制5 ?- d+ _) R7 _7 [# e' Y$ D
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//设置工作模式# n9 @1 b$ |! [, N4 W4 I2 N1 P
- USART_Init(USART1, &USART_InitStructure); //配置入结构体2 L( L' o$ k S1 M4 f5 K
- + N! ^& J- b8 U
- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
! _' p6 K3 P* e2 g - USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口接受超时中断
4 x6 t! U y. b7 f0 r" J - USART_Cmd(USART1, ENABLE);//使能串口1( q5 o+ I0 y5 C+ k e* b0 k, \
4 M7 b/ [) K# g6 h6 i- myUart_callBack = cb;; ~0 ]9 P+ C" K' J0 t# I& V2 v
- }
( I% F! U& I! g) [- I - void myUart_setBaudRate(uint32_t USART_BaudRate)
# @ g' T5 u( l7 r5 I, Z8 ? - {: J& _7 b( w, e) W% Z% L$ R
- USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);1 e+ j' W: S& T3 |2 }# j3 Y- z
- USART_ITConfig(USART1, USART_IT_IDLE, DISABLE);1 Q; @8 D* }! S# y; k" }
- USART_Cmd(USART1, DISABLE);' T/ a; V+ y0 R* F
$ i4 V+ N% p- t2 O& z- USART_InitStructure.USART_BaudRate = USART_BaudRate;//设置串口波特率& t) V* `, C& w8 N: t9 |$ {2 S
- USART_Init(USART1, &USART_InitStructure); //配置入结构体 @# G& y4 q! k; f7 d
0 j# o# {6 a* c' t$ W; l- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接收中断9 y4 ~; m: X6 d8 U# m, b, m8 [' a
- USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口接收超时中断
. f0 q( e, s; \ - USART_Cmd(USART1, ENABLE);//使能串口12 U+ Z, G& {2 f
- }
2 m+ H3 E: J6 w# J - void myUart_sendByte(uint8_t byte) //发送1字节数据
* j8 ]; D! x% N6 P! T' n2 s+ o - {- h+ _8 N$ |) y& f8 h1 e1 C' H
- while(!((USART1->ISR)&(1<<7)));
5 t0 c6 G& }: N* A }, e - USART1->TDR=byte; + o, @* g6 y+ e/ y$ V# z5 O
- } - v. D8 M6 ]* F5 N
- $ W w! s4 K( y, D4 {. |# {3 g- Z: Z
- void myUart_sendBytes(uint8_t *Buffer, uint32_t Length)
# p3 M4 N6 f* m1 R& u - {
2 c, u' T" j* f! P - while(Length != 0)
% u3 d4 i* k; O' A- o - {( E! }2 p4 ?9 {- g
- while(!((USART1->ISR)&(1<<7)));//等待发送完
/ ~. j3 \9 k- r2 l3 I6 ~0 v8 h - USART1->TDR= *Buffer;; @- |" M# [! l. L& @
- Buffer++;
" u% U) d2 i5 S3 f$ B8 Y - Length--;2 S+ s! v& j, r; s. \
- }
& {' M2 ~7 X9 i! h; D8 @& x5 v8 | - }
$ v7 z9 o! J$ e: Y1 X* j
2 e, Z+ H* q, L8 w0 Q& b- uint8_t myUart_recvByte(void)5 y/ D& P& { g) [& K- f$ O
- { ; t8 g7 @- [9 o+ f) m/ Q
- while(!(USART1->ISR & (1<<5)));//等待接收到数据
; r8 g o7 _) F. U% s; {8 L* P - return(USART1->RDR); //读出数据; k( A0 J* E8 v" r9 v
- }
! }- C0 M2 O* Q& L- A' a @% \ - - {& H6 h' c- e6 \" Y
! a; [( f8 C! P" @, b$ K3 m' s- PUTCHAR_PROTOTYPE
5 g9 b; F& `/ F8 l$ { - {5 V5 V$ _/ x8 L6 ~, H
- /* 将Printf内容发往串口 */* Y6 }1 M+ |8 R" R; @# k0 E
- USART_SendData(USART1,(uint8_t) ch);
S W. Z; [0 {6 c, Y! ~: ?! [ - while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)1 N4 a( d$ m! b8 T4 Q/ V
- {}
3 w( b) Q- m) g* m- T2 C5 T - ) \' N% I9 T6 m4 L2 x- X
- return (ch);+ q& ~ s X1 ?" O5 j; {
- }2 n4 }0 o i4 E4 e2 @( G8 v$ `+ W( m, B
1 D0 _. n; l2 K2 g1 _! c5 W- void USART1_IRQHandler(void) //串口1中断服务程序
' U; i' O9 f1 a7 N8 M - {; ^: _: T" a0 g2 L) [
- uint8_t Res;) Z4 O+ H9 ]& ?, l
( D; U3 U; F$ k1 S4 q6 }- if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
$ G3 p. @; W( ~& F" X+ X - { F0 g/ ]0 ^4 }' t" Q6 q9 X
- USART_ClearITPendingBit(USART1, USART_IT_IDLE);//USART_IT_IDLE需要手动清除. E7 Y4 k, C( H1 m! b. `
- if (USART_RX_count)
: f$ }' I% u# j" w9 q; ~# ] - {
4 a; ]& n7 ~* \( D! H - if (myUart_callBack)
( U" l. a: s2 F d: c$ \ - {
5 F( K( |/ n# z$ d - myUart_callBack(USART_RX_BUF, USART_RX_count);
! H! ` A2 @4 a9 e - }
2 X$ u/ U: N% K - }
0 C$ z+ ^9 x- \" T5 | - USART_RX_count = 0;9 \( B' G3 f* r
- }
, Y( l& s% x, A - if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
, o1 e0 m) m5 k0 [2 Y3 S - {8 I9 L |) P6 G. s8 g
- USART_RX_BUF[USART_RX_count] = USART_ReceiveData(USART1); //读取接收到的数据,自动清除USART_IT_RXNE中断标志' ?4 H2 a) s+ [7 x" b8 l; ]
- USART_RX_count ++;9 Q1 m U$ h' Y! U5 X2 p- S
- } ( T# D, j# B, A
- } ) G. A: W& `4 [" F) c6 B0 n
1 a$ q* S' B( X
复制代码
. ?' a& |+ g3 H1 \. C8 E |