第1课:点亮你的第一个LED灯
2 W: V, D6 y: n i) e# s# b* Y原理分析:& f$ o/ h5 c, t4 D6 h3 B
大家之前学习过51单片机,也使用过IO口。与ARM CORTEX M0的IO口配置有点区别,51不需要设置IO口为输入或者输出,而CORTEX M0的IO口有多种状态需要设置,那么下面我们一一介绍:) ~* H* ]# t! E/ q
首先看看IO口的模式,如下寄存器说明,IO口可以配置为4种模式:输入模式,输出模式,复用模式,模拟通道模式。由于stm32f051系列多数的IO关键复用了其外设功能,比如I2C,SPI,UART等,此时就可以设置IO口为复用模式。模拟通道则作为AD,DA的时候使用:) h! v6 Z) A1 ?( p8 o. u @. k" S

% q0 V/ t8 W. [6 o/ b+ d2 i1 N如果大家使用库函数编程的时候,可以在 stm32f0xx_gpio.h文件中找到设置IO模式的结构体GPIOMode_TypeDef :( r9 y( U; P" ^; w- E2 `% E! D p8 M
6 W" Z9 L" h: f0 E
下面来介绍下输入和输出模式,其中输出模式如下图所示,分为推挽输出和开漏输出。这时候大家就要回忆下模电的课程了。
# o$ l; E& i5 M( p0 O+ v & ]2 }! E: V, o* ]( f5 t
我使用下面一个等效图说明一下推挽输出和开漏输出。图所示:U1是输出锁存器,执行GPIO管脚写操作时,在写脉冲(Write Pulse)的作用下,数据被锁存到Q和/Q。T1和T2构成CMOS反相器,T1导通或T2导通时都表现出较低的阻抗,但T1和T2不会同时导通或同时关闭,最后形成的是推挽输出。
' I l3 h2 Z: ~8 F2 u$ D( l如图1.3所示,为GPIO管脚在开漏输出模式下的等效结构示意图。开漏输出和推挽输出相比结构基本相同,但只有下拉晶体管T1而没有上拉晶体管。同样,T1实际上也是多组可编程选择的晶体管。开漏输出的实际作用就是一个开关,输出“1”时断开、输出“0”时连接到GND(有一定内阻)。
3 S" M& S0 e/ v) o' s8 |
+ I( w5 t4 k5 p5 R* k
0 {9 R s: ]9 t同样大家使用库函数编程的时候,可以在 stm32f0xx_gpio.h文件中找到设置输出模式的结构体GPIOOType_TypeDef
( W# i2 J4 E2 v' V* o3 s& X
& m7 G6 f3 a- H6 M同时我们可以设置IO端口输出的速度,在库函数中通过结构体来解决:
% Q% ?( |0 F* s% | / e+ r/ i: D9 s9 T# y
输入的模式可以分为上拉和下拉模式,这就比较简单了,寄存器的设置如下图:
- \7 l, O, @* ^- P( ^8 l; M3 {( H ) B0 I4 F Y, z0 H+ _2 f' b1 M
同样大家使用库函数编程的时候,可以在 stm32f0xx_gpio.h文件中找到设置输入模式的结构体GPIOOPuPd_TypeDef
* s$ f$ v6 r7 v. e1 k- b( p8 | 0 E Y" _/ {% L3 A
上面介绍完了STM32F051的IO端口有哪几种模式,现在就来点亮一个LED灯,学过51的同学可以回忆下,51是通过设置IO口输出0或者1来驱动LED灯的亮灭。在STM32F051中,我们通过设置IO端口为输出来点亮LED等。
* ?/ g5 y" a# G1 H硬件准备:! @' T: o! \ v$ [ i U

# [) G+ C6 I: J' L: w
( i f. E; P7 w2 I+ w3 w如上图所示: 青风STM32F051开发板上,通过管脚PA11和管脚PA12连接2个LED灯,我们下面的任务首先来点亮它。
. {- ?' N1 W" \' i7 v软件准备:
! f% X: X2 r: k; y按照第一章的介绍首先建立一个工程项目,采用库函数来在驱动IO口首先要添加几个驱动库,如下图所示:2 A) I" d. N2 ~1 u5 D8 B( Y
$ s0 j# v. L/ }4 O" D
上图红色框框中的几个文件都是ST官方给我们编好的库函数。那边用户在使用中,只需要编写led.c 驱动文件和main.c主函数就OK,整个工程项目大家如果加入分层的思想那么就对之后的移植非常有利。打个比方:底层和应用程隔离。底层驱动和应用层无关,main.c使用的函数在led.c驱动中已经些好,这些才和硬件有关,这是需要移植到不同硬件时,main主函数是可以不做任何修改的,只需要修改和底层相关的led.c驱动。7 _( g+ _' s* \0 }" V, c) T+ w1 F3 |
下面来分析下led .c的驱动编写:* ^5 O; c- k! T3 q& ?

& ~+ O& c! s& F) B上面的函数中GPIO_ResetBits函数和GPIO_SetBits函数在stm32f0xx_gpio.c驱动文件中所定义了。分别表示复位和置位相关IO管脚。
+ c$ S, W7 F7 H" Y- C那么主函数的编写就比较简单了,我们需要调用下面2个头文件,才能够直接使用我们定义的子函数。如下使用LED_Open()函数就能够点亮一个LED灯了,是不是很简单。) J+ l2 P2 w! Y8 T3 A; B: z
. z8 y z6 w L. G
那么加入一个小的延迟delay函数和打开与关闭LED子函数相结合,就可以实现LED闪烁的功能了,函数如下所示:
6 A8 Q7 S& R0 x; b' ? I
. O) Y m! z/ N( }下载到青风STM32F051开发板上运行后的效果如下图所示:( c+ z/ j! O1 Z r
( M" \; x4 l+ o$ q
如图所示,上方的用户led灯不停闪烁。6 N9 W3 q0 v U
|