基于Arduino框架esp32的GPIO使用
注: 本文章内容是基于arduino框架进行esp32的开发。
开发环境搭建可以参考上一篇文章:2、搭建ESP32开发环境
1、GPIO简介
GPIO是为控制其中使用相对较多的外设之一,GPIO通常用于实现输出电平信号与读取引脚的电平状态。在实际使用中通常用于控制像led灯这类器件和读取按键按键是否按下灯。ESP32上的GPIO外设支持中断。
2、GPIO模式
**(1)输入模式:**在此模式下,GPIO将用于读取相应引脚的数字状态。例如用于读取引脚状态判断按键是否按下。
**(2)输出模式:**在输出模式下,GPIO会通过控制引脚输出数字状态来驱动外部设备。例如用于点亮LED、控制数码管灯。
3、Arduino框架下ESP32的GPIO相关函数
(1)pinMode:用于设置对应引脚的GPIO工作模式。
函数原型:
void pinMode(uint8_t pin, uint8_t mode);
/*
参数说明:
pin:GPIO管脚编号。
mode:GPIO管脚的工作模式。(INPUT、OUTPUT、INPUT_PULLDOWN、INPUT_PULLUP)
*/
宏说明:
模式宏 | 意义 |
---|---|
INPUT | 将GPIO设置为无上拉或下拉(高阻抗)的输入。 |
OUTPUT | 将GPIO设置为输出模式。 |
INPUT_PULLDOWN | 将GPIO设置为具有内部下拉功能的输入。(在引脚悬空时读取为低电平状态) |
INPUT_PULLUP | 将GPIO设置为具有内部上拉功能的输入。(在引脚悬空时读取为高电平状态)。 |
ESP32 SoC系列通过45kR电阻器支持内部上拉和下拉,当将GPIO模式配置为INPUT模式时,可以启用该功能。如果未定义上拉或下拉模式,引脚将保持在高阻抗模式。
(2)digitalWrite:当使用pinMode配置引脚为OUTPUT时用于控制此GPIO引脚输出状态,设置为高或低。
函数原型:
void digitalWrite(uint8_t pin, uint8_t val);
/*
参数说明:
pin:GPIO管脚编号。
val:GPIO管脚输出电平状态。(HIGH、LOW)
*/
宏说明:
电平状态宏 | 意义 |
---|---|
HIGH | 设置引脚输出高电平 |
LOW | 设置引脚输出低电平 |
(2)digitalRead:用于读取被配置为输入模式(INPUT or INPUT_PULLDOWN or INPUT_PULLUP)引脚的状态。
此函数将所选引脚的逻辑状态返回为高(HIGH)或低(LOW)。
函数原型:
int digitalRead(uint8_t pin);
/*
参数说明:
pin:GPIO管脚编号。
*/
(3)attachInterrupt:用于将中断连接到相应的引脚。
函数原型:
attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode);
/*
参数说明:
pin:GPIO管脚编号。
handler:中断函数
mode:中断模式
*/
宏说明:
中断模式宏 | 意义 |
---|---|
DISABLED | 失能中断 |
RISING | 上升沿触发 |
FALLING | 下降沿触发 |
CHANGE | 上升沿和下降沿都触发 |
ONLOW | 低电平触发 |
ONHIGH | 高电平触发 |
ONLOW_WE | |
ONHIGH_WE |
(4)attachInterruptArg:用于使用参数将中断附加到定义的管脚。
函数原型:
attachInterruptArg(uint8_t pin, voidFuncPtrArg handler, void * arg, int mode);
/*
参数说明:
pin:GPIO管脚编号。
handler:中断函数
arg:指向中断参数的指针。
mode:中断模式
*/
(5)detachInterrupt:从断开特定引脚的中断。
函数原型:
detachInterrupt(uint8_t pin);
/*
参数说明:
pin:GPIO管脚编号。
*/
4、GPIO使用例子
(1)GPIO输入输出模式
#include <Arduino.h>
#define PIN_LED 12
#define PIN_BUTTON 2
#define BUTTON_DOWN LOW //按键按下
#define BUTTON_UP HIGH //按键松开
uint8_t stateLED = 0;
void setup() {
// put your setup code here, to run once:
pinMode(PIN_LED, OUTPUT); //设置LED灯了解的引脚为输出模式
pinMode(PIN_BUTTON,INPUT_PULLUP); //设置按键对应的引脚为上拉输入模式
}
void loop() {
// put your main code here, to run repeatedly:
if( digitalRead(PIN_BUTTON)==BUTTON_DOWN ) //读取按键对应引脚的状态,用于判断按键是否按下
{
stateLED = !stateLED;
digitalWrite(PIN_LED,stateLED);
while(digitalRead(PIN_BUTTON)==BUTTON_DOWN); //保证一次按下只改变一直LED灯的状态
}
}
(2)GPIO中断
#include <Arduino.h>
struct Button {//按键结构体
const uint8_t PIN; //按键对应引脚标号
uint32_t KeyPresses_count; //按键按下次数记录
bool Key_state; //按键是否按下
};
//定义两个按键
Button button1 = {23, 0, false};
Button button2 = {18, 0, false};
//按键1的中断函数
void ARDUINO_ISR_ATTR isr(void* arg) {
Button* s = static_cast<Button*>(arg);
s->KeyPresses_count += 1;
s->Key_state = true;
}
//按键2的中断函数
void ARDUINO_ISR_ATTR isr() {
button2.KeyPresses_count += 1;
button2.Key_state = true;
}
void setup() {
Serial.begin(115200); //配置串口
pinMode(button1.PIN, INPUT_PULLUP); //配置按键1对应的引脚为上拉输入模式
attachInterruptArg(button1.PIN, isr, &button1, FALLING); //给按键2对应引脚连接中断(带参数的中断函数)
pinMode(button2.PIN, INPUT_PULLUP); //配置按键2对应的引脚为上拉输入模式
attachInterrupt(button2.PIN, isr, FALLING); //给按键2对应引脚连接中断
}
void loop() {
if (button1.Key_state) //按键1如果按下通过串口打印按键1累计被按下的次数
{
Serial.printf("Button 1 has been pressed %u times\n", button1.KeyPresses_count);
button1.Key_state = false;
}
if (button2.Key_state) //按键2如果按下通过串口打印按键2累计被按下的次数
{
Serial.printf("Button 2 has been pressed %u times\n", button2.KeyPresses_count);
button2.Key_state = false;
}
static uint32_t lastMillis = 0;
/*
millis():用来获取Arduino开机后运行的时间长度,该时间长度单位是毫秒,
最长可记录接近50天左右的时间。如果超出记录时间上限,记录将从0重新开始。
*/
if (millis() - lastMillis > 10000)//
{
lastMillis = millis();
detachInterrupt(button1.PIN);
}
}
如有不对之处,欢迎大家指正