简介
最多可支持 55 个通用 I/O 引脚(GPIO),分别为 PA0 ~ PA15,PB0 ~ PB15,PC0 ~ PC15,
PD2,PF0,PF1,PF4 ~ PF7,各片上设备用其来实现逻辑输入/输出功能。
每个 GPIO 端口有相关的控制和配置寄存器以满足特定应用的需求。GPIO 端口和其他备用功能(AFs)的备用引脚,在特定的封装下获得最大的的灵活性。GPIO引脚通过配置相关的寄存器可以用作备用功能输入/输出引脚。
每个 GPIO 引脚可以由软件配置为输出(推挽或开漏)、输入、外设备用功能或者模拟模式。
每个 GPIO 引脚都可以配置为上拉、下拉或无上拉/下拉。除模拟模式外,所有的 GPIO 引脚都
具备大电流驱动能力。
电气特性
- 电流驱动能力:25mA max
- 内部拉电阻阻值:30~50KΩ,典型值40KΩ
- 5V容忍:部分引脚支持,详见数据手册
主要配置流程
首先要使用GPIO_CTL寄存器来配置GPIO工作模式,有下面四种工作模式:
- 通用数字输出模式:主要用于输出数字信号,输出高/低电平
- 通用数字输入模式:用于读取外部电路输入的数字信号,读取高/低电平
- 备用功能模式:例如USART的RX,定时器的PWM输出通道,定时器的输入捕获通道等
- 模拟模式:ADC或者DAC功能的通道
然后,根据不同的工作模式,选着性地使用其他寄存器来进行剩余的配置。如下图所示。例如在通用数字输出模式下,可以使用OMODE来选择推挽或者开漏输出,使用OSPD来配置输出信号的最高频率,使用PUD来配置内部拉电阻。在通用数字输入模式下,只需要使用PUD配置拉电阻即可,OMODE和OSPD无需使用。
通用数字输出模式
当GPIO_CTL[1:0]=10时,配置GPIO为通用数字输出模式,此模式下,GPIO引脚可以输出高低电平信号来驱动外部电路。
在通用数字输出模式下,通过OMODE寄存器配置为推挽输出或者开漏输出两种不同的输出模式。通过OSPD寄存器来配置输出信号的速度,这个速度指的是引脚高低电平翻转的最高频率。通过PUD寄存器来配置内部的上下拉电阻。
推挽输出
使用GPIO_OCTL寄存器的一个单独的位来锁存输出控制信号,控制对应的GPIO输出高或者低电平。当GPIO_OCTL位=1时,输出驱动中的PMOS导通,NMOS截止,使得引脚与内部Vdd连接,用于输出高电平;当GPIO_OCTL位=0时,输出驱动中的PMOS截止,NMOS导通,使得引脚与内部Vss连接,用于输出低电平。
程序可以直接写GPIO_OCTL来改变引脚上输出的信号,但是GPIO_BOP和GPIO_BC寄存器有更高的访问效率,通过写BOP和BC寄存器可以间接控制GPIO_OCTL的值,所以一般使用GPIO_BOP和GPIO_BC寄存器来设置引脚输出电平。
推挽输出模式时,输入驱动电路也是工作的,可以读取GPIO_ISTAT寄存器来获取引脚上的电平。虽然这样做几乎没什么意义。
开漏输出
和推挽输出一样,开漏输出同样使用GPIO_OCTL寄存器的一个单独的位来锁存输出控制信号,可以通过GPIO_BOP和GPIO_BC寄存器来简介控制GPIO_OCTL寄存器的值。但是当GPIO_OCTL位=1时,PMOS和NMOS都是截止的,使得引脚与内部输出驱动电路处于“断路”状态,引脚输出高阻态,没有驱动能力;当GPIO_OCTL位=0时,输出驱动中的PMOS截止,NMOS导通,使得引脚与内部Vss连接,可以正常输出低电平。
开漏输出时一般都会使用上拉电阻(内部的或者外部的),此时GPIO是一个双向IO,既可以输出高低电平(高电平由上拉电阻提供),也可以通过读取GPIO_ISTAT寄存器来获取引脚上的输入的信号。
通用数字输入模式
当CTL[1:0]=00时,配置GPIO为通用数字输入模式,此模式下,GPIO引脚作为输入来采集外部电路的电平信号供CPU读取。
通用数字输入模式下,输出驱动电路被禁用,只有输入电路是有效的。在AHB时钟驱动下对引脚上的电平信号进行采样:每来一个AHB时钟周期,就对引脚上的电平进行捕获一次,并解释为逻辑1或者逻辑0,存储在ISTAT寄存器对应位中,对ISTAT寄存器的对应位的读取,就可以反映出引脚上输入的电平信号。
通用数字输入模式时,一般会使用上拉/下拉电阻,避免浮空输入产生噪声干扰。可以使用PUD来启用内部上拉或者下拉电阻。
备用功能模式
当CTL[1:0]=10时,配置GPIO为备用功能模式。备用功能模式(AFIO,Alternate Function IO)又叫复用功能模式。单片机内部的一些外设(如UART,I2C,SPI,定时器等)需要借助IO口来和外部电路实现信号的输入/输出,此时IO的输入和输出都由内部外设接管控制,而非CPU,这便是引脚的备用功能。一个GPIO可以支持多个备用功能,但是任何时刻都只能使用其中一个。
那么一个引脚有多少备用功能?每个备用功能分别是什么?这些都可以通过查阅数据手册的:《GD32F130xx pin alternate functions》来知晓。下面表格是摘选:
引脚名 | AF0(备用功能0) | AF1(备用功能1) | AF2(备用功能2) | ... |
PB6 | USART0_TX | I2C0_SCL | TIMER15_CH0_ON | ... |
PB7 | USART0_RX | I2C0_SDA | TIMER16_CH0_ON | ... |
PB8 | / | I2C0_SCL | TIMER15_CH0 | ... |
在备用功能模式下,需要通过AFSEL0或AFSEL1寄存器来选择需要的备用功能。例如需要将PB6配置为USART0的TX引脚,通过上表格我们知道PB6的AF0是USART0的TX备用功能,则要配置AFSEL0[3:0]=0000来选择第0个备用功能即可。
输出作用的AFIO
在输出AFIO的备用功能模式下,输出驱动电路不再受GPIO_OCTL寄存器控制,而是受备用功能对应的片内外设控制,例如对于配置成USART的TX引脚,它输出的信号受USART的发送电路控制。
此时还可以通过OMODE寄存器配置为推挽输出或者开漏输出两种不同的输出模式。通过OSPD寄存器来配置输出信号的速度。通过PUD寄存器来配置内部的上下拉电阻。
输入作用的AFIO
在输入AFIO的备用功能模式下,引脚上输入的信号被采样后,输入到了备用功能对应的外设,例如对于配置成USART的RX引脚,它采集的信号输入到了USART的接收电路。同时也可以像普通数字输入IO那样,通过读取ISTAT来获取输入信号,虽然这样做很少有意义。
此时还可以通过PUD寄存器来配置内部的上下拉电阻。OMODE寄存器和OSPD寄存器无需使用。
模拟模式
当需要将引脚作为为ADC或者DAC的通道时,要将GPIO配置为模拟模式。
当GPIO_CTL[1:0]=11时,配置GPIO为模拟模式,此模式下时,输出驱动电路和输入驱动电路都被禁用,相当于ADC或者DAC电路直接与引脚相连。
一些例子
例子1:使用PB13的通用推挽输出来驱动LED,输出高电平时LED点亮。
//配置PB13的模式为通用数字输出模式,且不启用内部拉电阻
gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_13); //配置PB13为推挽输出模式,速度为10MHz
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_13); //PB13输出高电平,点亮LED
gpio_bit_set(GPIOB,GPIO_PIN_13);//PB13输出低电平,熄灭LED
gpio_bit_reset(GPIOB,GPIO_PIN_13);//==========================【用宏封装】=============================
#define LED13_ON gpio_bit_set(GPIOC,GPIO_PIN_13)
#define LED13_OFF gpio_bit_reset(GPIOC,GPIO_PIN_13)
#define LED13_TOG \
do{ \
if(gpio_output_bit_get(GPIOC,GPIO_PIN_13)) \gpio_bit_reset(GPIOC,GPIO_PIN_13); \
else \gpio_bit_set(GPIOC,GPIO_PIN_13); \
}while(0)
例子2:使用PB13的通用数字输入模式来读取按键,PB13启用内部上拉电阻,按键一端接PB13,另一端接GND。按键按下时,PB13输入低电平;按键松开时,PB13输入高电平。
//配置PB13的模式为通用数字输入模式,启用内部上拉电阻
gpio_mode_set(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_13); //如果读取到PB13为低电平
if(RESET == gpio_input_bit_get(GPIOB,GPIO_PIN_13))
{//...按键处理逻辑
}
例子3:PA9为USART0的TX引脚,配置为备用功能1。PA10为USART0的RX引脚,配置为复用功1。
//PA9-USART0-TX
gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_9); //选择备用功能1
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9 );
gpio_output_options_set(GPIOA,GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_9);//PA10-USART0-RX
gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_10); //选择备用功能1
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_10 );
例子4:配置PB0为ADC通道
//模拟模式
gpio_mode_set(GPIOB, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0);