GPIO

STM32F1xx官方资料:
《STM32中文参考手册V10》-第8章通用和复用功能IO(GPIO和AFIO )
芯片数据手册(datasheet)

STM32的GPIO介绍

STM32引脚说明

GPIO是通用输入/输出端口的简称,是STM32可控制的引脚。GPIO的引脚与外部硬件设备连接,可实现与外部通讯、控制外部硬件或者采集外部硬件数据的功能。

STM32F103ZET6芯片为144脚芯片,包括7个通用目的的输入/输出口(GPIO)组,分别为GPIOA、GPIOB、GPIOC、GPIOD、GPIOE、GPIOF、GPIOG,同时每组GPIO口组有16个GPIO口。通常简略称为PAx、PBx、PCx、PDx、PEx、PFx、PGx,其中x为0-15。

STM32的大部分引脚除了当GPIO使用之外,还可以复用位外设功能引脚(比如串口),这部分在【STM32】STM32端口复用和重映射(AFIO辅助功能时钟) 中有详细的介绍。

GPIO基本结构

每个GPIO内部都有这样的一个电路结构,这个结构在本文下面会具体介绍。


这边的电路图稍微提一下:

保护二极管:IO引脚上下两边两个二极管用于防止引脚外部过高、过低的电压输入。当引脚电压高于VDD时,上方的二极管导通;当引脚电压低于VSS时,下方的二极管导通,防止不正常电压引入芯片导致芯片烧毁。但是尽管如此,还是不能直接外接大功率器件,须加大功率及隔离电路驱动,防止烧坏芯片或者外接器件无法正常工作。

P-MOS管和N-MOS管:由P-MOS管和N-MOS管组成的单元电路使得GPIO具有“推挽输出”和“开漏输出”的模式。这里的电路会在下面很详细地分析到。
TTL肖特基触发器:信号经过触发器后,模拟信号转化为0和1的数字信号。但是,当GPIO引脚作为ADC采集电压的输入通道时,用其“模拟输入”功能,此时信号不再经过触发器进行TTL电平转换。ADC外设要采集到的原始的模拟信号。

这里需要注意的是,在查看《STM32中文参考手册V10》中的GPIO的表格时,会看到有“FT”一列,这代表着这个GPIO口时兼容3.3V和5V的;如果没有标注“FT”,就代表着不兼容5V。

STM32的GPIO工作方式

GPIO支持4种输入模式(浮空输入、上拉输入、下拉输入、模拟输入)和4种输出模式(开漏输出、开漏复用输出、推挽输出、推挽复用输出)。同时,GPIO还支持三种最大翻转速度(2MHz、10MHz、50MHz)。

每个I/O口可以自由编程,但I/O口寄存器必须按32位字被访问。

1. GPIO_Mode_AIN 模拟输入

2. GPIO_Mode_IN_FLOATING 浮空输入

3. GPIO_Mode_IPD 下拉输入

4. GPIO_Mode_IPU 上拉输入

5. GPIO_Mode_Out_OD 开漏输出

6. GPIO_Mode_Out_PP 推挽输出

7. GPIO_Mode_AF_OD 复用开漏输出

8. GPIO_Mode_AF_PP 复用推挽输出

下面将具体介绍GPIO的这八种工作方式:

浮空输入模式


浮空输入模式下,I/O端口的电平信号直接进入输入数据寄存器。也就是说,I/O的电平状态是不确定的,完全由外部输入决定;如果在该引脚悬空(在无信号输入)的情况下,读取该端口的电平是不确定的。

上拉输入模式


上拉输入模式下,I/O端口的电平信号直接进入输入数据寄存器。但是在I/O端口悬空(在无信号输入)的情况下,输入端的电平可以保持在高电平;并且在I/O端口输入为低电平的时候,输入端的电平也还是低电平。

下拉输入模式


下拉输入模式下,I/O端口的电平信号直接进入输入数据寄存器。但是在I/O端口悬空(在无信号输入)的情况下,输入端的电平可以保持在低电平;并且在I/O端口输入为高电平的时候,输入端的电平也还是高电平。

模拟输入模式


模拟输入模式下,I/O端口的模拟信号(电压信号,而非电平信号)直接模拟输入到片上外设模块,比如ADC模块等等。

开漏输出模式


开漏输出模式下,通过设置位设置/清除寄存器或者输出数据寄存器的值,途经N-MOS管,最终输出到I/O端口。这里要注意N-MOS管,当设置输出的值为高电平的时候,N-MOS管处于关闭状态,此时I/O端口的电平就不会由输出的高低电平决定,而是由I/O端口外部的上拉或者下拉决定;当设置输出的值为低电平的时候,N-MOS管处于开启状态,此时I/O端口的电平就是低电平。同时,I/O端口的电平也可以通过输入电路进行读取;注意,I/O端口的电平不一定是输出的电平。

开漏复用输出模式


开漏复用输出模式,与开漏输出模式很是类似。只是输出的高低电平的来源,不是让CPU直接写输出数据寄存器,取而代之利用片上外设模块的复用功能输出来决定的。

推挽输出模式


推挽输出模式下,通过设置位设置/清除寄存器或者输出数据寄存器的值,途经P-MOS管和N-MOS管,最终输出到I/O端口。这里要注意P-MOS管和N-MOS管,当设置输出的值为高电平的时候,P-MOS管处于开启状态,N-MOS管处于关闭状态,此时I/O端口的电平就由P-MOS管决定:高电平;当设置输出的值为低电平的时候,P-MOS管处于关闭状态,N-MOS管处于开启状态,此时I/O端口的电平就由N-MOS管决定:低电平。同时,I/O端口的电平也可以通过输入电路进行读取;注意,此时I/O端口的电平一定是输出的电平。

推挽复用输出模式


推挽复用输出模式,与推挽输出模式很是类似。只是输出的高低电平的来源,不是让CPU直接写输出数据寄存器,取而代之利用片上外设模块的复用功能输出来决定的。

总结与分析

1、什么是推挽结构和推挽电路?

推挽结构一般是指两个参数相同的三极管或MOS管分别受两互补信号的控制,总是在一个三极管或MOS管导通的时候另一个截止。高低电平由输出电平决定。

推挽电路是两个参数相同的三极管或MOSFET,以推挽方式存在于电路中,各负责正负半周的波形放大任务。电路工作时,两只对称的功率开关管每次只有一个导通,所以导通损耗小、效率高。输出既可以向负载灌电流,也可以从负载抽取电流。推拉式输出级既提高电路的负载能力,又提高开关速度。

2、开漏输出和推挽输出的区别?

开漏输出:只可以输出强低电平,高电平得靠外部电阻拉高。输出端相当于三极管的集电极。适合于做电流型的驱动,其吸收电流的能力相对强(一般20ma以内);

推挽输出:可以输出强高、低电平,连接数字器件。

关于推挽输出和开漏输出,最后用一幅最简单的图形来概括:


该图中左边的便是推挽输出模式,其中比较器输出高电平时下面的PNP三极管截止,而上面NPN三极管导通,输出电平VS+;当比较器输出低电平时则恰恰相反,PNP三极管导通,输出和地相连,为低电平。右边的则可以理解为开漏输出形式,需要接上拉。

3、在STM32中选用怎样选择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_PP ——片内外设功能(I2C的SCL、SDA)

复用功能的开漏输出_AF_OD——片内外设功能(TX1、MOSI、MISO.SCK.SS)

来源:CSDN,作者:Yngz_Miao
原文:https://blog.csdn.net/qq_38410730/article/details/79858906
版权声明:本文为博主原创文章,转载请附上博文链接!

围观 538

一、CMSIS标准

ST公司的stm32采用的是cortex-m3内核,内核是整个微处理器的CPU。该内核是ARM公司设计的一种处理器体系架构。内核与外设的关系就像PC上的CPU与硬盘、主板、内存等的关系一样。

基于cortex系列的处理器内核都是一样的,区别在于除内核以外的外设的差异,由于这些差异,导致不同处理器移植起来比较麻烦,所以ARM与芯片厂商建立了CMSIS标准,CMSIS架构如下所示:

stm32之CMSIS标准、库目录、GPIO

CMSIS标准中最主要的是CMSIS核心层;内核函数层中的内核函数寄存器以及地址主要由ARM公司提供;设备外设访问层核外外设和中断寄存器地址由芯片生产厂商定义。

二、库目录和文件简介

1、core_cm3.c文件

在CoreSupport文件夹中有core_cm3.c和头文件core_cm3.h,它的作用是采用Cortex-M3内核设计的SoC芯片厂商设计的芯片提供了一个进入CM3内核的接口。core_cm3.c中还有一些与编译器(MDK、IAR等)有关的代码。较重要的是core_cm3.c中包含stdio.h头文件,这是一个ANSI C文件,主要作用是提供一些新类型的定义。

2、system_stm32f10x.c文件

DeviceSupport文件夹下是启动文件、外设寄存器定义、中断向量定义层的一些文件,这些文件由ST公司提供。system_stm32f10x.c的主要作用是设置系统时钟和总线时钟。

3、stm32f10x.h文件

这个文件非常重要,是非常底层的文件,包含了寄存器地址和结构体类型的定义,在使用到stm32固件库的地方都要包含它。

3、stm32f10x_it.c和stm32f10x_conf.h文件

stm32f10x_it.c这个文件主要是编写中断程序的,stm32f10x_conf.h被包含在stm32f10x.h文件中主要是配置外设的头文件,我们需要什么在这里打开。

4、startup_stm32f10x_hd.s文件

在这个文件中有一段启动文件,启动文件中先初始化系统时钟,然后才执行主函数,因此我们要注意配置时钟在这个文件里配置。

三、引脚端口的一些概念

1、一些寄存器

1)配置寄存器:选择是输入还是输出。

2)数据寄存器:保存了GPIO的输入电平或者将要输出的电平。

3)为空值寄存器:设置引脚电平为1或0,控制输出电平。

4)锁定寄存器:设置锁定引脚后,就不能修改其配置。

2、管脚时钟

stm32拥有丰富的时钟系统,我们在配置管教时钟时,如果该管脚要用到其复用功能,我们必须也要初始化复用功能时钟。例如要使用PC1口的AD功能:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);

3、GPIO8种工作模式

1)四种输入模式:上拉输入模式、下拉输入模式、浮空输入模式、模拟输入模式

上拉输入模式(GPIO_Mode_IPU):与VDD相连的为上拉电阻,若引脚配置为上拉输入模式,默认情况下该引脚是高电平。

下拉输入模式(GPIO_Mode_IPD):与VSS相连的为下拉电阻,若引脚配置为下拉输入模式,默认情况下该引脚是低电平。

浮空输入模式(GPIO_Mode_IN_FLOATING):没有上拉电阻也没有下拉电阻,一般这种模式用于标准的通信协议:IIC、USART等的接收端。

模拟输入模式(GPIO_Mode_AIN):使用ADC外设时,接口必须设置为,模拟输入模式。

2)四种输出模式:推挽输出模式、开漏输出模式、复用推挽输出模式、复用开漏输出模式

推挽输出模式(GPIO_Mode_Out_PP):一般用于0和3.3伏的场合。

开漏输出模式(GPIO_Mode_Out_OD):一般用于电平不平衡的场合。

任何一种开漏模式都要接上拉电阻。

复用推挽输出模式(GPIO_Mode_AF_PP)

复用开漏输出模式(GPIO_Mode_AF_OD)

4、中断

stm32有100个引脚,GPIO口总共80个,分为GPIOA~GPIOE 5组,每组16个。每个IO口都可以作为中断源的输入,可以配置为上升沿中断,下降沿中断,上升沿下降沿中断.

本文转载自:博客园 - xtusir

围观 465

GPIO的功能,简单说就是可以根据自己的需要去配置为输入或输出。但是在配置GPIO管脚的时候,常会见到两种模式:开漏(open-drain,漏极开路)和推挽(push-pull)。

Push-Pull推挽输出

输出的器件是指输出脚内部集成有一对互补的MOSFET,当Q1导通、Q2截止时输出高电平;而当Q1截止导通、Q2导通时输出低电平

Push-pull输出,实际上内部是用了两个晶体管(transistor),此处分别称为top transistor和bottom transistor。通过开关对应的晶体管,输出对应的电平。top transistor打开(bottom transistor关闭),输出为高电平;bottom transistor打开(top transistor关闭),输出低电平。Push-pull即能够漏电流(sink current),又可以集电流(source current)。其也许有,也许没有另外一个状态:高阻抗(high impedance)状态。除非Push-pull需要支持额外的高阻抗状态,否则不需要额外的上拉电阻。

Open-Drain开漏输出

开漏电路就是指以MOSFET的漏极为输出的电路。指内部输出和地之间有个N沟道的MOSFET(Q1),这些器件可以用于电平转换的应用。输出电压由Vcc'决定。Vcc'可以大于输入高电平电压VCC(up-translate)也可以低于输入高电平电压VCC(down-translate)。

Open-drain输出,则是比push-pull少了个top transistor,只有那个bottom transistor。(就像push-pull中的那样)当bottom transistor关闭,则输出为高电平。此处没法输出高电平,想要输出高电平,必须外部再接一个上拉电阻(pull-up resistor)。Open-drain只能够漏电流(sink current),如果想要集电流(source current),则需要加一个上拉电阻。

老外的理解

常见的GPIO的模式可以配置为open-drain或push-pull,具体实现上,常为通过配置对应的寄存器的某些位来配置为open-drain或是push-pull。当我们通过CPU去设置那些GPIO的配置寄存器的某位(bit)的时候,其GPIO硬件IC内部的实现是,会去打开或关闭对应的top transistor。相应地,如果设置为了open-d模式的话,是需要上拉电阻才能实现,也能够输出高电平的。因此,如果硬件内部(internal)本身包含了对应的上拉电阻的话,此时会去关闭或打开对应的上拉电阻。如果GPIO硬件IC内部没有对应的上拉电阻的话,那么你的硬件电路中,必须自己提供对应的外部(external)的上拉电阻。而push-pull输出的优势是速度快,因为线路(line)是以两种方式驱动的。而带了上拉电阻的线路,即使以最快的速度去提升电压,最快也要一个常量的R×C的时间。其中R是电阻,C是寄生电容(parasitic capacitance),包括了pin脚的电容和板子的电容。但是,push-pull相对的缺点是往往需要消耗更多的电流,即功耗相对大。而open-drain所消耗的电流相对较小,由电阻R所限制,而R不能太小,因为当输出为低电平的时候,需要sink更低的transistor,这意味着更高的功耗。(此段原文:because the lower transistor has to sink that current when the output is low; that means higher power consumption.)而open-drain的好处之一是,允许你cshort(?)多个open-drain的电路,公用一个上拉电阻,此种做法称为wired-OR连接,此时可以通过拉低任何一个IO的pin脚使得输出为低电平。为了输出高电平,则所有的都输出高电平。此种逻辑,就是“线与”的功能,可以不需要额外的门(gate)电路来实现此部分逻辑。

图表 4 open-drain“线与”功能

GPIO的推挽输出和开漏输出

GPIO的推挽输出和开漏输出

优点

Push-Pull推挽输出

(1)可以吸电流,也可以贯电流;

(2)和开漏输出相比,push-pull的高低电平由IC的电源低定,不能简单的做逻辑操作等。

Open-Drain开漏输出

(1)对于各种电压节点间的电平转换非常有用,可以用于各种电压节点的Up-translate和down-translate转换

(2)可以将多个开漏输出的Pin脚,连接到一条线上,形成“与逻辑”关系,即“线与”功能,任意一个变低后,开漏线上的逻辑就为0了。这也是I2C,SMBus等总线判断总线占用状态的原理。

(3)利用 外部电路的驱动能力,减少IC内部的驱动。当IC内部MOSFET导通时,驱动电流是从外部的VCC流经R pull-up ,MOSFET到GND。IC内部仅需很下的栅极驱动电流。

(4)可以利用改变上拉电源的电压,改变传输电平:图表 5 open-drain输出电平的原理,IC的逻辑电平由电源Vcc1决定,而输出高电平则由Vcc2决定。这样我们就可以用低电平逻辑控制输出高电平逻辑了。

GPIO的推挽输出和开漏输出

缺点

Push-Pull推挽输出

一条总线上只能有一个push-pull输出的器件;

在CMOS电路里面应该叫CMOS输出更合适,因为在CMOS里面的push-pull输出能力不可能做得双极那么大。输出能力看IC内部输出极N管P管的面积。push-pull是现在CMOS电路里面用得最多的输出级设计方式

Open-Drain开漏输出

开漏Pin不连接外部的上拉电阻,则只能输出低电平。当输出电平为低时,N沟道三极管是导通的,这样在Vcc'和GND之间有一个持续的电流流过上拉电阻R和三极管Q1。这会影响整个系统的功耗。采用较大值的上拉电阻可以减小电流。但是,但是大的阻值会使输出信号的上升时间变慢。即上拉电阻R pull-up的阻值 决定了逻辑电平转换的沿的速度。阻值越大,速度越低功耗越小。反之亦然。

转自: wair-博客

围观 1034

一、STM32中断分组:

STM32 的每一个GPIO都能配置成一个外部中断触发源,这点也是 STM32 的强大之处。STM32 通过根据引脚的序号不同将众多中断触发源分成不同的组,比如:PA0,PB0,PC0,PD0,PE0,PF0,PG0为第一组,那么依此类推,我们能得出一共有16 组,STM32 规定,每一组中同时只能有一个中断触发源工作,那么,最多工作的也就是16个外部中断。STM32F103 的中断控制器支持 19 个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。STM32F103 的19 个外部中断为:

线 0~15:对应外部 IO 口的输入中断。
STM32 GPIO外部中断总结
线 16:连接到 PVD 输出。

线 17:连接到 RTC 闹钟事件。

线 18:连接到 USB 唤醒事件。

二:外部中断的配置过程:

1、配置触发源GPIO口:

因为GPIO口作为触发源使用,所以将GPIO口配置成输入模式,触发模式有以下几种:

a.GPIO_Mode_AIN ,模拟输入(ADC模拟输入,或者低功耗下省电)

b.GPIO_Mode_IN_FLOATING ,浮空输入

c.GPIO_Mode_IPD ,带下拉输入

d.GPIO_Mode_IPU ,带上拉输入 

  GPIO_InitTypeDef GPIO_InitStructure;//定义结构体

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);//使能时钟

  GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_2;//选择IO口   PE2

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//设置成上拉输入

  GPIO_Init(GPIOE, &GPIO_InitStructure);//使用结构体信息进行初始化IO口

2、使能AFIO复用时钟功能:

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); 

3、将GPIO口与中断线映射起来: 

  GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);

4、中断线上进行中断初始化: 

  EXTI_InitTypeDef EXTI_InitStructure;//定义初始化结构体

  EXTI_InitStructure.EXTI_Line=EXTI_Line2; //中断线的标号 取值范围为EXTI_Line0~EXTI_Line15

  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断模式,可选值为中断 EXTI_Mode_Interrupt 和事件 EXTI_Mode_Event。

  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//触发方式,可以是下降沿触发 EXTI_Trigger_Falling,上升沿触发 EXTI_Trigger_Rising,或者任意电平(上升沿和下降沿)触发EXTI_Trigger_Rising_Falling

  EXTI_InitStructure.EXTI_LineCmd = ENABLE;

  EXTI_Init(&EXTI_InitStructure);//根据结构体信息进行初始化

5、中断优先级配置: 

  NVIC_InitTypeDef NVIC_InitStructure;//定义结构体

  NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //使能外部中断所在的通道

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级 2, 

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级 2

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 

  NVIC_Init(&NVIC_InitStructure); //根据结构体信息进行优先级初始化 

6、外部中断服务函数的编写:

外部中断函数分别为:

EXPORT EXTI0_IRQHandler

EXPORT EXTI1_IRQHandler

EXPOR T EXTI2_IRQHandler

EXPORT EXTI3_IRQHandler

EXPORT EXTI4_IRQHandler

EXPORT EXTI9_5_IRQHandler

EXPORT EXTI15_10_IRQHandler

中断线 0-4 每个中断线对应一个中断函数,中断线 5-9 共用中断函数 EXTI9_5_IRQHandler,中断线 10-15 共用中断函数 EXTI15_10_IRQHandler。 

  void EXTI2_IRQHandler(void)
  {
    if(EXTI_GetITStatus(EXTI_Line2)!=RESET)//判断某个线上的中断是否发生 

    {
      中断逻辑…
      EXTI_ClearITPendingBit(EXTI_Line2);   //清除 LINE 上的中断标志位
    }     
  }

三、关于使用GPIO口接按键进行外部中断的配置说明:

使用按键进行外部中断的时候,一般都需要进行按键延时消抖以及松手检测的相关处理,中断函数可以参看以下代码:

  void EXTI2_IRQHandler(void)
  {
    delay_ms(10);//延时消抖
    if(KEY2==0)    //按键真的被按下
      {
        LED0=!LED0;
      }
    while(KEY2!=0);//等待松手
    EXTI_ClearITPendingBit(EXTI_Line2); //清楚中断标志位 
  }

当然,如果你的按键是允许长按功能的,那么就进行别的逻辑操作,这里不作研究。

转自: 粥巴坨的博客

围观 545

GPIO英文全称General-Purpose Input /Output Ports,中文意思是通用I/O端口。由于MCU的通信外设接口众多,不可能每一外设固定一组GPIO,在MCU中,可通过软件运行期间能够动态配置和控制的引脚的状态,所以每个 GPIO 口除了通用输入输出功能外,还可能有其它复用功能。

在MM32L0产品中,每个 GPIO 端口有两个 32 位配置寄存器(GPIOx_CRL, GPIOx_CRH),两个 32 位数据寄存器(GPIOx_IDR 和 GPIOx_ODR),一个 32 位置位/复位寄存器(GPIOx_BSRR),一个 16 位复位寄存器(GPIOx_BRR)、一个 32 位锁定寄存器(GPIOx_LCKR)和两个复用功能选择寄存器(GPIOx_AFRH)和(GPIOx_AFRL)。

GPIO 端口的每个位可以由软件分别配置成多种模式。

• 输入浮空
• 输入上拉
• 输入下拉
• 模拟输入
• 开漏输出
• 推挽式输出
• 推挽式复用功能
• 开漏复用功能

每个 I/O 端口可以自由编程,然而必须按照 32 位字访问 I/O 端口寄存器(不允许半字或字节访问)。GPIOx_BSRR 和 GPIOx_BRR 寄存器允许对任何 GPIO 寄存器进行读/更改的独立访问;这样,在读更改访问之间产生 IRQ 不会发生危险。

初识MM32 GPIO
图1. I/O端口位的基本结构

1、输入浮空详解:
浮空(floating)就是逻辑器件的输入引脚既不接高电平,也不接低电平。一般实际运用时,引脚不建议悬空,易受干扰。

2、输入上拉\下拉详解:
上拉就是把电位拉高,比如拉到Vcc。上拉就是将不确定的信号通过一个电阻拉在高电平!弱强只是上拉电阻的阻值不同,没有什么严格区分。在MM32L0xxx中该上拉电阻位40k欧姆。

3、模拟输入详解:
模拟输入是指模拟信号的输入。配置模拟输入时,所有的上拉、下拉电阻和施密特触发器,均处于禁止状态,因此 “输入数据寄存器”将不能反映端口上的电平状态,也就是说,模拟输入配置下,CPU不能在“输入数据寄存器”上读到有效的数据。

4、开漏输出详解:
输出端相当于三极管的集电极,对输入数据寄存器的访问可得到 I/O 状态。可以做不同电压信号转换;多个同时级联还可以实现线与逻辑)。

5、推挽式输出详解:
可以输出高,低电平,连接数字器件; 推挽结构一般是指两个三极管分别受两互补信号的控制,总是在一个三极管导通的时候另一个截止。高低电平由IC的电源决定。

6、复用功能详解:
可以理解为GPIO口被用作第二功能时的配置情况(即并非作为通用IO口使用)。端口必须配置成复用功能输出模式(推挽或开漏)。

在MM32L0产品UM的8.1.11 章节外设的 GPIO 配置,用户可以查到需要使用相关功能时各GPIO的状态配置的表格。

初识MM32 GPIO初识MM32 GPIO

下面将根据库函数对MM32L0xx的GPIO配置,首先来看一下GPIO_Init函数的原型void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)。这个函数的实现是在HAL_gpio.h文件中,若要使用该函数在相应的应用程序的前面包含HAL_gpio.h头文件。

该函数的第一个参数为GPIO_ TypeDef,它是一个结构体类型,该类型在MM32L0xx.h中被定义。定义的原型为:

typedef struct
{
  __IO uint32_t CRL;
  __IO uint32_t CRH;
  __IO uint32_t IDR;
  __IO uint32_t ODR;
  __IO uint32_t BSRR;
  __IO uint32_t BRR;
  __IO uint32_t LCKR;
  __IO uint32_t RESERVED0;
  __IO uint32_t AFRL;
  __IO uint32_t AFRH;
} GPIO_TypeDef;

该函数的第二个参数为GPIO_ InitTypeDef,它也是一个结构体类型,该类型在HAL_gpio.h中被定义,第一个参数只找到配置的目标寄存器,第二个参数就是对相应端口如何配置的数据参数。这些参数存储在指向GPIO_InitTypeDef变量的首地址处。定义的原型为:

typedef struct
{
   uint16_t GPIO_Pin;
   GPIOSpeed_TypeDef GPIO_Speed;
   GPIOMode_TypeDef GPIO_Mode;
}GPIO_InitTypeDef;

GPIA是固件库中定义的一个宏,在编译的时候会宏展开,先列出与GPIOD端口地址映射有关的宏定义如下:

#define GPIOA             ((GPIO_TypeDef *) GPIOA_BASE)
#define GPIOA_BASE      (0x48000000)

如在配置MCU的PA15控制一个LED灯的亮和灭:

void GPIO_Init(void)
{
 GPIO_InitTypeDef  GPIO_InitStructure;
 
 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); //使能GPIOA时钟
//GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1);//此处只是控制闪灯,如使用到相关外设一定要配置GPIO复用功能。
 
GPIO_InitStructure.GPIO_Pin  =  GPIO_Pin_15; //配置GPIOA.15
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//
GPIO_Init(GPIOA, &GPIO_InitStructure);
}

GPIO_InitTypeDef的第一个变量为GPIO_Pin是一个16位的无符号数,该数只有16位,每一位代表一个引脚,若要配置某一个端口的某一个引脚只需要把相应的位设置为1就可以了。在MM32的固件库中有如下引脚号定义:

#define GPIO_Pin_0                 ((uint16_t)0x0001)  /* Pin 0 selected */
#define GPIO_Pin_1                 ((uint16_t)0x0002)  /* Pin 1 selected */
#define GPIO_Pin_2                 ((uint16_t)0x0004)  /* Pin 2 selected */
#define GPIO_Pin_3                 ((uint16_t)0x0008)  /* Pin 3 selected */
#define GPIO_Pin_4                 ((uint16_t)0x0010)  /* Pin 4 selected */
#define GPIO_Pin_5                 ((uint16_t)0x0020)  /* Pin 5 selected */
#define GPIO_Pin_6                 ((uint16_t)0x0040)  /* Pin 6 selected */
#define GPIO_Pin_7                 ((uint16_t)0x0080)  /* Pin 7 selected */
#define GPIO_Pin_8                 ((uint16_t)0x0100)  /* Pin 8 selected */
#define GPIO_Pin_9                 ((uint16_t)0x0200)  /* Pin 9 selected */
#define GPIO_Pin_10                ((uint16_t)0x0400)  /* Pin 10 selected */
#define GPIO_Pin_11                ((uint16_t)0x0800)  /* Pin 11 selected */
#define GPIO_Pin_12                ((uint16_t)0x1000)  /* Pin 12 selected */
#define GPIO_Pin_13                ((uint16_t)0x2000)  /* Pin 13 selected */
#define GPIO_Pin_14                ((uint16_t)0x4000)  /* Pin 14 selected */
#define GPIO_Pin_15                ((uint16_t)0x8000)  /* Pin 15 selected */
#define GPIO_Pin_All               ((uint16_t)0xFFFF)  /* All pins selected */

使用这些定义好的宏就方便很多,要配置某几个引脚只需要把相应的引脚相或就可以了。若你要多某一个端口的所有位进行配置,那么只需要使用一个宏GPIO_Pin_All 。

GPIOSpeed_TypeDef是一个枚举类型,它用于定义GPIO速度的参数,它的格式如下:

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

通过定义可以知道,GPIOSpeed_TypeDef有三种取值,那么GPIO的速度有三种。
GPIOMode_TypeDef也是一个枚举类型,它用于定义GPIO工作的模式,它的定义如下:

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;

这两位数据用来存储到某一个引脚的模式控制位MODEx[1:0] ,而高四位用来标志某一些标志。

MM32的GPIO库函数:
1、void GPIO_DeInit(GPIO_TypeDef* GPIOx);
函数解释:将外设 GPIOx 寄存器重设为缺省值,该函数的作用是把GPIO相关的寄存器配置成上电复位后的默认状态,在第一次初始化前或者不再使用某一个接口后可以调用该函数。
函数参数说明:GPIOx:GPIO的分组,如GPIOA 、GPIOB等的宏定义。

2、void GPIO_AFIODeInit(void);
函数解释:将复用功能(重映射事件控制和 EXTI 设置)重设为缺省值。

3、void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
函数解释:GPIO的初始化函数,该函数的作用是对IO进行初始化。
函数参数说明:
(1)GPIOx:GPIO的分组,如GPIOA 、GPIOB等的宏定义。
(2)GPIO_InitStruct:GPIO的初始化相关结构体。该结构体里面的成员变量决定了我们具体的初始化参数。以下进行说明:
l GPIO_Pin:指定具体的IO脚,如GPIO_Pin_0 GPIO_Pin_1这样的宏定义,这些宏由厂家写好,我们直接使用即可。
l GPIO_Mode:指定GPIO的模式。

4、void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
函数解释:把 GPIO_InitStruct 中的每一个参数按缺省值填入,GPIO结构体的初始化。对GPIO_InitStruct结构体进行默认配置
函数参数说明:GPIO_InitStruct,直接传入该结构体的指针,在该函数内会对结构体进行初始化。

5、uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
函数解释:读取指定端口管脚输入。
函数参数说明:GPIOx:GPIO的分组(如GPIOA,GPIOB等)。GPIO_Pin:具体的gpio管脚(如GPIO_Pin_0 、GPIO_Pin_1这样的宏定义)

6、uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
函数解释:读取指定的GPIO端口输入。
函数参数说明:GPIOx:gpio的分组/gpio端口;GPIO_Pin:具体的gpio管脚
函数返回值说明:输入管脚的值Bit_SET(高电平) Bit_RESET(低电平)

7、uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
函数解释:读取指定端口管脚输出。
函数参数说明:GPIOx:GPIO的分组/ GPIO端口;GPIO_Pin:具体的gpio管脚
函数返回值说明:输出管脚的值Bit_SET(高电平) Bit_RESET(低电平)

8、uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
函数解释:读取输出IO分组/端口的值
函数参数说明:GPIOx:GPIO的分组/ GPIO端口
函数返回值说明:一个io端口的所有数据 (输出状态)

9、void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
函数解释:对IO管脚进行置位(输出高电平)。这个函数使用GPIOx_BSRR寄存器来实现原子读或者修改操作。在这种情况下,在读和修改访问时发生一个IRQ中断是没有危险的。
函数参数说明:GPIOx:GPIO的分组/ GPIO端口;GPIO_Pin:具体的gpio管脚或者是io管脚的组合

10、void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
函数解释:清除指定的数据端口位,对IO管脚进行复位(输出低电平)。这个函数使用GPIOx_BSRR寄存器来实现读或者修改操作。在这种情况下,在读和修改访问时发生一个IRQ中断是没有危险的。
函数参数说明:GPIOx:GPIO的分组/ GPIO端口;GPIO_Pin:具体的GPIO管脚或者是IO管脚的组合

11、void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
函数解释:对某一位进行写入操作。
函数参数说明:GPIOx:GPIO的分组/ GPIO端口;GPIO_Pin:具体的GPIO管脚;BitVal:写入高电平或者低电平(Bit_RESET:写入低电平 Bit_SET:写入高电平

12、void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
函数解释:对GPIO端口进行写入操作,适用于对统一端口的多个管脚的写入
函数参数说明:GPIOx:GPIO的分组/ GPIO端口; BitVal:写入高电平或者低电平(Bit_RESET:写入低电平 Bit_SET:写入高电平)

13、void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
函数解释:锁定GPIO的寄存器,锁定的寄存器是GPIOx_MODER,GPIOx_OTYPER, GPIOx_OSPEEDR,GPIOx_PUPDR, GPIOx_AFRL and GPIOx_AFRH。在下一次复位前,被锁定的管脚不能被修改。
函数参数说明:GPIOx:GPIO的分组(如GPIOA,GPIOB等)。GPIO_Pin:具体的gpio管脚(如GPIO_Pin_0 、GPIO_Pin_1这样的宏定义)。

14、void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF);
函数解释:改变指定管脚的映射关系,即配置指定管脚的复用功能。
函数参数说明:GPIOx:GPIO的分组/ GPIO端口;GPIO_PinSource:具体要配置成复用功能的管脚(如GPIO_Pin_0 GPIO_Pin_1这样的宏定义);GPIO_AF:选择该管脚要使用的复用功能。

例:配置UART1的GPIO程序

void UART_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
   
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); //使能GPIOA时钟
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1);//GPIO复用功能设置
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1);
   
    //UART1_TX   GPIOA.9
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructure);// 初始化GPIOA.9
   
//UART1_RX   GPIOA.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);// 初始化GPIOA.10
   
}

转自: 灵动微电MMCU

围观 576

深入讲解MCU最基本外设GPIO的各种模式,希望大家对GPIO能有更深入的认识。

GPIO全称General Purpose Input Output,即通用输入/输出。从GPIO的名字我们很容易理解它的功能,而每种功能都对应相应的工作模式,主要有三种模式:高阻输入、推挽输出和开漏输出。

高阻输入

我们知道大部分MCU的I/O使用时都可以设置为高阻输入。高阻输入可以认为输入电阻是无穷大,认为I/O对前级影响极小。

如图1所示为GPIO在高阻输入模式下的等效结构示意图。输入模式主要由一个带有施密特触发输入的三态缓冲器(U1)组成,它能将缓慢变化或者畸变的输入脉冲信号整形成比较理想的脉冲信号。GPIO读操作时,在读脉冲(相当于打开开关)的作用下会把引脚当前的电平状态读到内部总线上,当GPIO不读时,引脚与内部总线之间是隔离的,相当于开关关闭。

图1  GPIO高阻输入结构示意图

图1 GPIO高阻输入结构示意图

推挽输出

推挽输出的工作原理是:在电路中用两只三极管构成一级放大电路,两只三极管分别放大输入信号的正半周和负半周,两只三极管输出的半周信号在放大器负载上合并后得到一个完整周期的输出信号。

图2  GPIO推挽输出结构示意图

图2 GPIO推挽输出结构示意图

如图2所示为GPIO推挽输出模式下的结构示意图。U1是输出锁存器,当执行GPIO写操作时,在写脉冲(Write pulse)的作用下,数据被锁存到Q和/Q。T1和T2构成CMOS反相器,T1导通或T2导通时都表现出低阻抗,但T1和T2不会同时导通或者关闭,最后形成的是推挽输出。在推挽输出模式下,GPIO还有回读功能,能实现回读功能的是三态缓冲器U2,而读到的是输出锁存器的状态,而不是引脚的外部状态。

开漏输出

开漏输出和推挽输出结构基本相同,只是开漏输出只有下拉晶体管T1而没有上拉晶体管T2。开漏输出的实际作用就是一个开关,输出“1”时断开,输出“0”时连接到内部的GND。

如图3所示为GPIO开漏输出模式结构示意图。输出结构没有内部上拉,因此在实际应用时通常都要外接合适的上拉电阻(通常为4.7KΩ~10KΩ)。开漏输出的功能能够方便的实现“线与”逻辑功能,即多个开漏的引脚可以直接并在一起使用,并统一外接一个合适的上拉电阻,就自然形成“逻辑与”的关系。开漏输出的另一种用途就是能够方便地实现不同逻辑电平之间的转换,如3.3V到5.5V之间,只需要外接一个上拉电阻,典型的应用例子就是基于开漏电气连接的I2C总线。

图3  GPIO开漏输出结构示意图

图3 GPIO开漏输出结构示意图

来源:周立功单片机

围观 830

页面

订阅 RSS - GPIO