STM32复习之GPIO

序言

        学完32之后,总感觉基础还不是很扎实,所以特意打算写一系列的文章来夯实以及总结一下在此期间编程遇到的迷惑与收获。比较适合小白入门以及学完总结的读者,还请多多建议以及留言讨论。

一、什么是GPIO 

        GPIO是我在学32的接触到的第一个外设部件,刚开始根据定义以及自己在网上找的资料,自己理解的是引脚,但是学完组成原理,搞明白了很多。

GPIO与引脚的区别?

        我们都知道单片机上都有很多引脚(PIN),这些引脚是芯片物理外接的管脚,包括一些如:电源VCC、GND、晶振接线以外,还剩下一些带PA0、PA1等等这些字样的引脚,这些引脚有两种功能:

        1、作为各种模块的引脚。比如外接一个超声波模块,其中模块上的Echa、Trig两个引脚就可以连接到单片机上的某两个引脚。这两个引脚就是功能引脚。

        2、定义为GPIO。可以定义为输入/输出,来作为操作控制位,实现对某个模块的操作,比如点亮一颗LED灯

概念

        所以聊完两者的区别就来看一下GPIO的概念:

G(General)P(Purpose)I(input)O(Outout):通用输入输出口。

用于感知外界信号(输入模式:用以读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等)和控制外部设备(输出模式:输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等)。

总之,STM32芯片的GPIO引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。

介绍完了它的概念,那下面就是详细了解它的结构

特点

1、IO电平兼容性好:3.3V兼容5V电平;

2、IO驱动能力强:每个口最大可吸收25mA电流;

3、IO口可配置上拉、下拉电阻;

4、每个IO口可配置为外部中断;

5、具有独立的唤醒IO口;

6、IO口具有锁存功能;

7、具有侵入检测引脚。

8、IO口具有AFIO功能:GPIO的复用功能,最大限度的利用端口资源。

IO口速度

一般IO口速度决定的是IO口反转速度,也就是高低电平转换一次的时间。

typedef enum
{ 
 GPIO_Speed_10MHz = 1,
 GPIO_Speed_2MHz, 
 GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;

二、结构

外部

STM32F103一共有4组端口PA、PB、PC、PD,都挂载在APB2总线可以看这篇文章了解上。这样的好处不仅仅是容易管理也容易引用这些引脚。寄存器的每一位都对应一个引脚,输出寄存器写1,对应的引脚输出高电平,写0,就输出低电平;输入寄存器读取1,对应的端口目前是高电平,读取0,就是低电平。只有寄存器低16位对应有端口,高16位没有用到,而驱动器是用来增加驱动能力的。 

当时看到端口和引脚的时候就又懵了,两者的区别又是啥呢?

端口和引脚的区别?

端口是单片机内部(CPU单元)和外部IO的接口组,比如说PA端口,有8个引脚PA0~PA7。端口在IO空间映射有寄存器,这个寄存器反映当前端口的状态,如PA0口上输入的电压是0~5V的信号,单片机在映射进寄存器时会定义一个门限(如1.8V),低于这个门限寄存器中相应位是0,高于这个门限相应位是1。一般端口还有其他控制寄存器,如控制端口引脚输入输出的寄存器,如控制端口引脚复用的寄存器等。当设置端口引脚为输出时,向相应的输出寄存器的相应位写1,该端口的对应IO引脚就会输出一个近似VCC的电平,当向相应位写0时,该端口的对应IO引脚会输出一个近似0V的电平。

PS:这一段话,看着有点烦,但是仔细读的话,会有收获的,其实就是怎么读写1/0。

到这时,明白了外部结构是怎么回事,那其中的内部结构呢?

内部

下图是从右往左看,同时我们讲解的顺序也是很如此,便于由外到内的理解。

图中除了最右端 I/O 端口是STM32 芯片的引脚,其它部分都在 STM32 芯片内部

1、保护二极管

引脚内部加上这两个保护二极管,就可以避免引脚的电压输入过高过低

过高:当引脚电压高于 VDD_FT 或 VDD 时,上方的二极管导通吸收这个高电压

过低:当引脚电压低于 VSS 时,下方的二极管导通,防止不正常电压引入芯片导致芯片烧毁

STM32 芯片内部有这样的保护,但并不意味着STM32 的引脚就无所不能,比如电机,那么要么电机不转,要么烧坏芯片。因此若要驱动一些大功率器件,必须要加大功率及隔离电路驱动。也可以说STM32引脚是用来做控制,而不是做驱动使用的

VDD_FT是和5V容忍I/O相关电位,与VDD不同可以看这篇文章了解)(注:转载自“江南侠客(上海)”)

将其简化为下图:

钳位二极管图

当该点电压超过VDD+VD1(0.7V)时,上面的二极管导通。而当该点电压小于-VD2(-0.7V)时,下面的二极管导通。因此,该点电压被钳制在VDD+VD1到-VD2间。

2、上下拉电阻

上拉和下拉电阻上都有一个开关,通过配置上下拉电阻开关,可以控制引脚的默认状态电平。这 个其实就是正点原子那款MiniSTM32单片机三个按键控制电平不同的原因。

当开启上拉时引脚默认电压为高电平,开启下拉时,引脚默认电压为低电平,这样可以消除引脚不定状态的影响。当然可以开关也可以都断开,这样就进入了一种引脚不定状态,这就是浮空模式(这些会在下面的输入输出模式部分详细讲解)万用表测量浮空模式下管脚电压时会发现只有1 点几伏,而且还不时改变。

3、P-MOS 和 和  N-MOS 

GPIO 引脚经过两个保护二极管后就分成两路,上面一路是经过输入驱动器为“输入模式”,下面一路经过输出驱动器为“输出模式”。

主要作用就是配置推挽和开漏输出两种模式

可以将P-MOS 看作NPN三极管,N-MOS看作PNP 三极管

 推挽输出模式

输入一个高电平时,P-MOS 管导通,N-MOS 管截止,对外输出高电平(3.3V)

输入一个低电平时,P-MOS 管截止,N-MOS 管导通,对外输出低电平(0V)

如果当切换输入高低电平时,两个MOS 管将轮流导通,一个负责灌电流(电流输出到负载),一个负责拉电流(负载电流流向芯片),使其负载能力和开关速度都比普通的方式有很大的提高。

开漏输出模式

不论输入是高电平还是低电平,P-MOS 管总处于关闭状态。

当给这个单元电路输入低电平时,N-MOS 管导通,输出即为低电平。当输入高电平时,N-MOS 管截止,这个时候引脚状态既不是高电平,又不是低电平,我们称之为高阻态。如果想让引脚输出高电平,那么引脚必须外接一个上拉电阻,由上拉电阻提供高电平。开漏输出模式等效电路图如图所示。

4、输出数据寄存器(ODR)

双 MOS 管结构电路的输入信号,是由 GPIO“输出数据寄存器GPIOx_ODR”提供的,因此我们通过修改输出数据寄存器的值就可以修改 GPIO 引脚的输出电平。

“置位/复位寄存器 GPIOx_BSRR”可以通过修改输出数据寄存器的值从而影响电路的输出。该寄存器是只写寄存器,通过写入 “置位/复位寄存器GPIOx_BSRR”状态,可分别对 “输出数据寄存器GPIOx_ODR” 进行置位和复位。

既然ODR 能控制管脚高低电平,为什么还需要BSRR寄存器?

意法半导体给的答案就是用BSRR去改变管脚状态的时候是原子操作置位/复位,没有被中断打断的风险。也就不需要关闭中断,关闭中断明显会延迟或丢失一事件的捕获,所以控制GPIO的状态最好可以用BSRR。

5、复用功能输出

STM32 的GPIO 引脚不仅仅可以用作普通IO输出电平进行控制,还可以用作芯片上其他外设的复用功能。因此当使用复用功能的时候,也就是通过其他外设复用功能输出信号与 GPIO 数据寄存器一起连接到双 MOS 管电路的输入,其中其中信号在进入输出控制缓冲器之前是用来选择使用复用功能还是普通 IO 口功能

例如我们使用 USART 串口通讯时,需要用到某个 GPIO 引脚作为通讯发送引脚,这个时候就可以把该 GPIO 引脚配置成 USART 串口复用功能,由串口外设控制该引脚,发送数据。

具体使用的GPIO口具备哪些复用功能,可以查阅具体的芯片手册得到

6、输入数据寄存器(IDR)

首先在介绍这个输入数据寄存器之前,应该熟悉一下施密特触发器是什么?

 施密特触发器是什么?

1、当输入电压高于正向阈值电压,输出为

2、当输入电压低于负向阈值电压,输出为

3、当输入在正负向阈值电压之间,输出不改变

基于上述特性, 施密特触发器可作为波形整形电路,能将模拟信号波形整形为数字电路能够处理的方波波形,而且由于施密特触发器具有滞回特性,所以可用于抗干扰

 输入数据寄存器是由IO口经过上下拉电阻、TTL施密特触发器引入。当信号经过TTL施密特触发器,模拟信号将变为数字信号0 或1,然后存储在输入数据寄存器中,通过读取“输入数据寄存器GPIOx_IDR” 就可以知道IO 口的电平状态。

7、复用功能输入(AFIO)

 复用功能输入和复用功能输出类似。在复用功能输入模式时,GPIO 引脚的信号传输到STM32芯片上其它外设,由该外设读取引脚的状态。同样,如我们使用USART 串口通讯时,需要用到某个GPIO 引脚作为通讯接收引脚,这个时候就可以把该GPIO 引脚配置成USART 串口复用功能,使USART 可以通过该通讯引脚的接收外部通信线上的数据。

8、模拟输入输出(AD)

一般用于ADCDAC两种功能,  当GPIO 引脚用于ADC 采集电压的输入通道时,用作“模拟输入”功能,如图所示

此时信号是不经过施密特触发器的,因为经过施密特触发器后信号只有0或1 两种状态,ADC 外设要采集到原始的模拟信号,信号源输入必须在施密特触发器之前。

同理,当GPIO 引脚用于DAC 作为模拟电压输出通道时,此时作为“模拟输出”功能,如图所示DAC 的模拟信号输出就不经过双MOS 管结构了,模拟信号直接通过管脚输出。

三、工作模式

上面介绍了GPIO的结构,不仅仅是为了让大家了解的更深入,也是为了让大家更好的理解GPIO的工作模式,因为 GPIO 内部的结构关系,决定了 GPIO 可以配置成以下几种模式。我在之前编程的时候,对于GPIO的初始化都是复制粘贴性质的

//复用推挽
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;

里面的工作模式也只是在第一次学的时候,了解了一下,后面再用的时候感觉没有多大区别,但是在用的是总感觉存在即合理,一定是自己没有学到位,做项目没有做到那些底层的,所以这次也是在重新复习一下。

工作模式的分类
工作模式的分类

输入模式

上拉输入(GPIO_Mode_IPU)

数字输入,可读取引脚电平,内部连接上拉电阻,悬空时默认高电平

上拉就是通过上拉电阻把电位拉高,比如拉到VDD(芯片电源电压,VCC是电源电压),将输入的不确定的信号嵌位在高电平(按下时那段既不是0也不是1的强制变为1)。

下拉输入(GPIO_Mode_IPD)

数字信号,可读取引脚电平,内部连接下拉电阻,悬空时默认低电平

下拉就是把电压拉低,拉到GND(VSS接地),下拉电阻另一端接地即可。原理上与上拉一样。(按下时那段既不是高电平也不是低电平的,非0非1的强制变为0)。

浮空输入(GPIO_Mode_IN_FLOATING)

数字输入,可读取引脚电平,若引脚悬空,则电平不确定

逻辑器件与引脚既不接高电平,也不接低电平,相当于浮在空中呈高阻态,上面用绳子一拉就上去了,下面用绳子一拉就沉下去了,一般来做ADC(模电转换中将模拟信号转换为数字信号)的输入用,这样可以减少上下拉电阻对结果的影响。

模拟输入(GPIO_Mode_AIN)

模拟输入,GPIO无效,引脚直接接入内部ADC

模拟输入模式直接接受模拟电压信号,其中模拟电压输入范围在0V~Vref(标准参考电压)之间,由于STM32芯片供电电压为3.3V,所以模拟输入电压的输入不超过3.3V。

输出模式

开漏输出(GPIO_Mode_OUTPUT_OD)

数字输出,可输出引脚电平,高电平为高阻态,低电平接VSS

开漏输出时不管输出0还是1,P-MOS管始终处于截止(断电)状态。输出低电平0时,下面的N-MOS管导通;输出高电平1时,下面的N-MOS管截止,高电平得靠人为设计外部电阻拉高。输出端相当于三极管的集电极。要得到高电平状态需要上拉电阻才行。适合于做低电平电流型的驱动(低电平电平可以输出较强的驱动电流,而高电仅靠外部上拉电阻维持高电平而驱动能力弱。一般用于低电平驱动电路。比如:0让灯亮,1让灯不亮),其吸收电流的能力相对强(一般20mA以内,最大25mA)。

复用开漏输出(GPIO_Mode_OUTPUT_OD)

数字输出,由片上外设控制,高电平为高阻态,低电平接VSS

推挽输出(GPIO_Mode_OUTPUT_PP)

数字输出,可输出引脚电平,高电平接VDD,低电平接VSS

输出低电平0时,输出的P-MOS管截止、而下面的N-MOS管导通;输出高电平1时,输出的P-MOS管导通、而下面的N-MOS管截止。高低电平电平都可以输出较强的驱动电流。常用于数字电平的输出。

最大特点是可以真正能真正的输出高电平和低电平,在两种电平下都具有驱动能力,输出高电平时的驱动能力强很多。对于开漏输出和推挽输出的区别最普遍的说法就是开漏输出无法真正输出高电平,即高电平时没有驱动能力,需要借助外部上拉电阻完成对外驱动。

复用推挽输出(GPIO_Mode_OUTPUT_PP)

数字输出,由片上外设控制,高电平接VDD,低电平接VSS

 代码

typedef enum
{ GPIO_Mode_AIN = 0x0,         //模拟输入
 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;

四、相关寄存器

typedef struct
{
  __IO uint32_t CRL;    //端口配置低寄存器(GPIOx_CRL)
  __IO uint32_t CRH;    //端口配置高寄存器(GPIOx_CRH)
  __IO uint32_t IDR;    //端口输入数据寄存器(GPIOx_IDR)
  __IO uint32_t ODR;    //端口输出数据寄存器(GPIOx_ODR)
  __IO uint32_t BSRR;   //端口位设置/清除寄存器(GPIOx_BSRR)
  __IO uint32_t BRR;    //端口位清除寄存器(GPIOx_BRR)
  __IO uint32_t LCKR;   //端口配置锁定寄存器(GPIOx_LCKR)
} GPIO_TypeDef;

五、GPIO使用

1、配置GPIO 时钟,完成初始化。
2、利用函数GPIO_Init配置引脚,包括引脚名称、引脚传输速率、引脚工作模式。
3、完成GPIO_Init 的设置

 void LED_GPIO_Config(void)
{		
		GPIO_InitTypeDef GPIO_InitStructure;/*定义一个GPIO_InitTypeDef类型的结构体*/
		
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);/*开启LED相关的GPIO外设时钟*/

		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;/*选择要控制的GPIO引脚*/	
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;/*设置引脚模式为通用推挽输出*/   
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;/*设置引脚速率为50MHz */    
		GPIO_Init(GPIOB, &GPIO_InitStructure);/*调用库函数,初始化GPIO*/	
}

IO 复用功能AFIO配置

IO复用功能AFIO常对应到外设的输入输出功能。使用时,需要先配置IO 为复用功能,打开AFIO时钟,然后再根据不同的复用功能进行配置。对应外设的输入输出功能有下述三种情况:
1、外设对应的引脚为输出:需要根据外围电路的配置选择对应的引脚为复用功能的推挽输出或复用功能的开漏输出。
2、外设对应的引脚为输入:根据外围电路的配置可以选择浮空输人、带上拉输入或带下拉输人。
3、ADC对应的引脚:配置引脚为模拟输入。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

岂有此李呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值