【STM32】GPIO输入

1 GPIO输出

1.1 按键简介

按键:常见的输入设备,按下导通,松手断开

按键抖动:由于按键内部使用的是机械式弹簧片来进行通断的,所以在按下和松手的瞬间会伴随有一连串的抖动

1.2 传感器模块简介

传感器模块:传感器元件(光敏电阻/热敏电阻/红外接收管等)的电阻会随外界模拟量的变化而变化,通过与定值电阻分压即可得到模拟电压输出,再通过电压比较器进行二值化即可得到数字电压输出

分别是光敏电阻传感器(光线越强,光敏电阻的阻值就越小)

热敏电阻传感器(温度越强,热敏电阻的阻值就越小)

对射式红外传感器(红外越强,红外接收管的阻值就越小)

反射式红外传感器

滤波电容:保持电路稳定

硬件电路

一般是这种(下接模式)

第一张图,当K1按下,PA0被下拉到GND,此时读取PAO口的电压就是低电平;

当K1松开,PA0被悬空,引脚的电压不确定,此时必须要求PA0是上拉输入,否则会出现引脚电压不稳定的错误现象。

第二张图多了一个上拉电阻。当按键按下时,PA0被下拉到GND,此时读取PAO口的电压就是低电平;

当按键松开时,引脚由于上拉作用,自然保持高电平。

这种接法下,PA0需要配置成上拉输入或者浮空输入

所以上面这两种接法,按键按下是低电平,松手是高电平。

上接模式

第三张图,PA0通过按键接到3.3V,要求PA0必须配置成下拉输入的模式。

当按键按下时,引脚为高电平;松手时,引脚为低电平。(一般单片机可能没有下拉输入模式)

第四张图,PA0需要配置成下拉输入或者浮空输入

下面这两种接法,按键按下是高电平,松手是低电平。

传感器模块

DO是数字输出;AO是模拟输出(ADC模拟转换器)。

C语言数据类型

|--------------------|--------|---------------------------|-------------------|---------------|
| 关键字 | 位数 | 表示范围 | stdint****关键字 | ST****关键字 |
| char | 8 | -128 ~ 127 | int8_t | s8 |
| unsigned char | 8 | 0 ~ 255 | uint8_t | u8 |
| short | 16 | -32768 ~ 32767 | int16_t | s16 |
| unsigned short | 16 | 0 ~ 65535 | uint16_t | u16 |
| int | 32 | -2147483648 ~ 2147483647 | int32_t | s32 |
| unsigned int | 32 | 0 ~ 4294967295 | uint32_t | u32 |
| long | 32 | -2147483648 ~ 2147483647 | | |
| unsigned long | 32 | 0 ~ 4294967295 | | |
| long long | 64 | -(2^64)/2 ~ (2^64)/2-1 | int64_t | |
| unsigned long long | 64 | 0 ~ (2^64)-1 | uint64_t | |
| float | 32 | -3.4e38 ~ 3.4e38 | | |
| double | 64 | -1.7e308 ~ 1.7e308 | | |

2 GPIO输入之按键控制LED灯

2.1 接线图

低电平点亮

2.2 封装模块

新建文件夹HardWare,模块化代码

先封装GPIO。LED.c,记得加上LED.h

cpp 复制代码
#include "stm32f10x.h"                  // Device header

// LED初始化函数
void LED_Init(void)
{
	// 1使用RCC开启GPIO的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	// 2使用GPIO_Init函数初始化GPIO[推挽输出50MHz]
	GPIO_InitTypeDef GPIO_InitStructure;
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;			
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	// 推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	// 3初始化熄灭
	GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2);
}

// 点亮LED1函数
void LED1_ON(void)
{
	GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}

// 熄灭LED1函数
void LED1_OFF(void)
{
	GPIO_SetBits(GPIOA, GPIO_Pin_1);
}


// 点亮LED2函数
void LED2_ON(void)
{
	GPIO_ResetBits(GPIOA, GPIO_Pin_2);
}

// 熄灭LED2函数
void LED2_OFF(void)
{
	GPIO_SetBits(GPIOA, GPIO_Pin_2);
}

// LED1反转
void LED1_Turn(void)
{
	// 读取当前端口输出状态,如果输出是0,就置1;否则置0
	if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1) == 0)
	{
		GPIO_SetBits(GPIOA, GPIO_Pin_1);
	}
	else
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_1);
	}
}

// LED2反转
void LED2_Turn(void)
{
	// 读取当前端口输出状态,如果输出是0,就置1;否则置0
	if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2) == 0)
	{
		GPIO_SetBits(GPIOA, GPIO_Pin_2);
	}
	else
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_2);
	}
}

再封装按键。KEY.c,记得加上KEY.h

cpp 复制代码
#include "stm32f10x.h"                  // Device header
#include "Delay.h"

// 按键初始化函数
// 上拉输入模式
void KEY_Init(void)
{
	// 1使用RCC开启GPIO的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	// 2使用GPIO_Init函数初始化GPIO[推挽输出50MHz]
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;			// 上拉输入
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;			
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		// 其实没有
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

// 读取按键的值
uint8_t KEY_GetNum(void)
{
	uint8_t KeyNum = 0;
	// 1号端口
	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
	{
		// 刚按下,有抖动
		Delay_ms(20);
		// 检查按键松手
		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
		{
			Delay_ms(20);
			KeyNum = 1;
		}
	}
	
	// 11号端口
	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0)
	{
		// 刚按下,有抖动
		Delay_ms(20);
		// 检查按键松手
		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0)
		{
			Delay_ms(20);
			KeyNum = 2;
		}
	}
	return KeyNum;
}

2.3 主函数

测试代码,主函数

cpp 复制代码
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "KEY.h"

uint8_t keyNum;

int main()
{
	LED_Init();
	KEY_Init();
	
	while (1)
	{
		keyNum = KEY_GetNum();
		// 按键1按下,点亮LED1
		if (keyNum == 1)
		{
			LED1_Turn();
		}
		// 按键2按下,熄灭LED1
		if (keyNum == 2)
		{
			LED2_Turn();
		}
	}
}

代码结构图

我的按键11不起作用,不能控制GPIOA_Pin_2的亮灭。

相关推荐
青牛科技-Allen1 小时前
GC3910S:一款高性能双通道直流电机驱动芯片
stm32·单片机·嵌入式硬件·机器人·医疗器械·水泵、
森焱森3 小时前
无人机三轴稳定控制(2)____根据目标俯仰角,实现俯仰稳定化控制,计算出升降舵输出
c语言·单片机·算法·架构·无人机
白鱼不小白3 小时前
stm32 USART串口协议与外设(程序)——江协教程踩坑经验分享
stm32·单片机·嵌入式硬件
S,D3 小时前
MCU引脚的漏电流、灌电流、拉电流区别是什么
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·硬件工程
芯岭技术6 小时前
PY32F002A单片机 低成本控制器解决方案,提供多种封装
单片机·嵌入式硬件
youmdt7 小时前
Arduino IDE ESP8266连接0.96寸SSD1306 IIC单色屏显示北京时间
单片机·嵌入式硬件
嘿·嘘7 小时前
第七章 STM32内部FLASH读写
stm32·单片机·嵌入式硬件
Meraki.Zhang7 小时前
【STM32实践篇】:I2C驱动编写
stm32·单片机·iic·驱动·i2c
几个几个n10 小时前
STM32-第二节-GPIO输入(按键,传感器)
单片机·嵌入式硬件
Despacito0o13 小时前
ESP32-s3摄像头驱动开发实战:从零搭建实时图像显示系统
人工智能·驱动开发·嵌入式硬件·音视频·嵌入式实时数据库