一、GPIO的八种模式
GPIO支持4种输入模式(浮空输入、上拉输入、下拉输入、模拟输入)和4种输出模式(开漏输出、开漏复用输出、推挽输出、推挽复用输出)。
GPIO_Mode_AIN | 模拟输入 |
GPIO_Mode_IN_FLOATING | 浮空输入 |
GPIO_Mode_IPD | 下拉输入 |
GPIO_Mode_IPU | 上拉输入 |
GPIO_Mode_Out_OD | 开漏输出 |
GPIO_Mode_Out_PP | 推挽输出 |
GPIO_Mode_AF_OD | 复用开漏输出 |
GPIO_Mode_AF_PP | 复用推挽输出 |
开漏输出:mos管导通,输出强低电平;mos管截止,此时mos管电阻无穷大,如果无外部上拉电路,输出为高阻态,如果有外部上拉电路,输出为弱高电平(驱动能力较弱)
推挽输出:NMOS管导通,PMOS管截止,输出强低电平;NMOS管截止,PMOS管导通,输出强高电平
二、端口复用功能
由数据手册可以得知,每一个IO口都有很多功能,比如PA4可以做SPI1的片选,也可以做SPI3的片选,这些都是IO端口的复用功能
使用硬件SPI时,此时的引脚需要使用复用功能,即配置为复用推挽输出
void SPI1_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
使用硬件iic时,引脚配置为复用开漏输出
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(i2cHandle->Instance==I2C2)
{
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
__HAL_RCC_I2C2_CLK_ENABLE();
}
}
使用软件iic时,此时的SCL和SDA引脚完全由我们控制,所以不使能复用功能,直接配置为开漏输出,然后SDA引脚读数据时配置为上拉输入模式,写数据时配置为开漏输出即可
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(i2cHandle->Instance==I2C2)
{
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
__HAL_RCC_I2C2_CLK_ENABLE();
}
}
注意:SPI作为主机,MISO配置为浮空输入或者复用推挽输出都可以,原因在于,MISO引脚的功能就是读取电平信号,所以配置为输入模式没有问题,当配置为复用推挽输出时,我们会把MISO端口的使用权交给SPI,他会自己控制MISO的端口模式为输入模式
三、GPIO速度
#define GPIO_SPEED_FREQ_LOW 0x00000000U /*!< IO works at 2 MHz, please refer to the product datasheet */
#define GPIO_SPEED_FREQ_MEDIUM 0x00000001U /*!< range 12,5 MHz to 50 MHz, please refer to the product datasheet */
#define GPIO_SPEED_FREQ_HIGH 0x00000002U /*!< range 25 MHz to 100 MHz, please refer to the product datasheet */
#define GPIO_SPEED_FREQ_VERY_HIGH 0x00000003U /*!< range 50 MHz to 200 MHz, please refer to the product datasheet */配置高速:输出频率高,噪音大,功耗高,电磁干扰强;
配置低速:输出频率低,噪音小,功耗低,电磁干扰弱;提高系统EMI(电磁干扰)性能;
我们知道GPIO速度有四种模式,低速,中速,高速和超高速,其中不同的速度对应不同的时钟频率。
- 低速:USART(115.2kbps)、按键扫描。
- 中速:I2C(400kbps)。
- 高速:SPI(18Mbps)、PWM高频信号。
- 超高速:QSPI FLASH,FMC,以太网等高速。
注意事项:
1、如果你使用9600波特率UART通信,建议速度配置为低。所以,如果你想使产品更加完美,速度配置也是关键的一项。
2、比如SPI时钟配置时,如果配置为30Mhz,那么GPIO引脚的速度最起码配置为高速模式,不然信号可能会失真。
3、GPIO设为输入模式时,输出驱动电路断开,速度配置无意义。此时应关注上拉/下拉电阻配置。
4、使用Cubemx生成代码时,SPI选用软件片选信号,此时注意GPIO口速度默认为低速模式,但是SPI一般配置高速模式,此时防止数据乱码需要修改GPIO口速度
四、如何选择I/O模式
- 浮空输入_IN_FLOATING ——浮空输入,可以做KEY识别,RX1
- 带上拉输入_IPU——IO内部上拉电阻输入
- 带下拉输入_IPD—— IO内部下拉电阻输入
- 模拟输入_AIN ——应用ADC模拟输入,或者低功耗下省电
- 开漏输出_OUT_OD ——IO输出0接GND,IO输出1,悬空,需要外接上拉电阻,才能实现输出高电平。当输出为1时,IO口的状态由上拉电阻拉高电平,但由于是开漏输出模式,这样IO口也就可以由外部电路改变为低电平或不变。可以读IO输入电平变化,实现C51的IO双向功能
- 推挽输出_OUT_PP ——IO输出0-接GND, IO输出1 -接VCC,读输入值是未知的
- 复用功能的开漏输出_AF_OD ——片内外设功能(I2C的SCL、SDA)
- 复用功能的推挽输出_AF_PP——片内外设功能(USART的TX和RX、SPI的MOSI、MISO.SCK)
五、JTAG引脚作为GPIO使用要注意
例如PA15引脚,它默认时JTDI引脚,但是可以复用为SPI的NSS片选信号。在初始化时,需要先开启AFIO时钟,再关闭JTAG功能,否则GPIO功能仍然不起作用。初始化代码如下:
stm32f103
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); /*使能SWD 禁用JTAG*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* CS: PA15 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
兆易创新gd32F103
void micromotor_alarm_gpio_config(void)
{
//1.GPIO引脚时钟使能
rcu_periph_clock_enable(RCU_GPIOA);
//2.复用功能时钟使能
rcu_periph_clock_enable(RCU_AF);
//3.GPIO配置为推完输出模式
gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_15);
//4.重映射配置:JTAG-DP禁用和SW-DP使能
gpio_pin_remap_config(GPIO_SWJ_SWDPENABLE_REMAP,ENABLE);
//5.引脚配置为低电平
gpio_bit_reset(GPIOA,GPIO_PIN_15);
}
常见的调试接口:
SW调试接口: PA13、PA14共两个引脚。
JTAG调试接口: PA13、PA14、PA15、PB3、PB4共五个引脚。