(本博客所有关于32的文章都是基于stm32f103c8t6(48引脚))
GPIO初识——理论讲解
一.GPIO的工作模式
四种输入模式
上拉输入:
若GPIO引脚配置为上拉输入模式,在默认情况下(GPIO引脚无输入),读取 得的GPIO引脚数据位1,高电平。
下拉输入:
若GPIO引脚配置为下拉输入模式,在默认情况下(GPIO引脚无输入),读取 得的GPIO引脚数据位0,低电平。
浮空输入:
在芯片内部既没有接上拉,也没有接下拉电阻,经由触发器输入。配置成这个模式直接用电压表测量其引脚电压为1点几伏,这是个不确定值。由于其输入阻抗较大,一般把这种模式用于标准的通信协议如I2C,USART的接收端。
模拟输入:
关闭了施密特触发器,不接上,下拉电阻,经由另一线路把电压信号传送到片上外设模块。如传送至ADC模块,由ADC采集电压信号。所以使用ADC外设时,必须设置为模拟输入模式。
四种输出模式
开漏输出:
此种输出方式,输出寄存器写1时,mos管不导通,此时电平为浮空状态不确定,写0的时候,mos管导通,此时为低电平。此种方式在没有外部电路辅助的时候只能输出低电平。但是利用他这种特性,我们可以外接一个上拉电阻,此时不但可以输出高低电平,而且由于上拉电阻的存在大大的增强了单片机的驱动能力。
推挽式输出:
最常用的一种GPIO模式,输出寄存器写1的时候为高电平,写0为低电平。能够快速的切换高低电平,适合做开关控制。
推挽式复用功能:
此种方式大体与推挽式输出相同,区别在于其提供片内外设功能(I2C的SCL,SDA)
开漏复用功能
同样的,此种方式大体上与开漏输出模式一样,区别在于其提供片内外设功能(TX1,MOSI,MISO.SCK.SS)
二.GPIO的寄存器介绍
GPIO总共有七种寄存器
一.端口配置低寄存器GPIOX_CPL
二.端口配置高寄存器GPIOX_CRH
三.端口输入寄存器GPIO_IDR
四.端口输出寄存器GPIO_ODR
五.端口设置/清除寄存器GPIO_BSRR
六.端口清除寄存器GPIO_BRR
七.端口配置锁定寄存器GPIO_LCKR
(1)端口配置寄存器(CPL和CPH)
对于端口配置寄存器而言,端口配置高寄存器配置GPIO口的高八位,端口配置低寄存器则配置GPIO口的低八位。(每个GPIO口总共由16位)
GPL寄存器和CPH寄存器都总共有32位,每四个字节操控一个GPIO口
四个字节中的低两位是端口的模式位(MODE),四个字节中的高两位为配置位(CNF)
模式位操控输入输出模式和输出速率
配置位则是配合模式位确定GPIO口是具体是何种输出模式或者输入模式
(2)端口输入寄存器(IDR)
是一个32位寄存器,但是只有低16位可以用,高16位保留。
是一个只读寄存器,寄存器的每一位都对应的GPIO口状态
(3)端口输出寄存器(ODR)
是一个32位寄存器,但是只有低16位可以用,高16位保留。
是一个可读可写寄存器,只能以字(16位)的形式进行操控。(也就是每次操作必须对整个GPIO口进行读写,不能对某个单独的位进行操作(不支持位操作))
(4)端口设置/清除寄存器(BSRR)
此寄存器分为低十六位和高十六位。只写寄存器
低十六位是设置位,写入1则对相应的位设置,写入0则没有影响
高十六位是清除位,写入1则对相应的位清除,写入0则没有影响
且同时设置低十六位和高十六位是第十六位(设置位)起作用
操作BSRR寄存器的实质就是操作ODR寄存器
(5)端口清除寄存器(BRR)
是一个32位寄存器,但只有低16位才起作用,高16位保留。只写寄存器
跟其名字一样,是一个清除寄存器,对应位写入1则该位清除
(6)端口配置锁定寄存器(GPIO_LCKR)
这个寄存器几乎不会用到,这里不做讨论
GPIO初识——实际运用
注意:为了提高32在进行小项目开发的速度,本篇文章所用的代码都是笔者自己基于32标准库进行二次开发 ,方便能够快速调用单片机外设
关于代码,工程文件会附在文章的末尾。
一.GPIO的初始化
//-------------------------------------------------------------------------------------------------------------------
// @brief GPIO初始化
// @param pin 选择的引脚 (可选择范围由 HYJ_GPIO.h 内PIN_enum枚举值确定)
// @param GPIO_Mode 引脚的模式
// @param dat 引脚初始化时设置的电平状态,输出时有效 0:低电平 1:高电平
// @return void
// Sample usage: HYJ_GPIO_Init(PA0,GPIO_Mode_Out_PP,1);//PA0初始化为GPIO功能、推挽输出、输出高电平
// @note 需要特别注意P20_2是不能用于输出的,仅仅只有输入的功能
//-------------------------------------------------------------------------------------------------------------------
void HYJ_GPIO_Init(PIN_enum pin ,GPIOMode_TypeDef GPIO_Mode,int8_t data)
{
GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO配置结构体
RCC_APB2PeriphClockCmd(get_clock(pin),ENABLE);//时钟使能
//GPIO的端口配置
GPIO_InitStructure.GPIO_Pin = get_pin(pin);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(get_port(pin), &GPIO_InitStructure);//将上述结构体传入真正的初始化函数(本质上在操作CPL CPH寄存器)
if(GPIO_Mode==GPIO_Mode_Out_OD||GPIO_Mode==GPIO_Mode_Out_PP||GPIO_Mode==GPIO_Mode_AF_OD||GPIO_Mode==GPIO_Mode_AF_PP)
HYJ_GPIO_Set(pin,data);//GPIO口初始化配置后,默认拉高电平(本质上在操作BSRR寄存器)
}
(1)对引脚所拖挂的外设模块进行使能
(2)再利用一个结构体变量,将引脚的选择和GPIO的工作模式进行设置,这里实际上操作的是端口配置寄存器(CPL和CPH)
(3)再根据需求将端口初始化为低电平或者高电平**
二.GPIO的调用和实例
初始化完成后就可以进行调用
//-------------------------------------------------------------------------------------------------------------------
// @brief GPIO输出设置
// @param pin 选择的引脚 (可选择范围由 HYJ_GPIO.h 内PIN_enum枚举值确定)
// @param dat 0:低电平 1:高电平
// @return void
// Sample usage: HYJ_GPIO_Set(PA0, 1);//P00_0 输出高电平
//-------------------------------------------------------------------------------------------------------------------
void HYJ_GPIO_Set(PIN_enum pin,int8_t data)
{
if(data==1) get_port(pin)->BSRR = get_pin(pin);
else get_port(pin)->BRR = get_pin(pin);
}
//-------------------------------------------------------------------------------------------------------------------
// @brief GPIO状态获取
// @param pin 选择的引脚 (可选择范围由 HYJ_GPIO.h 内PIN_enum枚举值确定)
// @return uint8 0:低电平 1:高电平
// Sample usage: uint8 status = gpio_get(PA0);//获取P00_0引脚电平
//-------------------------------------------------------------------------------------------------------------------
uint8_t HYJ_GPIO_Read(PIN_enum pin)
{
return GPIO_ReadInputDataBit(get_port(pin),get_pin(pin));
}
根据初始化的模式,选择调用输出设置函数
void HYJ_GPIO_Set(PIN_enum pin,int8_t data)
还是状态读取函数uint8_t HYJ_GPIO_Read(PIN_enum pin)
示例:
int main(void)
{
HYJ_GPIO_Init(PA0,GPIO_Mode_Out_PP,1);
while(1)
{
HYJ_GPIO_Set(PA0, 1);
}
}
此时PA0引脚就被设置成输出高电平
工程文件链接地址:
链接:https://pan.baidu.com/s/1abTvUt44NiH5B_o7IiPa3Q
提取码:cxm6
复制这段内容后打开百度网盘手机App,操作更方便哦–来自百度网盘超级会员V1的分享