写在前面/ O, }1 ?; @! Y0 n6 m9 ]
芯片型号:stm32f030c8t67 S8 k$ e2 q4 G/ B$ N1 ^
说明:便宜,用量大
2 ?7 O" j ?0 e1 o$ J% W4 b要点说明:初始化、主函数调用串口接收callback、串口接收空闲中断,串口接收中断
$ q0 B& P# O0 B" i1 |这种API封装方式可以拓展到其他单片机,但需要注意单片机是否支持接收空闲中断
9 P# g) f6 Z' L) {本文注意介绍空闲中断的应用,这样就不用在定时器中计时来检测接收超时中断了
- p" f8 p! f' u0 C9 ~2 ^' l; y8 _% h5 g H. m0 i9 P
一、应用
6 _2 z# _/ \$ u& t& T4 g+ }外部定义串口接收回调3 Y4 m$ e+ M; |9 w* j o
当串口数据接收完成后,在该回调中处理串口数据即可' T. M( f7 H6 x1 d
- void Uart_recvCallBack(void *buf, int len)* I' Q3 N. @( e' J
- {
% l3 @# [) k8 ` - 2 R- A8 n: u0 d
- }
复制代码
! f4 r; f8 ^. u; ? X外部初始化串口
* u+ S4 N z' S# ?0 L2 Y( c' V- myUart_initialize(115200,
: |0 [3 R; o+ |) D5 Q3 @0 F. a( Q - USART_WordLength_8b,
$ m3 h- w2 E6 D2 Z. \4 z; l - USART_StopBits_1,
: D9 y5 T' J+ S+ p: g - USART_Parity_No,
6 b# h F! f+ L1 R - Uart_recvCallBack);
复制代码 8 K3 r/ y8 G8 G* g! F
二、源码* j z9 A" _: }- n0 P+ \6 M
myUart.h2 j7 s4 @8 u% x9 ^6 O
- #ifndef __myUart_H
) _* v2 _+ K8 O - #define __myUart_H( [% a) n3 T; \3 `
' J! K* X0 W9 x( D# P- #include "stm32f0xx.h"
$ g/ O" l2 E2 Y. |- V1 [) K1 n$ I - #include "stm32f0xx_usart.h"/ o; A) h2 ^" `7 Z9 E3 k
- #include "stm32f0xx_gpio.h"+ _8 V6 x* e+ \/ ?
- #include "stm32f0xx_rcc.h": w2 H$ _! L( F- n+ {
- #include "stm32f0xx_misc.h"
; s( l4 B* M: G V, m; I* B
% a) l2 D0 e; h% i' B- #define USART_REC_LEN 200 //定义最大接收字节数
& N- R- `! Y1 s5 q" b; d - 1 r% @; D. Y4 B$ l% y$ _
- typedef void (*myUart_cb)(void *buf, int len);: ]2 d1 s3 t X+ Y4 E
- * \) J6 J3 ]- u2 I; F
- void myUart_initialize( uint32_t USART_BaudRate,
: r$ N- N0 t, y7 |* ?" j- F- X - uint32_t USART_WordLength,0 \: I* _, k6 v" ~# D
- uint32_t USART_StopBits,
- J$ f5 V n6 K& O, Z- \/ e - uint32_t USART_Parity,- N( ?9 i G' S3 n2 e6 q" i
- myUart_cb cb);
7 j. ]) a6 F6 H, ] - void myUart_setBaudRate(uint32_t USART_BaudRate);
' l5 R9 X' Y3 M5 p5 c* p# I - void myUart_sendByte(uint8_t byte);
$ \" C' a( L: ^ - void myUart_sendBytes(uint8_t *Buffer, uint32_t Length);
* c5 U: P# I5 j7 D - uint8_t myUart_recvByte(void);
2 l2 u' @+ A+ q. K0 {5 r! T8 m - int fputc(int ch, FILE *f);
& L2 `/ Z$ `1 v. @0 q/ G5 [4 i) Y - & r1 t0 ]: Q/ K) R8 c6 H3 m
- #endif /* __UART_H */
# _5 n9 ~0 h: E* V0 F7 z
复制代码 4 z: }. |, F: ?: ^. _0 U
myUart.c6 `0 P0 Q% u! I8 I
- #include "myUart.h"( @& ]7 `7 g6 r. S d
; J) z- x; s( X/ d+ C- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)3 O6 ^) k' k# d9 _! N1 O
/ t& n8 R, H6 J0 T0 E; U- uint8_t USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
$ d0 ^. Q5 _9 n6 a- O3 ^- H - uint16_t USART_RX_count = 0; //接收状态标记
) V; G' g: a H; n2 p* _ - myUart_cb myUart_callBack;
4 h n5 N/ W9 k5 C, m2 [ - /* Private functions ---------------------------------------------------------*/
5 t& l) d8 q& s5 i2 P4 d4 L) f3 P) n$ ^ - 6 J6 \$ e9 y% b
- USART_InitTypeDef USART_InitStructure;: _; a3 X* W, ~" o. U
- ! t. r+ t& E5 S0 \. z) j
- void myUart_initialize( uint32_t USART_BaudRate,# b$ E* G9 A9 V' x: g/ W! o
- uint32_t USART_WordLength,
& U$ H h( i( w" h8 p - uint32_t USART_StopBits,
- p8 O7 Q2 L' X8 M6 p3 H, D; ^ - uint32_t USART_Parity,4 R( T/ r3 W/ h8 n- V' R- q! ?
- myUart_cb cb)% ^6 C3 r% P" ]- F
- {
# P% S- m) _, P9 a
2 \: B W) s/ U# ]" W- GPIO_InitTypeDef GPIO_InitStructure;" o4 W/ y* a2 G. L: l$ X: L
- NVIC_InitTypeDef NVIC_InitStructure;
* D4 f. ]& \: u" H! E* C
; w9 K9 D5 R" U$ Q& V- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE );
" Q$ q& A. H( A - ( P2 G& c4 ?4 n$ u" f% q& W3 G$ {
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1);
3 ?5 u7 e4 h" p, I - GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1);
6 F! H3 K8 J0 f% w+ X4 }# a - /*! P; q( V7 ?+ j4 g1 s$ `
- * USART1_TX -> PA9 , USART1_RX -> PA10
; p1 l* _ E/ p7 A h. I& U( r - */
. ^8 P1 t6 x# R/ g( B* }& w! Q) s - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
( \( T+ g" b( R( P# a - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; [9 [5 x% ]" `& f3 V. z: ~3 O
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
* S" j1 \1 r5 p2 k' T8 H - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;- Y' T# L c8 J
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
* }( L6 z7 ^$ b s& T: | - GPIO_Init(GPIOA, &GPIO_InitStructure);
: I& {. p; }) f# \
7 H( U2 w( V3 |& G- d- //Usart1 NVIC 配置
2 j% o' Y6 O) H - NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;& U+ |7 \& Y1 p/ `$ R9 e
- NVIC_InitStructure.NVIC_IRQChannelPriority=1 ;//抢占优先级3
$ ?9 O6 m7 o! @ - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
- _# D5 r: `0 v: G5 z - NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
1 X7 { d! Q/ \1 Q, G; C* R
5 `, i/ l6 }2 b; E- USART_InitStructure.USART_BaudRate = USART_BaudRate;//设置串口波特率
3 f+ G. ^2 b; W! f - USART_InitStructure.USART_WordLength = USART_WordLength;//设置数据位( d+ v0 F/ F. \0 C& ^# M7 m
- USART_InitStructure.USART_StopBits = USART_StopBits;//设置停止位6 E8 h6 ~) ~% B z8 F% ~
- USART_InitStructure.USART_Parity = USART_Parity;//设置效验位
4 I1 N7 h% e7 p& t* Z: R! ?8 m - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//设置流控制
- y) l1 e- i( Y8 v3 c* P - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//设置工作模式
" |) S+ b5 W$ k& `) | - USART_Init(USART1, &USART_InitStructure); //配置入结构体8 V6 y* l S4 W; t1 n; S
- # i) u1 i/ G* z* ^
- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
( x+ h* y3 W! J7 T. S - USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口接受超时中断
) [, _ @9 C4 e7 Y$ S. N - USART_Cmd(USART1, ENABLE);//使能串口1, u m* q' a7 f
$ J/ B6 K* ~" v, Y! R6 d- myUart_callBack = cb;
& @, Y+ R e3 W# B$ Z! D - } 1 ?3 R3 _2 h! P; V" q
- void myUart_setBaudRate(uint32_t USART_BaudRate)
3 W: `. {+ h6 j# f6 X1 N - {$ d" [$ D9 n0 E2 K
- USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);! _0 @, v7 x% w; M" l% A8 z, J. Q
- USART_ITConfig(USART1, USART_IT_IDLE, DISABLE);! A) V1 s3 } \' y
- USART_Cmd(USART1, DISABLE);! k; |1 z" r# s! O3 g
- - K/ t5 s9 \% ?. K; Q
- USART_InitStructure.USART_BaudRate = USART_BaudRate;//设置串口波特率
/ ?. |- T; y5 G - USART_Init(USART1, &USART_InitStructure); //配置入结构体( ?# f5 k; m3 v) ~, W
h5 a l' y: l' _- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接收中断
! d- b+ \% S* `# g9 g - USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口接收超时中断
, W8 F# i( k' N: d# x# ^ f _ - USART_Cmd(USART1, ENABLE);//使能串口1
( _. ]% l4 n& g% p% |+ M - }
/ n q& F- e m: h& H# C- M3 s - void myUart_sendByte(uint8_t byte) //发送1字节数据# q/ R3 ?7 \9 { q
- {. U# ~: }( W# F5 P8 s
- while(!((USART1->ISR)&(1<<7)));+ G2 s u z3 n7 p# i) N' r r
- USART1->TDR=byte;
2 N+ u# n$ U. {: c - }
+ {1 B# C% F6 Y; {/ p6 k
6 m- k+ }! E2 A6 ?. X5 g2 x: N- void myUart_sendBytes(uint8_t *Buffer, uint32_t Length)
$ b! p- u1 C' M2 N+ T) \ - {
$ L) g5 C" ]$ Y8 ^ - while(Length != 0)
8 V: s( d" r, L5 F. p - {
E. `) u0 Q+ X% L$ h, K1 [ C - while(!((USART1->ISR)&(1<<7)));//等待发送完
& x* S' S; j. [/ E+ a7 ? - USART1->TDR= *Buffer;- [* Z# F. g- {3 _0 `
- Buffer++;
0 t6 S6 g9 {% I - Length--;% m+ L' t3 _& @# c- Z
- }
9 s( P) q4 {3 x% {% U& ]; e - }9 X% _' i2 c- W9 d& H$ |
( [6 z5 t4 a* v1 O4 {7 O" L- uint8_t myUart_recvByte(void)$ S" F3 p- d2 K& {3 _+ [
- { * L& ]/ |( y( Q% h, M
- while(!(USART1->ISR & (1<<5)));//等待接收到数据
& Q+ I6 [9 A& p1 a - return(USART1->RDR); //读出数据* D( ~- G- G9 n6 t$ z
- }9 ~' Q0 q/ d, i/ v' x } Z
" [) z6 ~ [! }. L m& j
. k4 e, q2 L8 f7 c; o& V- PUTCHAR_PROTOTYPE
; @( d3 {0 _/ J5 h+ J w - {
0 e3 {" g0 d% P: p: H, z, x- t2 m - /* 将Printf内容发往串口 */3 T' s+ X/ k W
- USART_SendData(USART1,(uint8_t) ch);
- A- x9 P1 n" i - while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET), K: y1 W: ~. w- o( q) e
- {}" _. K" s2 u6 T- A3 d1 i& M
3 R8 C! Y$ A9 {( @, h3 i* H- return (ch);
5 d9 v: R8 D6 B; P e - }
- [. s M! P. V* C% T# F
( d# H* S" M9 e7 f, \, ^" l- void USART1_IRQHandler(void) //串口1中断服务程序
& [$ d0 _4 O, W - {9 i4 e8 g& B1 H
- uint8_t Res;. O4 k* h* r$ f$ n/ H& L7 ?; u$ w& ~ {
- # b/ ^/ \" `& W" \- ~8 ]+ ?; e
- if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
$ v; \3 ]+ ?& l1 I8 |2 Y$ W/ Y6 e - {% g' J' Y2 z2 m. [8 H6 w3 c
- USART_ClearITPendingBit(USART1, USART_IT_IDLE);//USART_IT_IDLE需要手动清除
t5 g" I# }: B& T7 k' q; T - if (USART_RX_count)$ ^ c! O+ i, {6 S) A1 S3 g
- {
7 J( E, J& _. @9 O" k; M - if (myUart_callBack)4 W! K* a% b& S: p
- {
$ K9 ~3 q& x0 i$ |. M6 U; Q - myUart_callBack(USART_RX_BUF, USART_RX_count);( v1 K' C+ O* K3 N- ]; b0 I
- }
/ F" Y7 T( X/ W: h. I4 p - }+ J8 k/ {4 b, Z/ I2 J# o8 C
- USART_RX_count = 0;; |3 G" d7 t! G3 p6 V. u. F
- }' y0 `/ S7 d I" ?3 a
- if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
3 E2 l' d9 Y/ b. ` - {
' X3 [7 [1 I z) Y8 S8 p* ^ - USART_RX_BUF[USART_RX_count] = USART_ReceiveData(USART1); //读取接收到的数据,自动清除USART_IT_RXNE中断标志
) l" S7 L& h' u4 W+ @8 d9 @5 p+ [3 V - USART_RX_count ++;
+ q. E! R4 C$ l! D2 X @ - } * {- w Z4 M) o
- }
3 N* Q- w! W: @2 D
4 ]+ A/ ?/ C+ [$ C" [7 z
复制代码
+ ^5 g; A; J, j) J |