写在前面( P7 L& k' H) z$ C
芯片型号:stm32f030c8t6
5 B; b4 A4 o5 k0 M$ y* a8 e( \说明:便宜,用量大
3 x/ r1 t7 D+ d) _* f要点说明:初始化、主函数调用串口接收callback、串口接收空闲中断,串口接收中断
- @# M0 r4 L1 G" R( N4 a这种API封装方式可以拓展到其他单片机,但需要注意单片机是否支持接收空闲中断( d" f7 @7 d0 O# |
本文注意介绍空闲中断的应用,这样就不用在定时器中计时来检测接收超时中断了
5 V! _$ |: J" v7 D; A8 g3 R/ |1 t8 R+ J1 u3 Y1 z
一、应用
! P9 W# M! [, r外部定义串口接收回调6 Q2 ]% C5 ?; H8 J) p
当串口数据接收完成后,在该回调中处理串口数据即可5 Y$ L& G7 }$ L8 ?
- void Uart_recvCallBack(void *buf, int len)
) m) v$ m/ i4 K0 [( @ - {1 d2 ?7 A* _. F- ]/ g o
- ; \$ [; V& W( T' q. V' j& g. [, r
- }
复制代码
0 e4 E% w8 I7 V3 f' A, W A外部初始化串口- l+ z' p( c2 s+ m* R3 w5 r4 h
- myUart_initialize(115200,
! H" S" }3 r. a$ a5 D - USART_WordLength_8b,
8 D! G% W+ M& E i( f. u) ? - USART_StopBits_1,
& F7 D7 p; A! K4 n - USART_Parity_No,4 [: r# O) x! |. X
- Uart_recvCallBack);
复制代码 2 Y/ d* `% b% F$ O. k
二、源码7 v7 s2 }; C8 l' P4 _/ S
myUart.h5 d$ v4 n( X9 |
- #ifndef __myUart_H
6 O" E. a/ k% [# c; O/ T - #define __myUart_H
1 |: q. N8 n! U7 Y* ^) _3 p - $ s2 V( C7 Y. Y9 ~
- #include "stm32f0xx.h"7 w6 K) E; v$ e) d! w( T8 I
- #include "stm32f0xx_usart.h"
4 U! K8 Q. q- D! r - #include "stm32f0xx_gpio.h"
) P! b: t. C' Y# ?+ P4 @ c - #include "stm32f0xx_rcc.h"
# J# q" R9 `+ q' b8 r2 y0 l9 A - #include "stm32f0xx_misc.h"
0 h# g! J& d% f/ _( S
$ m) r }0 T( A: w! o- #define USART_REC_LEN 200 //定义最大接收字节数
* [7 t; C7 ?: X( R
8 Y# V7 R* ?7 }4 G6 d- typedef void (*myUart_cb)(void *buf, int len);
6 G1 a. i% D3 r0 ?
8 B3 f7 p0 h; W# C- void myUart_initialize( uint32_t USART_BaudRate,* v% `! }- V/ e: f8 U$ ^: D& {
- uint32_t USART_WordLength,
" s6 g4 { M$ e- y& g' F' P - uint32_t USART_StopBits,/ B( Z8 \7 E- A3 P, q
- uint32_t USART_Parity,
; I" y9 M9 `' O* r1 t+ O - myUart_cb cb);9 P& g: }: n o$ M7 k
- void myUart_setBaudRate(uint32_t USART_BaudRate);) L, s% e5 l! B. N, G. M1 Q6 ?
- void myUart_sendByte(uint8_t byte);
' y! j1 T" D4 H- V1 u- |" \, c0 l0 t - void myUart_sendBytes(uint8_t *Buffer, uint32_t Length);
4 O/ M& o4 a# L* n - uint8_t myUart_recvByte(void);. N" W. @8 U( ^" R/ X
- int fputc(int ch, FILE *f);$ K% k5 g/ S: a/ z+ c
- 2 g1 I' F# w% P2 s6 L0 P
- #endif /* __UART_H */' \6 f& c# ]$ _) F1 g
复制代码 . B9 C! I1 @& r6 v2 {/ a) y
myUart.c1 h# D8 m t" O- r
- #include "myUart.h"
. V. V5 E0 T8 G) J/ m( E - + B1 R- \/ t( V8 q
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)# E* m; @2 R: q
- 0 p. ?: c4 F9 Q8 ^2 p
- uint8_t USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.: ~- k' J. c4 d# k) X
- uint16_t USART_RX_count = 0; //接收状态标记 6 g& |; I. J3 q: d
- myUart_cb myUart_callBack;
; K) ^/ |# h* p! d1 ^! F1 ? - /* Private functions ---------------------------------------------------------*/; Y8 }' q$ g+ C$ }' }& n
- 7 ^* s4 q: g- }- H+ c
- USART_InitTypeDef USART_InitStructure;
5 T, o8 Z; }% N" i" _- S! @+ | - 4 Y4 w. |$ g; [' A' @
- void myUart_initialize( uint32_t USART_BaudRate,
0 Z0 {* ]" a) b. B) S% ~' F - uint32_t USART_WordLength,
/ M4 u9 d4 q) R1 u3 q0 Z - uint32_t USART_StopBits,
$ ~! l% j! `( _# D. Q - uint32_t USART_Parity,1 }& M( o8 b* q3 ~
- myUart_cb cb)! @9 |! k! }. @( c! V/ |
- {
$ `/ w: R" B R% p - ; M* x& E/ E- d3 z# ]
- GPIO_InitTypeDef GPIO_InitStructure;1 W) ]0 f; }5 I" F& k6 a
- NVIC_InitTypeDef NVIC_InitStructure;+ M' \! ?$ S- c4 J" {* N) `
. v+ o3 i! q7 l Z8 y- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE );1 K9 ~ v( @5 H4 i2 a' ~% H5 d! [
- : E5 Z- [% m% h! G
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1);
1 Y- S& d K* f" M - GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1);
! k6 F2 A7 {8 A, M! P - /*
( J) c5 R$ [, A0 n2 X7 |) c - * USART1_TX -> PA9 , USART1_RX -> PA10$ H2 P# I. v4 I; l0 v- h7 O
- */
, _, ?5 J+ Q: O7 Z8 m' E8 Q - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
! n6 T3 ~9 \9 }# s% g8 `2 s - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 7 K J- x5 D7 K4 N+ I
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
6 E# _0 t# \" e) Z7 g - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
. i0 J( d4 t# ]9 I1 f' F7 t y- h - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; & h+ @# }( u8 h! u) X6 ?
- GPIO_Init(GPIOA, &GPIO_InitStructure); # h- D+ }% ]3 f' Y4 G
- . I' G( }7 ?2 K' y. N. }* v
- //Usart1 NVIC 配置8 ?) J# \5 N, z$ D* {# t
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
4 Q# s5 s8 m1 V- ^ - NVIC_InitStructure.NVIC_IRQChannelPriority=1 ;//抢占优先级3
/ X U) k: {* ?% i' E4 T9 A - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能, A2 |1 s" g2 p' B/ {
- NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
, k1 F9 `6 @7 @/ [5 R4 _- T9 I7 s
( l" I& X' c, A" X( H- USART_InitStructure.USART_BaudRate = USART_BaudRate;//设置串口波特率
( L- {9 _: K( T$ n% h9 X - USART_InitStructure.USART_WordLength = USART_WordLength;//设置数据位* s; i, v& _' M( ?, u
- USART_InitStructure.USART_StopBits = USART_StopBits;//设置停止位
: E. Y& v5 C. o! ]( z x! A6 U - USART_InitStructure.USART_Parity = USART_Parity;//设置效验位9 N Z$ x7 D; r2 S
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//设置流控制
3 A; w6 T2 b [2 [ - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//设置工作模式7 o, e8 x1 o! ]1 ?' u) @) d! C7 f% B
- USART_Init(USART1, &USART_InitStructure); //配置入结构体
/ A% M5 `6 F6 S; S) L
) h Y, K- o+ C( W: t1 t- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
$ L$ E* f+ \6 B+ w" _ - USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口接受超时中断
: X' V& k* v1 ~, l7 Q - USART_Cmd(USART1, ENABLE);//使能串口1
. G! _1 x6 v V* F5 A - + y5 |' ^* ~" g5 j! Y }0 F
- myUart_callBack = cb;- r8 G' ?& T% ^& o
- }
. G: C: R" x$ ]& h - void myUart_setBaudRate(uint32_t USART_BaudRate)
) K" N1 Z k, V$ Y+ W& g3 S { - {
( d9 ?6 K0 S6 H: r+ B) |1 g7 G - USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
* _5 ~) [! A1 w - USART_ITConfig(USART1, USART_IT_IDLE, DISABLE);
) \- \! H) l6 l" X - USART_Cmd(USART1, DISABLE);
& U2 H4 e# _6 k2 K+ \* m; g* Q" z
% c' x, p4 D, ^& W3 o" {5 p- USART_InitStructure.USART_BaudRate = USART_BaudRate;//设置串口波特率$ y& i9 |- B7 B
- USART_Init(USART1, &USART_InitStructure); //配置入结构体0 s# l1 u4 ]4 }0 {" \5 ]' d- r
2 m$ J' y* Y d% R- o3 u- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接收中断2 R6 O7 P& ?8 A3 [! Y
- USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口接收超时中断
0 q& q+ n6 j) I! {$ ~8 y - USART_Cmd(USART1, ENABLE);//使能串口1
1 p; R: Z, y; q) @- K* D8 B3 y - }4 L8 p9 J$ Q- G: r
- void myUart_sendByte(uint8_t byte) //发送1字节数据
+ D+ X. G0 i: `! D- z' a# b - { T5 Q! Q& B9 u! s D) h$ P X, V
- while(!((USART1->ISR)&(1<<7)));9 `: Y" D! s6 J) z9 c
- USART1->TDR=byte; / H$ p. G$ z+ l
- }
7 F* @$ M, A" ^, @, Z
. i7 S" ?1 ]# p# r- void myUart_sendBytes(uint8_t *Buffer, uint32_t Length)* E, _% E& e1 H. M( c$ W5 m
- {( ~& J1 K! m3 u3 m0 e) \
- while(Length != 0)
! ]5 t' g1 x$ u. H ~6 E - {9 M+ N1 L- Y% G+ P" a' o, w& x: f
- while(!((USART1->ISR)&(1<<7)));//等待发送完2 F" n/ }9 _/ n) [! q8 {; R
- USART1->TDR= *Buffer;. v; Z& \( L- t7 ~# f
- Buffer++;
- ]+ Y( `/ k2 Y3 n# u- e- Z8 r( ? - Length--;
: S) ~( f, R |) O5 T - }
' L! {. e6 g$ O% K0 _" q - }
/ _. o! i: |2 Y - 8 ?2 n2 [4 @9 p4 j g8 e# m* [
- uint8_t myUart_recvByte(void); g; H) p8 x5 ~( v
- { 9 V7 V0 J1 E; s, x1 P$ {
- while(!(USART1->ISR & (1<<5)));//等待接收到数据- Q0 g# Z& c$ l9 a0 V" z
- return(USART1->RDR); //读出数据4 Z. t F: c# j- L% U
- }
# r7 \! F( B2 N7 }& q - 4 z+ c# G% j* W
- / w: h% K/ {3 M" C% Y k
- PUTCHAR_PROTOTYPE ! |. ]. Y2 S) T- ]% P; A
- {' L; u) B. K, O( M7 \" Q* V
- /* 将Printf内容发往串口 */& G a# z- k1 l* O) ]% A; ^
- USART_SendData(USART1,(uint8_t) ch);8 M" W- i. \, r2 i% c+ D2 P
- while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)0 n+ i$ i: v! n4 V. d( [ ^1 }0 T
- {}. G# E5 X3 U& _" t: u: a2 T5 M; V w
( \* }) M8 `+ B6 |% t3 F- return (ch);- A1 V& r. I- M; Y6 U8 s
- }
; b) {9 M/ c/ a5 g4 E - $ t6 ^5 W! Q5 `. `7 i4 H8 f
- void USART1_IRQHandler(void) //串口1中断服务程序, u% }- L5 r* i V) c
- {: N- {1 \+ {! Q8 J
- uint8_t Res;# Y! s y8 m4 t0 B) x% m
- " _5 V) g: [6 m$ x3 M. s; s. b
- if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)# M8 e Y6 f7 f; H+ Q
- {% d, ]: N5 q, h9 f$ ?; o/ w: x0 B, }
- USART_ClearITPendingBit(USART1, USART_IT_IDLE);//USART_IT_IDLE需要手动清除! h: F- M, r4 @. ^( J
- if (USART_RX_count)
( p* `- d& G X2 G7 ] - {
- }# E0 ?, D& C C - if (myUart_callBack)' n1 j3 m+ e/ L& v
- {. t) q* D: g6 q
- myUart_callBack(USART_RX_BUF, USART_RX_count);
- q$ u# x0 g! U: u - } F) s4 k6 K1 @0 u+ R$ y) v
- }; y& ~ B7 ]/ U( e' _ S
- USART_RX_count = 0;
1 V- \# U3 i1 k3 Q; r - }
; t# @: j4 F7 A8 `, L - if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断+ r2 z, L( h9 e, Q5 E
- {
! f( }; v9 f) y* V8 l - USART_RX_BUF[USART_RX_count] = USART_ReceiveData(USART1); //读取接收到的数据,自动清除USART_IT_RXNE中断标志1 l2 e1 C! L5 b/ g% q( o
- USART_RX_count ++;! ~/ o* \; O3 u$ i' Z
- }
+ s2 B9 o* N8 ]. h - }
" A+ R6 L3 `' a: C# M
0 O5 B9 n5 F' n
复制代码
% E- L8 m6 }, k: ]8 w" x# q# Y |