3 GPIO通用输入输出口(一)

3 GPIO通用输入输出口

GPIO简介

GPIO(General Purpose Input Output)通用输入输出口
可配置为8种输入输出模式
引脚电平:0V~3.3V,部分引脚可容忍5V
输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等
输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等

GPIO基本结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cAKuZgC9-1680926793325)(32单片机.assets/image-20230402205748436.png)]

GPIO位结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f2vhP91Q-1680926793328)(32单片机.assets/image-20230402205815058.png)]

注意:

保护二极管:使输入的电压控制在0-3.3v之间(一般VDD接3.3,VCC接0)

施密特触发器:它的执行逻辑是,如果输入电压大于某一阈值,输出就会瞬间升为高电平,如果输入电压小于某一阈值,输出就会瞬间降为低电平;

输入端:
1.上拉电阻和下拉电阻(上拉电阻至VDD和下拉电阻至VCC)目的给数字端口默认输入一个电平:
	1)如果上面导通,下面断开,就是上拉输入模式;(高电平)
	2)如果上面断开,下面导通,就是下拉输入模式;(低电平)
	3)如果两个都断开,就是浮空输入模式;
	
2.模拟输入连接ADC上的,因为ADC需要接受模拟量,所以接到施密特触发器前;(模拟输入)
3.复用功能输入,整个是连接到其他需要读取端口的外设上的,比如串口的输入引脚等,这跟西线接收的是数字量,所以在施密特触发器后面;(数字输入)
	
输出端:
1.如果想单独控制其中某一个端口而不影响其他端口的话
	1)第一种方式是先读出整个寄存器,然后用按位与和按位或的方式更改某一位,最后再将更改后的数据该回去,再C中就是&=和|=的操作;(在输出数据寄存器操作麻烦,效率不高)
	2)第二种通过位设置/清除寄存器,如果我们要对某一位进行置1的操作,在位设置寄存器的对应位写1即可,剩下不需要操作的位写0,自动将输出数据寄存器中对应位置为1,而剩下写0的位则保持不变。如果想对某一位进行清0的操作,就在位清除寄存器的对应位写1即可;
	3)第三种操作,就是读写stm32中的“位带”区域。(位带跟51单片机的位寻址作用差不多)
2.输出控制之后就接到了两个MOS管(上为P-MOS,下为N-MOS)
	1)推挽输出模式又名强推输出模式(P-MOS和N-MOS均有效):数据寄存器位1时,上管导通,下管断开,输出直接接到VDD,就是输出高电平;数据寄存器位0时,上管断开,下管导通,输出直接接到VSS,就是输出低电平;(对IO口有绝对的控制权,高低电平都由STM32说了算)
	2)开漏输出模式(P-MOS无效,N-MOS有效):数据寄存器位1时,下管断开,输出相当于断开,也就是高阻模式;数据寄存器位0时,下管导通,输出直接接到VSS,就是输出低电平;(这种模式只有低电平有驱动能力,高电平没有驱动能力,可以作为通信协议的驱动方式,比如I2C通信的引脚就是使用开漏模式。在多机通信的情况下,这个模式可以避免各个设备的相互干扰。另外还可以输出5伏的电平信号,VDD接5V)
	3)关闭模式即当引脚配置为输入模式的时候(P-MOS和N-MOS均无效):端口的信号由外部信号来控制。

GPIO模式

•通过配置GPIO的端口配置寄存器,端口可以配置成以下8种模式

模式名称性质特征
浮空输入数字输入可读取引脚电平,若引脚悬空,则电平不确定
上拉输入数字输入可读取引脚电平,内部连接上拉电阻,悬空时默认高电平
下拉输入数字输入可读取引脚电平,内部连接下拉电阻,悬空时默认低电平
模拟输入模拟输入GPIO无效,引脚直接接入内部ADC
开漏输出数字输出可输出引脚电平,高电平为高阻态,低电平接VSS
推挽输出数字输出可输出引脚电平,高电平接VDD,低电平接VSS
复用开漏输出数字输出由片上外设控制,高电平为高阻态,低电平接VSS
复用推挽输出数字输出由片上外设控制,高电平接VDD,低电平接VSS

1)浮空/上拉/下拉输入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TAjthpt4-1680926793330)(32单片机.assets/image-20230402221002291.png)]

	1)如果上面导通,下面断开,就是上拉输入模式;(高电平)
	2)如果上面断开,下面导通,就是下拉输入模式;(低电平)
	3)如果两个都断开,就是浮空输入模式;

2)模拟输入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LNq9dSpd-1680926793332)(32单片机.assets/image-20230402221236061.png)]

模拟输入是连接ADC上的,因为ADC需要接受模拟量,所以接到施密特触发器前;(模拟输入)
从引脚直接接入片上外设,也就是ADC,所以当我们使用ADC时,将引脚配置为模拟输入就行了

3)开漏/推挽输出

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8zieEtco-1680926793334)(32单片机.assets/image-20230402221621611.png)]

一个端口只能有一个输出,但可以有多个输入,所以当配置为输出模式的时候,内部也可以顺便输入一下,也不会造成什么影响

4)复用开漏/推挽输出

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TOCy6NVu-1680926793340)(32单片机.assets/image-20230402221933130.png)]

引脚的控制权转移到了片上外设,由片上外设来控制;在输入部分,片上外设也可以读取引脚的电平,同时普通的输入也是有效的,顺便接收一下电平信号。

在GPIO的8中模式中,除了模拟输入这个模式会关闭数字输入功能,其他的7个模式中,所有的输入都是有效的。

3.1 GPIO输出

LED和蜂鸣器简介

LED:发光二极管,正向通电点亮,反向通电不亮
有源蜂鸣器:内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定
无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oN1vQOD8-1680926793343)(32单片机.assets/image-20230403104356092.png)]

硬件电路

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QrdUWloz-1680926793348)(32单片机.assets/image-20230403105235788.png)]

注意:很多单片机或者芯片都使用了高电平弱驱动,低电平强驱动的规则,这样可以一定程度避免高低电平打架,所有一般推荐第一种接法。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7TV6QUSV-1680926793352)(32单片机.assets/image-20230403105527859.png)]

注意:

PNP的三极管最好接在蜂鸣器上边,NPN的三极管最好接在蜂鸣器下边

补充:驱动电路(三极管驱动)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YlmZFypl-1680926793354)(32单片机.assets/v2-74d957ad822dbd76852ad52661815761_720w.webp)]

基极 b(base),发射极 e(emitter),集电极 c(collector);

箭头朝内PNP,箭头朝外NPN,导通电压顺箭头过,电压导通,电流控制;

对于三极管的开关特性分析,主要是看基极与发射极之间的电压情况。对PNP,只要e极电压比b高0.7V以上,e、c之间就可以导通;同样对NPN,只要b极电压比e高0.7V以上,e、c之间就可以导通。总之是箭头的始端比末端高 0.7V 就可以导通三极管的 e 极和 c 极。所以,NPN型三极管,b作为控制端,高电平导通,低电平关断;PNP型三极管,高电平关断,低电平导通。

​                                                               [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yDj4J2aF-1680926793356)(32单片机.assets/image-20230403110902500.png)]

NPN驱动:高电平导通

npn型导通输出的是低电平,没导通是高电平。导通是指给基极电压要大于PN结导通电压,三极管就能导通,硅0.7v,锗0.3v

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0AozN0tO-1680926793358)(32单片机.assets/image-20230403110947527.png)]

PNP驱动:低电平导通

面包板

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yeh0Q9qx-1680926793359)(32单片机.assets/image-20230403115940587.png)]

stm32f10x_rcc中的三个常用函数:

//RCC_AHB外设时钟控制(启用或禁用AHB外设时钟)
void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
//RCC_APB2外设时钟控制
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
//RCC_APB1外设时钟控制
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);

stm32f10x_gpio中的常用函数:

//
void GPIO_DeInit(GPIO_TypeDef* GPIOx);
void GPIO_AFIODeInit(void);
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
//GPIO的读取函数(bit是数据寄存器的某一位,没有就是整个数据寄存器)
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);	//读取某个端口输入数据
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);	//读取整个输入数据寄存器
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);  //读取某个端口输出,看看自己的输出数据
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);	//读取整个输出数据寄存器
//GPIO的输出函数
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);

8种输入输出模式:

typedef enum
{ GPIO_Mode_AIN = 0x0,			//(AIN:Analog IN)模拟输入
  GPIO_Mode_IN_FLOATING = 0x04,  //浮空输入
  GPIO_Mode_IPD = 0x28,			//(IPD:In Pull Down)下拉输入
  GPIO_Mode_IPU = 0x48,			//(IPU:In Pull Up)上拉输入
  GPIO_Mode_Out_OD = 0x14,		//(Out_OD:Out Open Drain)开漏输出(高电平不会亮)
  GPIO_Mode_Out_PP = 0x10,		//(Out_PP:Out Push Pull)推挽输出(高低电平均可点亮)
  GPIO_Mode_AF_OD = 0x1C,		//(AF_OD:Alt Open Drain)复用开漏
  GPIO_Mode_AF_PP = 0x18		//(AF_PP:Alt Push Pull)复用推挽
}GPIOMode_TypeDef;

使用输出或者输入的函数控制GPIO口:

void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);		//把指定端口设置为高电平
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);	//把指定端口设置为低电平
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);//前两个设置端口,根据第三个参数的值来设定指定的端口值
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);			//第二个参数可以同时对16个端口进行写入操作

3.2 LED闪烁&LED流水灯&蜂鸣器

1.LED闪烁

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0rp3Uuzh-1680926793361)(32单片机.assets/image-20230403194523596.png)]

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

int main(void)
{
	//step1:使用RCC开启GPIO的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	//step2:使用GPIO_Init函数初始化GPIO
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	//(Out_PP:Out Push Pull)推挽输出(高低电平都是有驱动能力)
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;  			//选择的是GPIOA外设的0号引脚,所以选择GPIO_Pin_0
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	//step3:使用输出或者输入的函数控制GPIO口
//	GPIO_SetBits(GPIOA, GPIO_Pin_0);
//	GPIO_ResetBits(GPIOA, GPIO_Pin_0);
//	GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
//	GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
	
	while (1)
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_0);
		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);
	}
}

2.LED流水灯

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

int main(void)
{
	//step1:使用RCC开启GPIO的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	//step2:使用GPIO_Init函数初始化GPIO
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	//(Out_PP:Out Push Pull)推挽输出(高低电平都是有驱动能力)
//	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 ;  			
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	//step3:使用输出或者输入的函数控制GPIO口

	
	while (1)
	{
		GPIO_Write(GPIOA, ~0X0001);	//0000 0000 0000 0001  按位取反,低电平点亮
		Delay_ms(500);
		GPIO_Write(GPIOA, ~0X0002);	//0000 0000 0000 0010  按位取反,低电平点亮
		Delay_ms(500);
		GPIO_Write(GPIOA, ~0X0004);	//0000 0000 0000 0100  按位取反,低电平点亮
		Delay_ms(500);
		GPIO_Write(GPIOA, ~0X0008);	//0000 0000 0000 1000  按位取反,低电平点亮
		Delay_ms(500);
		GPIO_Write(GPIOA, ~0X0010);	//0000 0000 0001 0000  按位取反,低电平点亮
		Delay_ms(500);
		GPIO_Write(GPIOA, ~0X0020);	//0000 0000 0010 0000  按位取反,低电平点亮
		Delay_ms(500);
		GPIO_Write(GPIOA, ~0X0040);	//0000 0000 0100 0000  按位取反,低电平点亮
		Delay_ms(500);
		GPIO_Write(GPIOA, ~0X0080);	//0000 0000 1000 0000  按位取反,低电平点亮
		Delay_ms(500);

	}
}

3.蜂鸣器

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

int main(void)
{
	//step1:使用RCC开启GPIO的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	//step2:使用GPIO_Init函数初始化GPIO
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	//(Out_PP:Out Push Pull)推挽输出(高低电平都是有驱动能力)
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	//step3:使用输出或者输入的函数控制GPIO口

	
	while (1)
	{
		GPIO_ResetBits(GPIOB, GPIO_Pin_12);	
		Delay_ms(500);
		GPIO_SetBits(GPIOB, GPIO_Pin_12);	
		Delay_ms(500);

	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值