趁着今天不是很忙,继续鼓捣下STM32F030 Nucleo64这块板子,这次我们来玩玩串口通信。咱们当码农电工的,往往在做项目调试代码的时候,想查看一些信息,但是呢,项目不需要LCD等显示模块,除了用软件仿真来查看外,串口也是一个经济实惠快捷的选择。
& f( \; ]) K9 H& o r
5 r$ s9 c `# U8 j. ^串口作为单片机和外部一个比较重要的通信接口,同时也是咱们码农调试代码的好工具,其重要性不言而喻了。STM32F030R8这颗芯片自带2路串口,咱们这次玩USART2,因为nucelo64这块板子板载虚拟串口,就是USART2。
- W3 v8 E$ n5 J. b4 G& K* [' _0 o& T2 L1 A) W3 f: m/ n
* B3 F6 ^0 B2 g串口的配置可以总结为以下几点:* d; e! k/ `2 [9 q9 S
(1)串口和GPIO的时钟使能2 ?8 n6 @. c- k
(2)串口复位0 G* ^: K' z( [, q7 G
(3)GPIO模式设置5 w' w3 S$ d1 T2 Y# |/ p" a! ?
(4)串口参数初始化, k1 l' O; M) |! Y4 A4 J" ^/ Y
(5)打开中断(也可以用查询方式,这里不讲)1 L2 Y& h# h9 v
(6)使能串口
& ^: z# x& S- z(7)既然开了中断,那么就要写串口中断服务函数
+ Z4 Q5 E3 \% @) S6 E; a' y
% k, `1 L% Y Y: i下面,我们开始简单介绍下完成上面步骤的几个库函数,可以打开stm32f0xx_usart.c和stm32f0xx_usart.h这两个文件查看。+ ~/ G7 o0 a& l* d3 `: m
(1)使能对应外设时钟
# J" @2 T) x& f' j, Q/ F( p1 y 相信这一点经过上一贴的描述,大家应该都可以完成,那么下面就直接贴代码了
9 k( _' C. O5 [1 P; J8 v6 P; J' Y+ n- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //使能USART2时钟! s$ o/ ~0 b. P0 i2 r( l
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
复制代码
1 u: ]5 q2 D \5 E9 E7 t(2)串口复位
8 I. X3 l* m q4 c 在外设初始化的时候,可以考虑让外设重新复位,每一个相关的寄存器恢复到默认值,其实我个人做项目的时候也没用到复位,也没发现啥问题,各位也可以尝试下
0 ^3 T; i+ g- Z* x- USART_DeInit(USART2); //复位串口2
复制代码 $ _1 z" U; e1 ~8 W/ S8 N
(3)GPIO模式配置
8 y; {2 R: z; T- M5 ]# M/ X) U 由于USART2是占用了PA2和PA3这两个IO,需要启动GPIO复用功能,采用GPIO_PinAFConfig这个函数来设置,可以参考STM32F030R8数据手册,如下图所示:# P) z3 W( f: y+ v
# B/ u5 z) i" _
8 t: a. ?6 x* T0 c. T7 `+ L具体代码如下:" V+ f5 v, J3 j8 Y: R% U
- /*
) p! N# m( r7 _* z, m0 t# k - USART2 GPIO Configuration 7 q" m; ~3 z$ R5 a( A9 A& N4 t
- PA2 ------> USART2_TX
1 m; o+ D7 S8 q6 t9 `. r+ _ - PA3 ------> USART2_RX 1 V5 b e" v7 i5 _* q- o
- */
; e5 T/ |: \: h6 z, T3 I' |1 n - GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_1);& J8 _8 P& t& u7 h8 w; Q
- GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1);
+ m5 ?6 H2 m8 D2 q: L) w0 e - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; //PA.2 PA.31 ^- c2 c. p. b% W9 D& X0 L
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+ d& ^' m# ]+ I; `( z& _. M - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
& _. O2 V8 ?% c8 T) k7 j1 V C - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
8 r1 S- J; `- P7 K' i - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
( _. p4 \! o6 z - GPIO_Init(GPIOA, &GPIO_InitStructure);
复制代码
+ L. S9 y/ W2 u(4)串口参数初始化
' o2 y0 A+ D6 \# y& N 我们可以打开库函数stm32f0xx_usart.c和stm32f0xx_usart.h这两个文件,串口的初始化是由void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct)这个函数来实现的。
; O; s% i& Y% ]# p5 k) \ 这个函数的第一个入口参数是指定初始化的串口标号,这里选择 USART2。! V* L6 [& U# G
第二个入口参数是一个 USART_InitTypeDef 类型的结构体指针,这个结构体指针的成员变量用来设置串口的一些参数。我们可以打开库函数看看:
( b; o* e6 n3 w- P! D) e
# S2 L0 w; W4 w: t8 a& q实现方式如下:6 T! A/ Y% g H! h: k
- //USART 初始化设置$ }4 G) R5 w" S2 B0 T
- USART_InitStructure.USART_BaudRate = bound; //设置波特率
) ~9 r) J& \' N# m3 R7 L - USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式
# @0 y4 f; n+ B$ H A7 p! u. F - USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位
8 v, U+ O: c% r7 A6 }# g - USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位9 r. y" k V+ s1 v
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制
. M. u- J0 j8 r1 r - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式/ {3 a9 F, {6 x6 }
- USART_Init(USART2, &USART_InitStructure);
复制代码 从上面的初始化格式可以看出初始化需要设置的参数为:波特率,字长,停止位,奇偶校验位,硬件数据流控制,模式(收,发) 。
- J U* V! p0 l4 i& y. J8 A! Y
" W" V, k6 D/ K) k" Z3 b4 f(5)打开中断5 {7 Q0 |' N9 W- p4 a
使能串口中断的函数是:$ d0 K' Y* X. s! ]- j) U2 K g
- USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//使能串口2接收中断
复制代码 千万不要忘记了还要配置中断通道、优先级等参数:- NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; h9 q$ |, V S$ ?7 ]
- NVIC_InitStructure.NVIC_IRQChannelPriority = 3;
" z2 }7 H. _+ @ `: \. k& B- p - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;& a, O2 r7 h# n, ~6 ?& f
- NVIC_Init(&NVIC_InitStructure);
复制代码 2 r+ C ?5 Y( {% T% v j
(6)使能串口
) y' a9 x7 q7 g8 p2 j- G/ S 这个最简单  ,一个库函数搞掂~~~* u; ]8 F3 ~1 {) L5 b8 K
- USART_Cmd(USART2, ENABLE); //使能串口2
复制代码
) y; E4 c: E" j6 c9 H(7)编写中断服务函数5 W [" a) b/ ~/ T
既然你打开了中断,那么中断响应之后,肯定得干些事情,这时候,就轮到中断服务函数出场了~~~% X5 n+ B& D9 f2 U
中断服务函数的名字不能随便定义,我们可以打开系统启动文件startup_stm32f030.s文件,在里面可以查看到这颗芯片所有外设的中断服务函数的名字
2 {5 C% K6 U! }, M# e9 p
' V6 }! q) Q7 K4 ~+ c- X2 A
本次例程要实现的功能是串口的接收和发送,中断服务函数代码如下:9 v2 L8 ]( v: v& M" ^6 L6 M
- void USART2_IRQHandler(void)
/ u, ^$ p9 q) O2 z2 a' \: e - {
% S! X) U. I2 M: V - u8 ch;
+ m9 F+ O" F( Y f -
n% H1 O; k( b( [ - if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET), t! J5 K: g8 ~+ {" O0 J4 R
- { 9 n! j! w% r+ x
- ch = USART_ReceiveData(USART2);8 k; S4 I: |( h' K( g
- printf("%c", ch); //将接受到的数据直接返回打印$ x! I8 L8 K, m6 ]" y
- }
6 f% h0 }0 [3 m -
2 \, _, m3 ?/ f( o! m) f+ u - }
复制代码 从上面的函数可以看到,这里用到了printf函数,具体的配置方法可以看看我之前发过的帖子,这里就不重复介绍了
% L9 q+ s% G! R! |! k
7 t4 t+ R; C5 u& c贴上工程代码:( U; M1 [- E% }* O
STM32F030_USART2.rar
(1.75 MB, 下载次数: 121)
|