由于是stm32学习的第一个章节,会啰嗦一些,旨在帮助和我一样刚接触stm32时一头雾水的朋友,更好地理解、学会它。
很多学过51,刚开始学stm32的朋友可能会和我一样十分不适应,在我看来,stm32与51代码最大的区别在于,stm32几乎所有外设都要进行配置过后才能使用,比如说你想操作一个IO口,那么首先要对这个IO口所挂载的时钟进行使能,再对此IO口进行配置、使能。这也是为什么51点亮一个LED只需要一行代码,你找到的stm32的代码却看着都让人头大的原因。
为什么要进行初始化(配置)?就GPIO来说,51的IO口很简单,能且只能实现高低电平的输入输出;而stm32可以在此基础上,指定GPIO输入输出的类型,速率等一系列参数,正因为stm32可以实现更多的功能,因此要进行初始化,指定GPIO的参数。实际上配置完成后,就使用上来说是不会比51复杂到哪去的。因此,先耐着性子学会GPIO的配置吧。
认识GPIO初始化
首先要适应这种stm32的代码风格:对每个模块都写一个xxx_Init()函数进行初始化(配置)。至于这个函数里要写些什么,视这个模块用到哪些功能而定。比如说我想写一个程序控制LED的亮灭,需要用到GPIO,所以要做以下的事情:对GPIO的时钟进行使能、对GPIO进行初始化。把这两个过程写在一个名为LED_Init()的函数中,这样只需要在main()中调用一下LED_Init()就可以实现LED模块的初始化了。
本章仅讲解GPIO的初始化,其他功能怎么初始化在以后的章节中会进行讲解。
首先,我们要认识下面这个结构体:GPIO_InitTypeDef
typedef struct
{
uint16_t GPIO_Pin;
GPIOSpeed_TypeDef GPIO_Speed;
GPIOMode_TypeDef GPIO_Mode;
}GPIO_InitTypeDef;
它具有三个成员变量:GPIO_Pin, GPIO_Speed, GPIO_Mode
对于GPIO的配置其实就是指定这三个参数的值。接下来通过一个实例讲解这三个变量的含义。
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度 50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);//根据设定参数配置 GPIO
这便是GPIO初始化的常用格式(事实上stm32任何外设的初始化都可以参照这种格式)
1.首先,要实例化一个GPIO_InitTypeDef对象,名为GPIO_InitStructure。
2.接下来对它的三个成员变量进行配置。其中GPIO_Pin用来设置是要初始化哪个或者哪些IO口(这里要注意,决定的不是A、B、C...,而是GPIOx后面的数字,也就是16个引脚中的哪一个); GPIO_Mode 是用来设置输出输入模式(GPIO共有8种模式,这里用到的是推挽输出);GPIO_Speed 是IO口速度设置,有2M、10M、50M三个可选值。
3.最后,调用一下GPIO_Init()函数,GPIO的初始化就完成了。GPIO_Init()第一个参数填GPIOx,也就是确定A、B、C...,结合前面设置的GPIO_Pin,就确定了具体是哪一个IO口;第二个参数填 &GPIO_InitStructure,将我们之前设置好的参数通过GPIO_InitStructure这个对象输入进去,实现GPIO的初始化。
完整的GPIO初始化流程
接下来给出一个完整的GPIO初始化实例,用了两个IO口(PB5、PE5)分别控制两个LED。
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//GPIO_InitTypeDef结构体用于配置GPIO,首先实例化一个它的对象
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能PB、PE端口的时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定的参数初始化GPIOB.5
GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高电平
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 端口配置
GPIO_Init(GPIOE, &GPIO_InitStructure); //推挽输出,IO口速度为50MHz
//这里虽然配置的是另一个IO口PE.5,但仍旧使用了上面配置PB.5时的对象,是因为两个IO参数一样,若出现参数不一样的情况,要重新实例化一个对象(或者更改之前对象的参数)
GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高电平
}
认真理解这段代码。其中有两句代码是之前没有提到过的,分别是时钟的使能与GPIO_SetBits() 这个函数。
GPIO 是挂载在 APB2 总线上的外设,在固件库中对挂载在 APB2 总线上的外设时钟使能是通过函数 RCC_APB2PeriphClockCmd()来实现的,至于其他情况下时钟使能是什么函数,在以后的章节中会提到。
至于GPIO_SetBits() 在下文进行讲解。
IO口操作
GPIO配置完成后,就可以对IO口进行操作了。常用两种方式进行操作,效果是一样的。
寄存器版
在sys.h中有以下定义
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入
......
//这里由于篇幅关系仅给出GPIOB的定义,其余GPIO端口都有类似定义
这使IO口的操作变得和51一样简单
#define LED PBout(5) //define下提高程序可读性
...
LED = 1; //输出高电平
LED = 0; //输出低电平
LED_in = PBin(5); //读取PB.5电平
可以直接用PBout(5)=1进行GPIOB.5的高电平输出,也可以像51一样先宏定义改个名称,增强可读性。
库函数版
//输出
GPIO_SetBits(GPIOB,GPIO_Pin_8); //PB.8输出高电平
GPIO_ResetBits(GPIOB,GPIO_Pin_8); //PB.8输出低电平
//输入
GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2) //读取PE.2电平
Tips:操作IO口前,必须先进行对应的GPIO初始化
上一篇:STM32学习笔记之GPIO的基本使用
下一篇:STM32学习笔记(一)GPIO
推荐阅读最新更新时间:2024-11-07 19:44
设计资源 培训 开发板 精华推荐
- TCR2EN13、200mA、1.3V 输出电压 CMOS 低压降稳压器的典型应用
- SW3516H PD100W快充模块
- RTK20-Main-Board
- 使用 Analog Devices 的 LTC2411IMS 的参考设计
- ADR5044B 4.096 Vout 负精密基准配置的典型应用
- 18650锂电池充放保护板
- 使用 Microchip Technology 的 TC28C46EOE 的参考设计
- MC33PF3000A6ES PMIC 解决方案电源管理的典型应用
- 【训练营】四足机器狗
- ZLDO485 4.85 伏超低压降稳压器的典型应用是将开关稳压器变压器缠绕以提供略高于所需的电压,并使用线性稳压器从该电压降至所需电压