GPIO功能描述
- GPIO内部结构框图
- GPIO寄存器
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端口(Px)都由7个寄存器组成,负责控制该端口的16个引脚Px0~Px15
- GPIO工作模式
typedef enum
{
//四种输入
GPIO_Mode_AIN = 0x00, //模拟输入
GPIO_Mode_IN_FLOATING = 0x04, //浮空输入
GPIO_Mode_IPD = 0x28, //下拉输入
GPIO_Mode_IPU = 0x48, //上拉输入
//四种输出
GPIO_Mode_Out_OD = 0x14, //开漏输出
GPIO_Mode_Out_PP = 0x10, //推挽输出
GPIO_Mode_AF_OD = 0x1C, //复用开漏输出
GPIO_Mode_AF_PP = 0x18, //复用推挽输出
}GPIOMode_TypeDef;
-
① 作为普通GPIO输入:
根据需要配置该引脚为浮空输入、带弱上拉输入或带弱下拉输入,同时不要使能该引脚对应的所有复用功能模块。
② 作为普通GPIO输出:
根据需要配置该引脚为推挽输出或开漏输出,同时不要使能该引脚对应的所有复用功能模块。
③ 作为普通模拟输入:
配置该引脚为模拟输入模式,同时不要使能该引脚对应的所有复用功能模块。(A/D模拟输入)
④ 作为内置外设的输入:
根据需要配置该引脚为浮空输入、带弱上拉输入或带弱下拉输入,同时使能该引脚对应的某个复用功能模块。
⑤ 作为内置外设的输出:
根据需要配置该引脚为复用推挽输出或复用开漏输出,同时使能该引脚对应的所有复用功能模块 -
配置速度
typedef enum { GPIO_Speed_10MHz = 1, GPIO_Speed_2MHz = 2, GPIO_Speed_50MHz = 3, }GPIOSpeed_TypeDef;
-
GPIO标准外设库接口函数
/***初始化以及复位函数***/ //将GPIOx外设寄存器恢复为默认复位值 void GPIO_DeInit(GPIO_TypeDef* GPIOx); //取消所有的复用功能 void GPIO_AFIODeInit(void); //根据GPIO初始化结构参数初始化GPIOx外设寄存器 void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct); //GPIO结构体初始化 void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct); /***引脚功能操作函数***/ //读取选定的GPIO输入端口引脚数据 uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); //读取选定的GPIO输入端口数据 uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx); //读取选定的GPIO的输出端口引脚数据 uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); //读取选定的GPIO的输出端口数据 uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx); //置为选定GPIO端口引脚 void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); //复位选定GPIO端口引脚 void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); //置为或复位选定的GPIO端口引脚 void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal); //置为或复位选定的GPIO数据端口 void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal); //将原来的端口引脚的置为设为复位,复位设为置为 void GPIO_Toggle(GPIO_TypeDef* GPIOx, uint16_t PortVal); //外部中断处理函数 //外设端口作为中断线号输入 void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource); //事件输出 void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource); void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); void GPIO_EventOutputCmd(FunctionalState NewState); void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState); void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface);
void GPIO_Toggle(GPIO_TypeDef* GPIOx, uint16_t PortVal) { GPIOx->ODR ^= PortVal; }
-
GPIO库函数简要解释:
函数名 具体功能 GPIO_DeInit 重新初始化外围设备GPIOx相关寄存器到它的默认复位值 GPIO_AFIODeInit 初始化交错功能(remap, event control和 EXTI 配置) 寄存器 GPIO_Init 根据GPIO_初始化结构指定的元素初始化外围设备GPIOx GPIO_StructInit 填充GPIO_初始化结构(GPIO_InitStruct)内的元素为复位值 GPIO_ReadInputDataBit 读指定端口引脚输入数据 GPIO_ReadInputData 读指定端口输入数据 GPIO_ReadOutputDataBit 指定端口引脚输出数据 GPIO_ReadOtputData 读指定端口输出数据 GPIO_SetBits 置1指定的端口引脚 GPIO_ResetBits 清0指定的端口引脚 GPIO_WriteBit 设置或清除选择的数据端口引脚 GPIO_Write 写指定数据到GPIOx端口寄存器 GPIO_PinLockConfig 锁定GPIO引脚寄存器 GPIO_EventOutputConfig 选择GPIO引脚作为事件输出 GPIO_EventOutputCmd 允许或禁止事件输出 GPIO_PinRemapConfig 改变指定引脚的映射 GPIO_EXTILineConfig 设置外部中断 GPIO_ETH_MediaInterfaceConfig 配置以太网接口 GPIO_Toggle 取反置位端口引脚 -
主流程
>>开始 >>开启PGIO外设时钟 >>初始化GPIO参数 >>使能GPIO端口 >>若有中断,编写中断服务函数
-
IO输出实例演示
#define LED PAout(12) //输出,使用的是位带操作来实现操作某个 IO 口的 1 个位 void led_init(void) { GPIO_InitTypeDef GPIO_InitStructure; //GPIO初始句柄 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能PA端口 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //PA.8端口设置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口的速度为50MHZ GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA GPIO_SetBits(GPIOA,GPIO_Pin_12); //PA.8输出高 }
-
注意点
-
在使用PA15引脚的时候,按照正常的 IO 初始化,并且停止使用JTAG,依然不能点亮LED,因为PA15默认JTAG的一个脚,现在要变成普通IO就要使能复用时钟。
-
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);//使能PA端口 GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //关闭JTAG口,使PB3,PB4,PA15这几个IO作为普通IO使用
-
-
操作 IO 口输出高低电平的三种方法
-
位操作就是可以单独的对一个比特位读和写,这个在51单片机中非常常见。51单片机中通过关键字sbit来实现位定义,STM32F103中没有这样的关键字,而是通过访问位带别名区来实现。
-
a.通过位带操作 PA12 输出高低电平从而控制 LED 的方法如下: #define LED PAout(15) //输出 LED=1; //通过位带操作控制 LED 的引脚 PA12 输出高电平 LED=0; //通过位带操作控制 LED 的引脚 PA12 输出低电平 b.使用固件库操作和寄存器操作: 来实现 IO 口操作。 库函数操作方法如下: GPIO_SetBits(GPIOA, GPIO_Pin_12); //设置 GPIOA12 输出 1,等同 LED=1; GPIO_ResetBits (GPIOA, GPIO_Pin_12); //设置 GPIOA12 输出 0,等同 LED=0; 库函数操作就直接调用两个函数即可控制 IO 输出高低电平。 c.通过直接操作寄存器: BRR 和 BSRR 的方式来操作 IO 口输出高低电平,方法如下: GPIOA->BRR=GPIO_Pin_12; //设置 GPIOA.12 输出 1,等同 LED=1; GPIOA->BSRR=GPIO_Pin_12; //设置 GPIOA.12 输出 0,等同 LED=0;
-
-
IO输入实例演示
-
void Key_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能 PORTA 时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//PA12 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉 GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化PA12 } void Key_Scan(void) { if(KEY == 0) { delay_ms(10); if(KEY == 0) LED = !LED; } }