EPS32基础篇开发

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

开发 EPS32基础篇


前言


提示:以下是本篇文章正文内容,下面案例可供参考

一、GPIO输入输出

  1. 输入模式 (INPUT):当将 pinMode(pin, INPUT)
    设置为输入模式时,该引脚允许从外部电路读取电平信号(高或低),例如连接到按钮、传感器等。
  2. 输出模式 (OUTPUT):通过 pinMode(pin,
    OUTPUT),你可以控制这个引脚作为通用的输出口,可以驱动LED或其他电子元件。
  3. 模拟输入模式 (ANALOGIN):如果你想要将该引脚作为一个ADC(模拟数字转换器)使用,获取电压值而不是简单的二进制状态,可以使用
    pinMode(pin, ANALOGIN)。

GPIO可设置一下4种状态

c 复制代码
// 设置引脚2为输入模式
pinMode(2, INPUT);

// 设置引脚3为输出模式
pinMode(3, OUTPUT);

// 设置引脚4为输入上拉模式(假设Arduino板支持)
pinMode(4, INPUT_PULLUP);
// 设置引脚4为输入下拉模式(假设Arduino板支持)
pinMode(4, INPUT_PULLDOWN);

代码示例:检测按键,按下时:LED亮,松开时,LED灭

c 复制代码
const int buttonPin = 2;  // 定义按键连接的引脚
int ledPin = 13;  // LED灯连接的引脚

void setup() {
  // 初始化串口通信,以便在串口监视器中查看输出
  Serial.begin(9600);
  // 设置按键引脚为输入模式
  pinMode(buttonPin, INPUT_PULLUP);
  // 设置LED引脚为输出模式
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // 读取按键状态
  int buttonState = digitalRead(buttonPin);
  // 在串口监视器中输出按键状态
  if (buttonState == HIGH) {
    Serial.println("Button is NOT pressed");
    digitalWrite(ledPin, LOW);  // 熄灭LED灯
  } else {
    Serial.println("Button is pressed");
    digitalWrite(ledPin, HIGH);  // 点亮LED灯
  }
  // 为了避免串口输出过快,添加一个小延迟
  delay(100);
}

二、PWM输出

基本概念和工作原理

PWM(脉宽调制)是一种用于控制电子设备亮度、音量等特性的技术。在Arduino ESP32中,PWM输出功能用于控制LED灯的亮度,或者驱动电机等。它通过在一定时间内改变高电平(通电)和低电平(断电)的时间比例,来控制设备的亮度或工作状态。

  1. 初始化PWM通道
    -------初始化PWM通道包括选择通道和设置相关参数。使用ledcSetup()函数来设置PWM通道的频率和分辨率。例如,要设置LEDC通道0的频率为1000Hz,分辨率为8位,可以调用ledcSetup(0, 1000, 8);。(有两种分辨率设置8位和10位)
  2. 绑定PWM通道到具体引脚
    ------将初始化后的PWM通道绑定到具体的GPIO引脚,需要使用ledcAttachPin()函数。该函数接受两个参数:要绑定的引脚编号和PWM通道编号。例如,要将引脚2绑定到LEDC通道0,可以调用ledcAttachPin(2, 0);。
  3. 设置PWM的占空比
    ------设置PWM的占空比,可以使用ledcWrite()函数。该函数接受两个参数:PWM通道的编号和要设置的占空比数值。例如,要将LEDC通道0的占空比设置为50%,可以调用ledcWrite(0, 128);,因为8位分辨率的PWM信号的占空比取值范围为0到255,所以128代表50%的占空比。

easeInOutQuad函数 是一种非常有用的缓动函数,它可以在多种应用场景中产生平滑、自然的动画效果;

示例代码:呼吸灯

c 复制代码
#define LED_PIN 14        // LED连接的引脚
#define LEDC_CHANNEL 0    // PWM通道
#define LEDC_FREQ 1000    // PWM频率
#define LEDC_RESOLUTION 8 // 分辨率

// 缓动函数
float easeInOutQuad(float t) {
  if (t < 0.5) return 2 * t * t;
  else         return -1 + (4 - 2 * t) * t;
}

void setup() {
  // 初始化PWM通道
  ledcSetup(LEDC_CHANNEL, LEDC_FREQ, LEDC_RESOLUTION);
  // 将LED引脚绑定到PWM通道
  ledcAttachPin(LED_PIN, LEDC_CHANNEL);
}

void loop() {
  // LED亮度渐增
  for (int i = 0; i <= 255; i++) {
    float t = i / 255.0;
    int dutyCycle = easeInOutQuad(t) * 255;
    ledcWrite(LEDC_CHANNEL, dutyCycle);  // 设置PWM的占空比
    delay(10);  // 延时10毫秒(根据需要调整)
  }

  // LED亮度渐减
  for (int i = 255; i >= 0; i--) {
    float t = i / 255.0;
    int dutyCycle = easeInOutQuad(t) * 255;
    ledcWrite(LEDC_CHANNEL, dutyCycle);  // 设置PWM的占空比
    delay(10);  // 延时10毫秒(根据需要调整)
  }
}

三、外部中断

ESP32的所有GPIO引脚(除了34-39之外)都可以被配置为中断引脚。

中断触发模式列举:attachInterrupt();函数

  1. CHANGE:当外部中断引脚的电平发生变化时触发中断,无论是从低到高还是从高到低。
  2. RISING:当外部中断引脚从低电平变为高电平时触发中断。上升沿
  3. FALLING:当外部中断引脚从高电平变为低电平时触发中断。下降沿
  4. ONLOW:当外部中断引脚处于低电平时触发中断。
  5. ONHIGH:当外部中断引脚处于高电平时触发中断。

代码示例:下降沿检测,计数

c 复制代码
// 定义外部中断引脚
#define INTERRUPTION_PIN 14
// 定义用于计数的变量
volatile int count = 0;

// 中断服务程序
void IRAM_ATTR handleInterrupt() {
  // 增加计数
  count++;
}

void setup() {
  // 初始化串口通信,用于调试
  Serial.begin(115200);

  // 配置外部中断引脚为输入模式
  pinMode(INTERRUPTION_PIN, INPUT_PULLUP);

  // 确保在attachInterrupt之前,引脚4处于高电平状态
  digitalWrite(INTERRUPTION_PIN, HIGH);
  delay(1); // 短暂延时,确保引脚状态稳定

  // 附加中断服务程序到外部中断引脚
  attachInterrupt(digitalPinToInterrupt(INTERRUPTION_PIN), handleInterrupt, FALLING);

  // 输出初始计数
  Serial.println("Initial count: " + String(count));
}

void loop() {
  // 延时一段时间,然后输出当前计数
  delay(1000);
  Serial.println("Current count: " + String(count));
}

四、ADC

使用注意事项:

ESP32的ADC驱动程序API支持ADC1和ADC2。

ADC1有8个通道,连接到GPIO 32-39。

ADC2有10个通道,连接到GPIO 0, 2, 4, 12-15和25-27。但请注意,ADC2与Wi-Fi模块共享资源,因此在使用ADC2时需要注意Wi-Fi状态。

高精度:采用12位分辨率,可以提供较为精确的转换结果。

多通道支持:支持18个模拟输入管脚,满足多种应用场景的需求。

低功耗:部分控制器支持Deep-sleep模式下的低功耗运行。

灵活配置:可配置多种分辨率(如12位、11位、10位、9位)

代码示例:ADC检测

cpp 复制代码
#include <Arduino.h>

const int analogPin = 35; // 定义模拟输入引脚

void setup() {
  Serial.begin(9600); // 初始化串口通信
  pinMode(analogPin, INPUT); // 设置模拟输入引脚为输入模式
  analogReadResolution(12); // 设置ADC分辨率为13位
  analogSetAttenuation(ADC_11db); // 设置ADC衰减倍数为11dB
}

void loop() {
  int sensorValue = analogRead(analogPin); // 读取模拟输入值
  Serial.println(sensorValue); // 打印读取的ADC值
  delay(1000); // 延迟1秒
}

五、定时器

代码示例:定时器

c 复制代码
#define LED_PIN 12 // GPIO2,通常内建LED在ESP32上

// 创建定时器句柄
hw_timer_t * timer = NULL;

// 定义一个标志位用于指示是否要处理定时器事件
volatile bool timerFlag = false;

void IRAM_ATTR onTimer() {
  // 这是定时器中断服务程序 (ISR)
  timerFlag = true;
}

void setup() {
  Serial.begin(115200);
  
  pinMode(LED_PIN, OUTPUT); // 设置LED引脚为输出模式
  digitalWrite(LED_PIN, LOW); // 初始状态关闭LED

  // 设置定时器
  timer = timerBegin(0, 80, true); // 分频因子80意味着定时器计数频率为20MHz/80=250kHz
  timerAttachInterrupt(timer, &onTimer, true); // 将ISR关联到定时器
  timerAlarmWrite(timer, 250000, true); // 每250000微秒(即每秒)产生一次中断
  timerAlarmEnable(timer); // 启用定时器报警
}

void loop() {
  if (timerFlag) {
    // 处理定时器事件
    static bool ledState = false;
    ledState = !ledState; // 反转LED状态
    digitalWrite(LED_PIN, ledState);
    
    Serial.println("Timer triggered!");
    
    timerFlag = false; // 重置标志位
  }
}

六、DHT11

代码示例:250ms读取一次温湿度

c 复制代码
#include "DHT.h" // 包含DHT库

#define LED_PIN 14         // GPIO12,通常内建LED在ESP32上
#define DHTPIN 4           // DHT11连接到GPIO4
#define DHTTYPE DHT11      // 使用DHT 11

// 创建定时器句柄
hw_timer_t * timer = NULL;

// 定义一个标志位用于指示是否要处理定时器事件
volatile bool timerFlag = false;

// 创建DHT对象
DHT dht(DHTPIN, DHTTYPE);

void IRAM_ATTR onTimer() {
  // 这是定时器中断服务程序 (ISR)
  timerFlag = true;
}

void setup() {
  Serial.begin(115200);
  
  pinMode(LED_PIN, OUTPUT); // 设置LED引脚为输出模式
  digitalWrite(LED_PIN, LOW); // 初始状态关闭LED

  // 初始化DHT传感器
  dht.begin();

  // 设置定时器
  timer = timerBegin(0, 80, true); // 分频因子80意味着定时器计数频率为20MHz/80=250kHz
  timerAttachInterrupt(timer, &onTimer, true); // 将ISR关联到定时器
  timerAlarmWrite(timer, 250000, true); // 每250000微秒(即每秒)产生一次中断
  timerAlarmEnable(timer); // 启用定时器报警
}

void loop() {
  if (timerFlag) {
    // 处理定时器事件
    static bool ledState = false;
    ledState = !ledState; // 反转LED状态
    digitalWrite(LED_PIN, ledState);
    
    // 读取温度和湿度
    float humidity = dht.readHumidity();
    float temperature = dht.readTemperature();

    // 检查是否成功读取
    if (isnan(humidity) || isnan(temperature)) {
      Serial.println("Failed to read from DHT sensor!");
    } else {
      // 打印结果
      Serial.print("Humidity: ");
      Serial.print(humidity);
      Serial.print("%  Temperature: ");
      Serial.print(temperature);
      Serial.println("°C");
    }

    Serial.println("Timer triggered!");

    timerFlag = false; // 重置标志位
  }
}

实验现象

七、u8g2驱动SSD1306 屏幕

cpp 复制代码
#include <Wire.h>
#include <U8g2lib.h>
#include "DHT.h"

// DHT传感器配置
#define DHTPIN 4           // DHT11连接到GPIO4
#define DHTTYPE DHT11      // 使用DHT 11
// 定义OLED的宽度和高度
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

// 定义I2C地址和引脚
#define OLED_SDA_PIN 21
#define OLED_SCL_PIN 22
#define OLED_I2C_ADDRESS 0x3C // SSD1306 I2C 地址,默认为0x3C或0x3D


// 创建对象
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ OLED_SCL_PIN, /* data=*/ OLED_SDA_PIN, /* reset=*/ U8X8_PIN_NONE);

DHT dht(DHTPIN, DHTTYPE);

// 创建定时器句柄
hw_timer_t * timer = NULL;
bool timerFlag500ms = false;
void IRAM_ATTR onTimer() {
  // 这是定时器中断服务程序 (ISR)
  timerFlag500ms = true;
}
//函数声明
void DISPLAY_Refresh();

void setup() {
  Serial.begin(115200);
  
  // 初始化U8g2库
  u8g2.begin();
  u8g2.enableUTF8Print(); // 启用UTF-8支持
  // 初始化DHT传感器
  dht.begin();
  // 设置默认字体大小
  u8g2.setFont(u8g2_font_wqy12_t_gb2312); // 使用支持中文的字体

    // 设置定时器
  timer = timerBegin(0, 80, true); // 分频因子80意味着定时器计数频率为20MHz/80=250kHz
  timerAttachInterrupt(timer, &onTimer, true); // 将ISR关联到定时器
  timerAlarmWrite(timer, 50000, true); // 每250000微秒(即每秒)产生一次中断
  timerAlarmEnable(timer); // 启用定时器报警
}

void loop() {
  if(  timerFlag500ms == true)
  {
     timerFlag500ms = false;
     DISPLAY_Refresh();
  }
}
//刷新屏幕显示
void DISPLAY_Refresh()
{
    // 处理定时器事件
    // 读取温度和湿度
    float humidity = dht.readHumidity();
    float temperature = dht.readTemperature();
 
  // 清除屏幕缓冲区
  u8g2.clearBuffer();

  // 设置光标位置并打印中文字符
  u8g2.setCursor(0, 20);
  u8g2.print("温度:"); // 中文文本
  u8g2.setCursor(30, 20);
  u8g2.print( temperature);
  u8g2.print("℃");
  u8g2.setCursor(0, 40);
  u8g2.print("湿度:"); // 中文文本
  u8g2.setCursor(30, 40);
  u8g2.print( humidity);
  u8g2.print("%");

  // 设置光标位置并打印英文字符
  u8g2.setCursor(0, 60);
  u8g2.print("Hello, World!");

  // 将缓冲区内容发送到显示屏
  u8g2.sendBuffer();
}

相关推荐
知困勉行的Allen2 小时前
MCS-51单片机常用汇编指令和特殊功能寄存器~
c语言·汇编·数据结构·单片机·嵌入式硬件·51单片机·学习方法
1101 11016 小时前
STM32-笔记36-ADC(模拟/数字转换器)
笔记·stm32·嵌入式硬件
youcans_7 小时前
【动手学电机驱动】STM32-MBD(3)Simulink 状态机模型的部署
stm32·单片机·嵌入式硬件·matlab·代码生成
end_SJ7 小时前
初学STM32 --- USMART
stm32·单片机·嵌入式硬件
我想学LINUX8 小时前
【stm32+K210项目】基于K210与STM32协同工作的智能垃圾分类系统设计与实现(完整工程资料源码)
stm32·单片机·嵌入式硬件·毕业设计·课程设计·项目
JoneMaster8 小时前
[读书日志]8051软核处理器设计实战(基于FPGA)第五篇:8051软核处理器主体框架搭建(verilog)
嵌入式硬件·fpga开发·硬件架构
end_SJ9 小时前
初学stm32 --- RTC实时时钟
stm32·嵌入式硬件·实时音视频
森旺电子9 小时前
STM32+WIFI获取网络时间+8位数码管显示+0.96OLED显
stm32·单片机·嵌入式硬件
厉昱辰9 小时前
入手51单片机的学习路径
嵌入式硬件·学习·51单片机
析木不会编程10 小时前
STM32的LED点亮教程:使用HAL库与Proteus仿真
stm32·嵌入式硬件·proteus