GPIO内部结构
GPIO输入模式
(1)浮空输入模式
图中施密特触发器是开启的,IO口的状态可以直接送到输入寄存器中,CPU可以直接读取输入寄存器;
在上图中,阴影的部分处于不工作状态,尤其是下半部分的输出电路,实际上是与端口处于隔离状态。
黄色的高亮部分显示了数据传输通道,外部的电平信号通过左边编号1的IO端口进入STM32,经过编号2的施密特触发器的整形送入编号3的输入数据寄存器,在输入数据寄存器的另一端编号4,CPU可以随时读出IO端口的电平状态
(2)上拉输入模式
上图是STM32的GPIO带上拉输入模式的配置。与前面的浮空输入模式相比,仅仅是在数据通道上部,接入了一个上拉电阻,根据STM32的数据手册,这个上拉电阻阻值介于30K~50K。
同样,CPU可以随时在输入数据寄存器的另一端,读出IO端口的电平状态。
(3)下拉输入模式
(4)模拟输入模式
施密特触发器是关闭的,信号直接到ADC输入;
STM32的模拟输入通道的配置则更加简单,信号从左边编号1的端口进入,从右边编号2的一端直接进入ADC模块。
这里我们看到所有的上拉、下拉电阻和施密特触发器,均处于断开状态,因此输入数据寄存器将不能反映端口上的电平状态,也就是说,模拟输入配置下,CPU不能在输入数据寄存器上读到有效的数据。
GPIO输出模式
(1)开漏输出模式 GPIO_OType_OD
当CPU在编号1端通过“位设置/清楚寄存器”或“输出数据寄存器”写入数据后,该数据位通过编号2的输出控制电路传送到编号4的IO端口。
如果CPU写入的是逻辑1,则编号3的N-MOS管将处于关闭状态,此时IO端口的电平将由外部的上拉电阻决定,如果CPU写入的是逻辑0,则编号3的N-MOS管将处于开启状态,此时IO端口的电平被编号3的N-MOS管拉到了VSS的零电位。
在上图的上半部,施密特触发器处于开启状态,这意味着CPU可以在“输入数据寄存器”的另一端,随时监控IO端口的状态;通过这个特性,还实现了虚拟的IO端口双向通信,只要CPU输出逻辑1,由于编号3的N-MOS管处于关闭状态,IO端口的电平将完全由外部电路决定,因此,CPU可以在“输入数据寄存器”读到外部电路的信号,而不是它自己输出的逻辑1。
GPIO口的输出模式下,有3种输出速度可选(2MHz、10MHz和50MHz),这个速度是指GPIO口驱动电路的响应速度,而不是输出信号的速度,输出信号的速度与程序有关(芯片内部在IO口的输出部分安排了多个响应速度不同的输出驱动电路,用户可以根据自己的需要选择合适的驱动电路)。通过选择速度来选择不同的输出驱动模块,达到最佳的噪声控制和降低功耗的目的。高频的驱动电路,噪声也高,当不需要高的输出频率时,请选用低频驱动电路,这样非常有利于提高系统的EMI性能。当然如果要输出较高的频率的信号,但却选用了较低频率的驱动模块,很可能会得到失真的输出信号。
开漏输出:开漏输出就是不输出电压,低电平时接地,高电平时不接地。如果外接上拉电阻,则在输出高电平时电压会拉到上拉电阻的电源电压。这种方式适合在连接的外设电压比单片机电压低的时候。
a、只能输出低电平,不能输出高电平。如果要输出高电平,则需要外接上拉。
b、开漏输出具有“线与”功能,一个为低,全部为低,多用于I2C和SMBUS总线。
(2)开漏复用输出模式
(3)推挽输出模式 GPIO_OType_PP
推挽输出:推挽输出就是单片机引脚可以直接输出高电平电压。低电平时接地,高电平时输出单片机电源电压。这种方式可以不接上拉电阻。但如果输出端可能会接地的话,这个时候输出高电平可能引发单片机运行不稳定,甚至可能烧坏引脚。推挽方式的驱动力更大。
a、可以输出高低电平,用于连接数字器件,高电平由VDD决定,低电平由VSS决定。
b、推挽结构指两个三极管受两路互补的信号控制,总是在一个导通的时候另外一个截止,优点开关效率效率高,电流大,驱动能力强。
c、输出高电平时,电流输出到负载,叫灌电流,可以理解成推,输出低电平时,负载电流流向芯片,叫拉电流,即挽。
(4)推挽复用输出模式
GPIO推挽复用输出模式,编号2的输出控制电路的输入,与复用功能的输出端相连,此时输出数据寄存器被从输出通道断开了,并和片上外设的输出信号连接。我们将GPIO配置成复用输出功能后,如果外设没有被激活,那么它的输出将不确定,其它部分与前述模式一致,包括对“输入数据寄存器”的读取。
3、应用场合
①上拉输入、下拉输入可以用来检测外部信号;例如,按键等;
②浮空输入模式,由于输入阻抗较大,一般把这种模式用于标准通信协议的I2C、USART的接收端;
③普通推挽输出模式一般应用在输出电平为0和3.3V的场合。而普通开漏输出模式一般应用在电平不匹配的场合,如需要输出5V的高电平,就需要在外部一个上拉电阻,电源为5V,把GPIO设置为开漏模式,当输出高阻态时,由上拉电阻和电源向外输出5V电平。
④对于相应的复用模式,则是根据GPIO的复用功能来选择,如GPIO的引脚用作串口的输出,则使用复用推挽输出模式。如果用在IC、SMBUS这些需要线与功能的复用场合,就使用复用开漏模式。
⑤在使用任何一种开漏模式时,都需要接上拉电阻。
GPIO用到的函数
void gpio_deinit(uint32_t gpio_periph) // reset GPIO port
void gpio_mode_set(uint32_t gpio_periph, uint32_t mode, uint32_t pull_up_down, uint32_t pin) //set GPIO mode
void gpio_output_options_set(uint32_t gpio_periph, uint8_t otype, uint32_t speed, uint32_t pin)//set GPIO output type and speed
void gpio_bit_set(uint32_t gpio_periph, uint32_t pin) //set GPIO pin bit
void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin) //reset GPIO pin bit
void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value) //write data to the specified GPIO pin
void gpio_port_write(uint32_t gpio_periph, uint16_t data)//write data to the specified GPIO port
FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin) //get GPIO pin input status
uint16_t gpio_input_port_get(uint32_t gpio_periph) //get GPIO all pins input status
FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin) //get GPIO pin output status
uint16_t gpio_output_port_get(uint32_t gpio_periph) //get GPIO all pins output status
void gpio_af_set(uint32_t gpio_periph, uint32_t alt_func_num, uint32_t pin) //set GPIO alternate function
void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin) //lock GPIO pin bit
void gpio_bit_toggle(uint32_t gpio_periph, uint32_t pin) //toggle GPIO pin s
void gpio_port_toggle(uint32_t gpio_periph) //toggle GPIO port status
时钟树
时钟源
可以选择
内部8MHz时钟源(IRC8M)、外部4~32MHz高速时钟源(HXTAL)、内部48MHz高速时钟源(IRC48M),并且可以经过PLL进行倍频。
CK_SYS(即系统时钟)配置方法有三种,当SCS寄存器配置为00时,CK_SYS为8MHz(内部8MHz直连);当SCS寄存器配置为01时,CK_SYS为外部高速时钟源的频率,即与外部高速时钟直连;当SCS寄存器配置为10时,CK_SYS为时钟源经过PLL倍频获得的频率值。
选择时钟源:void rcu_system_clock_source_config(uint32_t ck_sys)
configure the system clock source
ck_sys: system clock source select
only one parameter can be selected which is shown as below:
RCU_CKSYSSRC_IRC8M: select CK_IRC8M as the CK_SYS source
RCU_CKSYSSRC_HXTAL: select CK_HXTAL as the CK_SYS source
RCU_CKSYSSRC_PLL: select CK_PLL as the CK_SYS source
AHB、APB1、APB2、PLL配置
void rcu_ahb_clock_config(uint32_t ck_ahb)
/*!
rief configure the AHB clock prescaler selection
param[in] ck_ahb: AHB clock prescaler selection
only one parameter can be selected which is shown as below:
arg RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512
param[out] none
etval none
*/
void rcu_apb1_clock_config(uint32_t ck_apb1)
/*!
rief configure the APB1 clock prescaler selection
param[in] ck_apb1: APB1 clock prescaler selection
only one parameter can be selected which is shown as below:
arg RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1
arg RCU_APB1_CKAHB_DIV2: select CK_AHB/2 as CK_APB1
arg RCU_APB1_CKAHB_DIV4: select CK_AHB/4 as CK_APB1
arg RCU_APB1_CKAHB_DIV8: select CK_AHB/8 as CK_APB1
arg RCU_APB1_CKAHB_DIV16: select CK_AHB/16 as CK_APB1
param[out] none
etval none
*/
void rcu_apb2_clock_config(uint32_t ck_apb2)
/*!
rief configure the APB2 clock prescaler selection
param[in] ck_apb2: APB2 clock prescaler selection
only one parameter can be selected which is shown as below:
arg RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2
arg RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2
arg RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2
arg RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2
arg RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2
param[out] none
etval none
*/
void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul);
/*!
rief configure the PLL clock source selection and PLL multiply factor
param[in] pll_src: PLL clock source selection
only one parameter can be selected which is shown as below:
arg RCU_PLLSRC_IRC8M_DIV2: select CK_IRC8M/2 as PLL source clock
arg RCU_PLLSRC_HXTAL: select HXTAL as PLL source clock
param[in] pll_mul: PLL multiply factor
only one parameter can be selected which is shown as below:
arg RCU_PLL_MULx(x=2..32): PLL source clock * x
param[out] none
etval none
*/