GPIO介绍及使用
- 一、GPIO简介
-
- 二、GPIO基本结构
- 三、GPIO位结构
- 四、GPIO模式
-
- [1. 浮空/上拉/下拉输入](#1. 浮空/上拉/下拉输入)
- 2.模拟输入
- [3. 开漏/推挽输出](#3. 开漏/推挽输出)
- 4.复用开漏/推挽输出
- 五、LED和蜂鸣器简介
一、GPIO简介
- GPIO(General Purpose Input Output)通用输入输出口
- 可配置为8种输入输出模式
- 引脚电平:0V~3.3V,部分引脚可容忍5V
- 输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等
- 输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等
二、GPIO基本结构
GPIO 外设挂载在APB2总线上
三、GPIO位结构
1.推挽输出模式:
\qquad P-MOS和N-MOS均有效,数据寄存器为1时,P-MOS导通,N-MOS断开,输出接到VDD,输出高电平;数据寄存器为0时,P-MOS断开,N-MOS导通,输出接到VSS,输出低电平。这种模式下,高低电平均有较强的驱动能力,所以推挽输出模式也可以叫强推输出模式,在推挽输出模式下,STM32对I0口具有绝对的控制权,高低电平都由STM32控制。
2.开漏输出模式:
\qquad P-MOS是无效的,只有N-MOS在工作,数据寄存器为1时,N-MOS断开,这时输出相当于断开,也就是高阻模式,数据寄存器为0时,N-MOS导通,输出直接接到VSS,也就是输出低电平。这种模式下,只有低电平有驱动能力,高电平是没有驱动能力的。
\qquad 用途:开漏模式可以作为通信协议的驱动方式,如12C通信的引脚,就是使用的开漏模式,在多机通信的情况下,这个模式可以避免各个设备的相互干扰,另外开漏模式还可以用于输出5V的电平信号。
3.关闭状态:
\qquad 当引脚配置为输入模式的时候,两个MOS管都无效,也就是输出关闭,端口的电平由外部信号来控制
四、GPIO模式
通过配置GPIO的端口配置寄存器,端口可以配置成以下8种模式
1. 浮空/上拉/下拉输入
\qquad 由图可以看出,在输入模式下,输出驱动器是断开的(无效)
,端口只能输入而不能输出,输入驱动器上两个电阻可以选择为上拉工作、下拉工作或者都不工作,对应的就是上拉输入、下拉输入和浮空输入,然后输入通过施密特触发器(TTL肖特基触发器)进行波形整形后,连接到输入数据奇存器。
2.模拟输入
\qquad 模拟输入模式下,输出是断开的(无效的)
,输入的施密特触发器(TTL肖特基触发器)也是关闭的无效状态,所以整个GPI0的输入输出都是不起作用的,只有模拟输入是有效的,也就是从引脚直接接入片上外设,也就是ADC,所以,当我们使用ADC的时候,将引脚配置为模拟输入即可,其它时候是用不到模拟输入的
3. 开漏/推挽输出
\qquad 输出是由输出数据寄存器控制的,P-MOS如果无效,就是开漏输出,如果P-MOS和N-MOS都有效,就是推挽输出,另外还可以看到,在输出模式下,输入模式也是有效的。但是在上面的电路图中,在输入模式下,输出都是无效的,这是因为,一个端口只能有一个输出,但可以有多个输入,所以当配置成输出模式的时候,内部也可以输入,不会影响输出。
4.复用开漏/推挽输出
\qquad 可以看到通用的输出输出数据寄存器是没有连接的,引脚的控制权转移到了片上外设,由片上外设来控制,在输入部分,片上外设也可以读取引脚的电平,同时普通的输入也是有效的,顺便接收一下电平信号
\qquad 在GPIO的这8种模式中,除了模拟输入这个模式会关团数字的输入功能,在其他的7个模式中,所有的输入都是有效的
片内外设、片上外设和片外外设的区别 片内外设就是片上外设,同一种意思不同说法。
片内外设:指的是在芯片内部,但是不属于ARM内核的外部设备(如串口模块、Flash、IIC模块、SPI通信模块、ADC、DAC模块) 片外外设:独立于芯片外部的设备(如SD卡,显示屏等)
五、LED和蜂鸣器简介
1.LED:发光二极管,正向通电点亮,反向通电不亮
发光二极管如何分辨正负极:
如果是引脚没有剪过的LED,那其中长脚是正极,短脚是负极
通过LED内部也可以看正负极,较小的一半是正极,较大的一半是负极
2.有源蜂鸣器:内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定
有源蜂鸣器内部电路中用了一个三极管开关来进行驱动,在VCC和GND分别接上正负极的供电,中间引脚接低电平,蜂鸣器响,接高电平,蜂鸣器关闭,即低电平触发。
3.无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音
c
#include "stm32f10x.h" // Device header
#include "Delay.h"
// LED 500ms闪烁一次
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
while (1)
{
GPIO_ResetBits(GPIOA, GPIO_Pin_0);//LED 500ms闪烁一次
Delay_ms(500);
GPIO_SetBits(GPIOA, GPIO_Pin_0);
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0);
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1);
Delay_ms(500);
}
}
c
#include "stm32f10x.h" // Device header
#include "Delay.h"
// 流水灯效果
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
while (1)
{
GPIO_Write(GPIOA, ~0x0001); //0000 0000 0000 0001
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0002); //0000 0000 0000 0010
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0004); //0000 0000 0000 0100
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0008); //0000 0000 0000 1000
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0010); //0000 0000 0001 0000
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0020); //0000 0000 0010 0000
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0040); //0000 0000 0100 0000
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0080); //0000 0000 1000 0000
Delay_ms(100);
}
}
c
#include "stm32f10x.h" // Device header
#include "Delay.h"
// 蜂鸣器响
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
while (1)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
Delay_ms(100);
GPIO_SetBits(GPIOB, GPIO_Pin_12);
Delay_ms(100);
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
Delay_ms(100);
GPIO_SetBits(GPIOB, GPIO_Pin_12);
Delay_ms(700);
}
}