有朋友问到此系列的更新相关的情况,在此我简要说明一下。本STM32系列教程的更新,是楼主在利用工作之余的私人时间,同时在保证成帖质量的基础上,平均一周更新1-2篇。码字不易,还望各路朋友多多包涵。如有需要交流,可以在下方留言板骚扰我哦~或者直接私信楼主。在此,谢谢各位小伙伴们一直以来的关注和捧场。你所需要的,就是我所追求的。
PS:上周由于开发板的问题,耽误了帖子的更新。于是楼主又去某宝淘了一块开发板。以后所有的程序,均在这块开发板上执行。
-------------------------------------------------------------------------------------------------------
在上一讲中,我们学习了MDK的安装以及破解。这一讲中,我们就开始认认真真的谈一谈,STM32可爱的GPIO口。
本文中,通过对点亮一个LED灯的操作,我们来讲解一下,如何操作GPIO口。就像学各类软件编程的同学们言必谈HelloWorld一样,学单片机的最基本操作就是点灯了。这也是操作一款单片机最最基础的任务。而由于STM32的强大的功能,和芯片复杂的内部结构。对它的GPIO口的操作,相对于51单片机的IO口来说,使用起来要稍微繁琐了那么一点。
本节当中,通过操作寄存器的方式,来操作STM32的GPIO口。从而实现点亮LED灯的操作。在下一讲当中,再介绍如何使用库函数来操作GPIO口。
既然是寄存器法点亮LED灯,那么就不得不说到,和点亮LED灯相关的寄存器了。在这之前,我们先上开发板的电路原理图。
由电路原理图我们可以看出,开发板上使用的是一个RGB全彩LED灯,具有红色,绿色,和蓝色三原色。也就是说这个LED灯内部具有三个不同颜色的LED灯,分别为红绿蓝,并分别接在PB5,PB0,PB1这三个GPIO口上。并且要想使他们发光,这三个GPIO口都要输出低电平才OK。
那么,要想使这三个GPIO口能够输出低电平或者是高电平。需要哪些步骤呢?
(1)打开这些GPIO口所对应端口的时钟;
(2)配置PB5,PB0,PB1这三个GPIO口的工作模式;
(3)令PB5,PB0,PB1这三个GPIO口输出高低电平以熄灭或点亮对应的LED发光管。
首先对第(1)步进行说明。
经过对原理图的分析,我们可以看出PB5,PB0,PB1这三个GPIO口是我们需要使用的三个IO口,而他们又都挂在APB2总线上,如图。
因此我们第一步首先要把GPIOB端口的时钟使能。通过查找微控制器参考手册。找到和GPIOB端口相关的寄存器RCC_APB2ENR,如图所示。通过查找我们发现,这个寄存器中的第三位为GPIOB端口的使能位。
再往下查对寄存器RCC_APB2ENR第三位的说明,可以得知,此位为0的时候,端口B的时钟关闭,此位设置成1的时候,表示打开IO端口B的时钟。
那么我们想使用这个端口的三个引脚PB5,PB0,PB1,就先要把端口B的时钟打开。因此程序如下:
RCC->APB2ENR |= (1<<3); //令GPIOB端口时钟使能
其次对第(2)步进行分析。
在使能过GPIOB端口的时钟之后,接下来我们就要配置PB5,PB0,PB1这三个引脚的工作模式了。由于这三个引脚是用来点亮LED发光管的,因此要设置成推挽输出的模式;同时将其输出的最大频率设置为50MHz。
通过查STM32F10x微控制器参考手册我们得知,配置GPIO口工作模式和两个寄存器相关。哪两个呢?一个叫做GPIOx_CRL,另一个叫做GPIOx_CRH。(其中x=A,B,C....)这两个寄存器中的L表示低,H表示高。因此顾名思义,GPIOx_CRL这个寄存器管的是0~7这底八个端口的配置,而GPIOx_CRH这个寄存器管的是8~15这个高八个端口的配置。
由于PB5,PB0,PB1这三个引脚都属于GPIOB_CRL寄存器的配置范畴,因此我们只需要对GPIOB_CRL这个寄存器进行相关配置就好。通过查微控制器参考手册,我们发现我们应该分别对GPIOB_CRL的0~3位(PB0)、4~7位(PB1)、20~23位(PB5)进行配置。如下图所示。
同时,通过对其对应位的说明,如要将PB5,PB0,PB1配置成推挽输出,50MHz的模式,应该将其对应的4位写入0011(即0x03)即可。
因此写出程序如下:
//初始化PB0 PB1 PB5为推挽输出,输出频率最大为50MHz
//先清零,再赋值。以下三行为将对应位清零操作
GPIOB->CRL &= ~( 0x0F<< (4*0));
GPIOB->CRL &= ~( 0x0F<< (4*1));
GPIOB->CRL &= ~( 0x0F<< (4*5));
//以下三行分别将PB0 PB1 PB5,设置为推挽输出50MHz
GPIOB->CRL |= (3<<4*0);
GPIOB->CRL |= (3<<4*1);
GPIOB->CRL |= (3<<4*5);
最后对第(3)步进行分析。
通过原理图,我们可以看出。要想使这三个LED灯发光,那么我们需要让PB5,PB0,PB1这三个引脚输出一个低电平信号。通过查微控制器参考手册,我们可以选择使用端口输出数据寄存器(GPIOx_ODR) (x=A..E)来对这三个引脚输出高低电平进行控制。
对于GPIOB_ODR的用法就是,将对应的位写0,其对应的管脚输出低电平信号。反之,输出高电平信号。因此要想将红绿蓝三个LED灯依次点亮,那么程序如下:
While(1)
{
GPIOB->ODR &= ~(1<<5); //令PB5输出低电平,点亮红色LED灯
Delay(1000000);
GPIOB->ODR |= (1<<5); //令PB5输出高电平,熄灭红色LED灯
GPIOB->ODR &= ~(1<<0); //令PB0输出低电平,点亮绿色LED灯
Delay(1000000);
GPIOB->ODR |= (1<<0); //令PB0输出高电平,熄灭绿色LED灯
GPIOB->ODR &= ~(1<<1); //令PB1输出低电平,点亮蓝色LED灯
Delay(1000000);
GPIOB->ODR |= (1<<1); //令PB1输出高电平,熄灭蓝色LED灯
}
经过以上(1)(2)(3)三个步骤的配置之后,我们将程序编译烧写到开发板中,可以看到如下现象:
http://v.youku.com/v_show/id_XMjY1ODYxMDQxMg==.html
----------------我是萌萌哒分割线-----------------------------
好啦,到这儿今天的这一讲就算是顺利结束啦。下一讲当中,我们将要对如何使用库函数法,来操作GPIO口。欢迎大家有问题,下方留言交流哦~!
大Z带你重玩STM32系列(四)------STM32的库函数(固件库)