title: 03_2 GPIO输入
tags:
- STM32
categories: - STM32学习
按键介绍
- 按键:常见的输入设备,按下导通,松手断开
- 按键会存在抖动

- 按键会存在抖动
传感器模块介绍
- 传感器:光敏电阻/热敏电阻/红外接收管

- 传感器的元件的电阻会随着外界的模拟量的变化而变化,通过与定值电阻分压即可得到模拟电压输出,再通过电压比较器进行二值化即可得到数字电压输出

注意这其中一个传感器,N1为传感器电阻本身,上面的R1是用来和传感器电阻进行分压,旁边的电容作用是用来滤波(用来保证电路为稳定,在分析的时候可以忽略),然后可以用分压定理来分析一下传感器电阻的阻值变化对电压的影响
当N1阻值变小时,下拉作用会增强,中间AO端的电压会拉低,极端情况下,AO输出被完全下拉,输出为0
当N1阻值变大,下拉作用被减弱,中间的引脚由于R1的上拉作用,电压就会升高,极端情况下,N1阻值无穷大,相当于断路,输出电压被R1拉高至VCC
二值化模块(LM393)
LM393是一个电压比较器芯片
中间红框是有两个独立的电压比较电路,其实这个电压比较器就是两个运算放大器[[51单片机的AD/DA]]
- 当同相输入端的电压大于反相输入端的电压时,输出会瞬间升为最大值VCC
- 反之,当同相输入端的电压小于反相输入端的电压时,输出会瞬间降低为最小值GND
这样就能对模拟电路进行二值化
红外传感器
对于红外传感器,N1就是一个红外接收管,对应会多一个点亮红外发射管的电路,
- 发射管发射红外光,
- 接收管接收红外光,
- 电位器直接换成了两个电阻进行分压,这样数字输出就是固定阈值的二值化
硬件电路
按键的硬件电路
可以分为上接和下接模式,一般选择下接,和LED接法类似,是电路设计的习惯和规范
一、直接与GND相连

随便选取一个GPIO口,通过K1接地,
当按键按下时,PA0被直接下拉到GND,此时读取PA0口的电压就是低电平
当按键松手时,PA0被悬空,此时悬空会导致引脚电压不确定,所以在这种接法下,必须要求PA0是上拉输入模式,否则会出现引脚电压不确定的错误现象
如果PA0是上拉输入模式,引脚再悬空,PA0就是高电平,所以这种模式下,按下为低电平,松开就是高电平
二、外部接上拉电阻

如果外部没有接上拉电阻,就必须要开启上拉输入模式。外接了上拉电阻就可以选择浮空输入
- 当按键按下时,引脚直接接到GND,此时PA0的引脚可以配置为浮空输入或者上拉输入
- 因为由内外电路双重控制,此时的高电平会更强一些,对应的高电平会更加稳定
- 但是当引脚强行拉低时,损耗也会大一些
三、上接接法
单片机一般没有下拉模式,且下拉模式不强,不建议学

按键控制LED
- C 语言数据类型

注意:
- C语言中int是16位的,但是在stm32中int是32位,short是16位,long也是32位的
- 注意stdint关键字,是C语言提供的有
stdint.h头文件给前面的重命名,后面的_t的意思是typedefine 重命名,但是其实只是换一个名字而已
封装库函数
新建文件夹hardware用于存放硬件驱动,比如led
直接新建.c/.h的文件夹
led.c的文件
#include "stm32f10x.h"
void LED_Init(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_1 | GPIO_Pin_2; //选择pin1和pin2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //选择时钟速度
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2); //setbit,高电平,led不点亮,这样能默认led是熄灭的状态
}
void LED1_ON(void) //然后就是led1开
{
GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}
void LED1_OFF(void) //led1关
{
GPIO_SetBits(GPIOA, GPIO_Pin_1);
}
void LED1_Turn(void) //led取反
{
if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1) == 0)
{
GPIO_SetBits(GPIOA, GPIO_Pin_1);
}
else
{
GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}
}
void LED2_ON(void) 下面同理
{
GPIO_ResetBits(GPIOA, GPIO_Pin_2);
}
void LED2_OFF(void)
{
GPIO_SetBits(GPIOA, GPIO_Pin_2);
}
void LED2_Turn(void)
{
if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2) == 0)
{
GPIO_SetBits(GPIOA, GPIO_Pin_2);
}
else
{
GPIO_ResetBits(GPIOA, GPIO_Pin_2);
}
}
- 主函数
#ifndef __LED_H
#define __LED_H
void LED_Init(void);
void LED1_ON(void);
void LED1_OFF(void);
void LED1_Turn(void);
void LED2_ON(void);
void LED2_OFF(void);
void LED2_Turn(void);
#endif
按键封装
- 输入函数介绍
GPIO_ReadInputDataBit;此函数用于读取输入寄存器某一个端口的输入值- 返回值是高低电平
GPIO_ReadInputData相比较上一个函数少了bit,是用来读取整个输入数据寄存器- 返回值是uint16_t ,是一个16位的数据,每一位代表一个端口值
- 输出函数介绍
GPIO_ReadOutputDataBit,用于读取输出寄存器的某一位- 原则上来说不是用来读取端口的输入数据,一般用于输出模式,来看自己输出的是什么
GPIO_ReadOutputData,用于读取整个输出寄存器
#include "stm32f10x.h" // Device header
#include "Delay.h"
void Key_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //注意按键在gpioB的位置
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //input 上拉模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11; //我们的按键接在了Pin1 & Pin11 上
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //在输入模式下这个速度没有实际用处
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
uint8_t Key_GetNum(void) //uint8_t = unsigned char
{
uint8_t KeyNum = 0; //先初始一个值
//接下来就是寻找读取gpio端口值的函数
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0) //如果pin1按下
{
Delay_ms(20); //延时消抖
while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0); //如果不松手就一直死循环
Delay_ms(20); //松手消抖
KeyNum = 1; //赋值
}
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0) //pin11同理
{
Delay_ms(20);
while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0);
Delay_ms(20);
KeyNum = 2;
}
return KeyNum; //最后返回按键按下的键值
}
光敏传感器控制蜂鸣器
光敏传感器
void LightSensor_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //简简单单的初始化
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
uint8_t LightSensor_Get(void)
{
return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13); //直接返回光敏电阻的读取值
}
蜂鸣器
void Buzzer_Init(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);
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}
void Buzzer_ON(void)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
}
void Buzzer_OFF(void)
{
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}
void Buzzer_Turn(void)
{
if (GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_12) == 0)
{
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}
else
{
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
}
}
文章详细介绍了STM32的GPIO输入模式,特别是按键的下接模式和上接模式,以及如何处理按键抖动。同时,讲解了传感器如光敏和热敏电阻的工作原理,通过电压比较器LM393实现模拟信号的二值化。此外,还涵盖了C语言在STM32中的数据类型和封装库函数的使用方法。


2262

被折叠的 条评论
为什么被折叠?



