GPIO简介
GPIO的英文名称是General Purpose Input Output,顾名思意,就是通用输入输出口,可以用来输入输出高低电平进而控制各种连接在GPIO上的模块等等。STM32的GPIO就是51单片机的P11、P12等等引脚,不过STM32的GPIO更加强大,具有多种模式,为了控制功耗,每一个GPIO都有单独的时钟开关,每使用到一个GPIO都要对其时钟使能,而且STM32的GPIO的输入输出必须单独配置。
GPIO的模式与各种外设GPIO模式的设置
GPIO有八种输入输出模式,对于输出模式还能设置输出的速度,每一个外设对应GPIO口的模式都不全相同,例如使用I2C_SCL的时候GPIO口要设置成 开漏复用输出,SPI_SCK主模式GPIO口要设置成 推挽复用输出等等,记住是不可能的,不过官方的参考手册就已经给出了每一个外设的GPIO的配置情况,我们需要用到某个外设GPIO口的时候不知道怎么配置模式可以到《STM32中文参考手册》8.1.11小节查看
GPIO的常用寄存器
首先对于每一个寄存器必须以字(32位)的方式操作这些外设寄存器
-
端口配置低寄存器(GPIOx_CRL) (x=A…E)
配置GPIO 0~7位的模式
-
端口配置高寄存器(GPIOx_CRH) (x=A…E)
配置GPIO 8~16位的模式
-
端口输入数据寄存器(GPIOx_IDR) (x=A…E)
有16个位 只读并只能以字(16位)的形式读出
对于每个GPIO16个引脚的状态,是高电平就是1,低电平就是0
-
端口输出数据寄存器(GPIOx_ODR) (x=A…E)
配置GPIO输出的电平
-
端口位设置/清除寄存器(GPIOx_BSRR) (x=A…E)
前16位写1就会对对应的ODR寄存器的位写1
后16位写1就会对对应的ODR寄存器的位写0
一般只用BSRR寄存器来写1,也就是只用前16位,后面16位一般不用
-
端口位清除寄存器(GPIOx_BRR) (x=A…E)
前16位有效,后16位无效,对一个位写1,就会清楚对应的ODR位为0
功能上于BSRR的后16位一样,因此一般不用BSRR的后16位
固件库中的GPIO类型结构体,里面包含了各种寄存器,而且都是有序排布,每两个寄存器的地址相隔是4:
typedef struct
{
__IO uint32_t CRL;
__IO uint32_t CRH;
__IO uint32_t IDR;
__IO uint32_t ODR;
__IO uint32_t BSRR;
__IO uint32_t BRR;
__IO uint32_t LCKR; //不常用
} GPIO_TypeDef;
GPIO的初始化
对于任何一种外设的初始化,其实都遵循差不多的配置流程
无非就是定义一个结构体变量,里面放了外设相关的寄存器,开始对于的外设的时钟(有的外设和GPIO共用引脚(复用),这时候需要把两个时钟都打开),配置结构体变量中的参数(即外设的各种配置参数,例如GPIO的模式,输出速度等等),最后调用一个初始化函数一般叫XXX_Init(),入口参数一般是塞入结构体(注意要加上&取地址号),外设的名称,如果有特殊需要,比如需要开启中断,那就还需要使用一个中断开启函数什么什么的。
例:初始化GPIOE_5为复用推挽输出
void GPIO_Config()
{
GPIO_InitTypeDef GPIO_InitStructure; //定义初始化结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); //初始化GPIO的时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //引脚位
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//输出速度
GPIO_Init(GPIOE,&GPIO_InitStructure);//调用库函数的GPIO初始化函数
}
GPIO的常用库函数
-
初始化函数
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct); -
引脚置1函数
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); -
引脚置0函数
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
用GPIO点亮LED
LED连接的引脚为PE5,低电平点亮
#include "stm32f10x.h"
#include "bsp_systick.h" //systick 用于写延时函数
void GPIO_Config()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_InitStructure);
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
int main(void)
{
GPIO_Config();
GPIO_SetBits(GPIOE,GPIO_Pin_5); //设置GPIOE的电平为高,即灭掉LED
while(1)
{
GPIO_ResetBits(GPIOE,GPIO_Pin_5);
delay_ms(300);
GPIO_SetBits(GPIOE,GPIO_Pin_5);
delay_ms(300);
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
delay_ms(300);
GPIO_SetBits(GPIOB,GPIO_Pin_5);
delay_ms(300);
}
}