与大家分享我对一下GPIO函数的理解
- 目录
标号 | 函数名 |
---|---|
1 | void GPIO_DeInit(GPIO_TypeDef* GPIOx); |
2 | void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct); |
3 | void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct); |
4 | void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); |
5 | uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); |
6 | uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx); |
7 | uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); |
8 | uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx); |
9 | void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); |
10 | void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); |
11 | void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal); |
12 | void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal); |
13 | void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); |
14 | void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF); |
1:void GPIO_DeInit(GPIO_TypeDef* GPIOx);
------------------复位IO口
-
Function used to set the GPIO configuration to the default reset state
用于将GPIO选择的IO口组设置为默认状态;
函数参数GPIOx就是用于选择具体哪一组IO口 -
程序实现过程
//例如设置GPIOA
if (GPIOx == GPIOA)
{
RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOA, ENABLE);//复位端口
RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOA, DISABLE);//不复位端口
}
通过if判断找到复位的IO口组,通过调用RCC_AHB1PeriphResetCmd复位端口
使端口寄存器恢复默认值
2:void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
-------------------------IO初始化
- 首个参数GPIOx
选择具体哪一个GPIOx口
例如:GPIOA 即选择PA组IO口 - 参数GPIO_InitStruct
参数为一个结构体,结构体内容为
typedef struct
{
uint32_t GPIO_Pin; //指定要配置的GPIO引脚
GPIOMode_TypeDef GPIO_Mode; //指定设置IO口的模式
GPIOSpeed_TypeDef GPIO_Speed; //指定所选引脚的速度
GPIOOType_TypeDef GPIO_OType; //指定所选引脚的操作输出类型
GPIOPuPd_TypeDef GPIO_PuPd; //指定所选引脚的操作上拉/下拉
}GPIO_InitTypeDef;
- GPIO_Pin: 即指定具体哪个IO口
- GPIO_Speed: 输出驱动电路的带宽, 即一个驱动电路可以不失真地通过信号的最大频率
- GPIO_PuPd: 即设置引脚的上拉/下拉/悬空
目前的单片机往往可以内部挂载一个电阻,通常io口呈现出高阻态
上拉:就是IO串联一个电阻到Vcc,这样就会让IO口电平呈现Vcc
下拉:就是IO串联一个电阻到Gnd,这样就会让IO口电平呈现Gnd
悬空:即不上下拉,这样IO口会呈现出高阻状态,并且IO口的初始电平是不确定的
具体分析一下GPIO_Mode和GPIO_OType
设置GPIO_Mode时,是设定一个枚举类型的值
typedef enum
{
GPIO_Mode_IN = 0x00, //输入
GPIO_Mode_OUT = 0x01, //输出
GPIO_Mode_AF = 0x02, //复用
GPIO_Mode_AN = 0x03 //模拟输入
}GPIOMode_TypeDef;
- 1:输入:检测输入的电平
- 2:输出:输出高电平或低电平
- 3:复用:调用外设时设置
STM32F4 有很多的内置外设,这些外设的外部引脚都是与 GPIO 共用的。也就是说,一个引脚可以有很多作用,但是默认为IO口,如果想使用一个 GPIO内置外设的功能引脚,就需要GPIO的复用,那么当这个 GPIO 作为内置外设使用的时候,就叫做复用。 比如说串口 就是GPIO复用为串口
- 4:模拟输入:应用ADC模拟输入,或者低功耗下省电
当GPIO引脚用于ADC采集电压的输入通道时,用作"模拟输入"功能,此时信号不经过施密特触发器,直接直接进入ADC模块,并且输入数据寄存器为空 ,CPU不能在输入数据寄存器上读到引脚状态,当GPIO用于模拟功能时,引脚的上、下拉电阻是不起作用的,这个时候即使配置了上拉或下拉模式,也不会影响到模拟信号的输入输出
设置GPIO_OType也是设置一个枚举类型的值
typedef enum
{
GPIO_OType_PP = 0x00, //推挽输出
GPIO_OType_OD = 0x01 //开漏输出
}GPIOOType_TypeDef;
区别~!!!!
推挽输出电路: 其中IN端输出高电平时下面的PNP三极管截止,而上面NPN三极管导通,输出电平VS+;当IN端输出低电平时则恰恰相反,PNP三极管导通,输出和地相连,为低电平
开漏输出电路:IN端输出低电平时,三极管导通,使输出接地,IN端输出高电平时,三极管截止,所以引脚既不输出高电平,也不输出低电平,为高阻态。为正常使用时必须接上拉电阻,
总结:推挽输出(PP)可以输出强高低电平,连接数字器件
开漏输出(OD)可以输出强低电平,高电平得靠外部电阻拉高。输出端相当于三极管的集电极. 需要外接上拉电阻,才能实现输出高电平 合于做电流型的驱动,其吸收电流的能力相对强(一般20ma以内);在使用任何一种开漏模式时,都需要接上拉电阻,否则只能输出低电平
推挽和开漏一般是对应输出,上下拉一般对应着输入
3:void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
---------------使用默认值填充所有IO口
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct)
{
/* Reset GPIO init structure parameters values */
GPIO_InitStruct->GPIO_Pin = GPIO_Pin_All;
GPIO_InitStruct->GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStruct->GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStruct->GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct->GPIO_PuPd = GPIO_PuPd_NOPULL;
}
默认设置为低速推挽无上下拉输入模式
4:void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
--------------------锁定GPIO管脚配置寄存器
- 当执行正确的写序列设置了位16(LCKK)时,该寄存器用来锁定端口位的配置。位[15:0]用于锁定GPIO 端口的配置。在规定的写入操作期间,不能改变LCKP[15:0]。当对相应的端口位执行了LOCK序列后,在下次系统复位之前将不能再更改端口位的配置
5:uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
------------------------读取指定的输入端口引脚状态
- 参数选择具体哪组IO口,哪个IO口
- 返回值:0或者1,
6:uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
------------------------读取指定的GPIO组数据端口
- 参数是选择哪一组IO口
7:uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
--------------------------读取指定的输出端引脚状态
- 同读取输入
8:uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
---------------------------读取指定的GPIO组端口
- 同检测输入
9:void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
-----------------------------设置IO口的输出高电平
- 第一个参数设置GPIO的IO组
- 第二个参数设置具体IO口
作用:设置IO口输出高电平
10:void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
------------------------------设置IO口的输出低电平
- 第一个参数设置GPIO的IO组
- 第二个参数设置具体IO口
作用:设置IO口输出低电平
11:void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
-----------------------------设置IO口的电平
- 第一个参数设置哪组GPIO
- 第二个参数设置取缔哪个IO
- 第三个参数设置高电平还是低电平
作用:设置IO口的电平
WriteBit和SetBit、ResetBit的区别!!!!
WriteBit一次只能设置一个IO口,但是SetBit支持或运算可以同时设置几个IO的电平
12:void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
----------------------------设置一组IO口的电平
- 第一个参数选择GPIO组
- 第二个参数设置电平
作用:设置GPIO组的电平
13:void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
-------------------------------切换IO口
- 第一个参数为哪组GPIO
- 第二个参数是哪个IO口
我也不太清楚,有会的大佬可以评论一下
14:void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF);
-------------------------------设置IO口的复用功能
- 第一个参数选择GPIO组
- 第二个参数选择IO口
- 第三个参数选择复用的外设功能
设置IO口的映射,通过使用此函数映射到外设
使用复用功能时,先要将GPIO初始化的复用模式打开,才能开始映射
总结就这些了,觉得还行的可以互相交流交流
谢谢!