05 - GPIO 外设

通用输入输出与PWM控制

GPIO 基础

初始化与配置

#include "driver/gpio.h"
 
// 复位指定GPIO
gpio_reset_pin(GPIO_NUM_2);
 
// 设置方向
gpio_set_direction(GPIO_NUM_2, GPIO_MODE_OUTPUT);
 
// 设置方向 (输入)
gpio_set_direction(GPIO_NUM_4, GPIO_MODE_INPUT);
 
// 设置上拉/下拉
gpio_set_pull_mode(GPIO_NUM_4, GPIO_PULLUP_ONLY);   // 上拉
gpio_set_pull_mode(GPIO_NUM_4, GPIO_PULLDOWN_ONLY); // 下拉
gpio_set_pull_mode(GPIO_NUM_4, GPIO_FLOATING);      // 浮空

读写操作

// 输出电平
gpio_set_level(GPIO_NUM_2, 1);  // 高电平
gpio_set_level(GPIO_NUM_2, 0);  // 低电平
 
// 读取电平
int level = gpio_get_level(GPIO_NUM_4);
 
// 读取模式
gpio_mode_t mode = gpio_get_mode(GPIO_NUM_4);

中断处理

中断配置

#include "driver/gpio.h"
#include "esp_intr_alloc.h"
 
static IRAM_ATTR void gpio_isr_handler(void *arg)
{
    uint32_t gpio_num = (uint32_t) arg;
    printf("GPIO %d interrupted!\n", gpio_num);
}
 
void setup_gpio_interrupt(void)
{
    gpio_config_t io_conf = {
        .pin_bit_mask = (1ULL << GPIO_NUM_4),
        .mode = GPIO_MODE_INPUT,
        .pull_up_en = GPIO_PULLUP_ENABLE,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_POSEDGE  // 上升沿触发
    };
    gpio_config(&io_conf);
 
    gpio_install_isr_service(0);
    gpio_isr_handler_add(GPIO_NUM_4, gpio_isr_handler, (void *) GPIO_NUM_4);
}

中断触发类型

模式说明
GPIO_INTR_DISABLE禁用中断
GPIO_INTR_POSEDGE上升沿触发
GPIO_INTR_NEGEDGE下降沿触发
GPIO_INTR_ANYEDGE任意边沿触发
GPIO_INTR_LOW_LEVEL低电平触发
GPIO_INTR_HIGH_LEVEL高电平触发

LEDC (PWM)

PWM 输出配置

#include "driver/ledc.h"
 
void ledc_pwm_init(void)
{
    // 配置定时器
    ledc_timer_config_t timer_conf = {
        .speed_mode       = LEDC_LOW_SPEED_MODE,
        .timer_num        = LEDC_TIMER_0,
        .duty_resolution  = LEDC_TIMER_8_BIT,  // 8位分辨率 (0-255)
        .freq_hz          = 1000,              // 1kHz
        .clk_cfg          = LEDC_AUTO_CLK
    };
    ledc_timer_config(&timer_conf);
 
    // 配置通道
    ledc_channel_config_t channel_conf = {
        .gpio_num       = GPIO_NUM_2,
        .speed_mode     = LEDC_LOW_SPEED_MODE,
        .channel        = LEDC_CHANNEL_0,
        .timer_sel      = LEDC_TIMER_0,
        .duty           = 0,
        .hpoint         = 0
    };
    ledc_channel_config(&channel_conf);
}
 
// 设置占空比
void ledc_set_duty(uint8_t duty)
{
    ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty);
    ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
}

呼吸灯效果

void breathe_ledc(void)
{
    int direction = 1;
    int duty = 0;
 
    while (1) {
        duty += direction * 5;
        if (duty >= 255) direction = -1;
        if (duty <= 0) direction = 1;
 
        ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty);
        ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
        vTaskDelay(pdMS_TO_TICKS(20));
    }
}

DAC 输出

数模转换

#include "driver/dac.h"
 
// 初始化 DAC1 (GPIO25)
void dac_init(void)
{
    dac_output_enable(DAC_CHANNEL_1);
}
 
// 输出电压 (0-255 对应 0-3.3V)
void dac_output(uint8_t value)
{
    dac_output_voltage(DAC_CHANNEL_1, value);
}
 
// 输出正弦波示例
void dac_sine_wave(void)
{
    int i = 0;
    while (1) {
        uint8_t value = (sin(i * 0.1) + 1) * 127;  // 0-254
        dac_output_voltage(DAC_CHANNEL_1, value);
        vTaskDelay(pdMS_TO_TICKS(10));
        i++;
    }
}

DAC 参数

通道GPIO分辨率
DAC1GPIO258-bit
DAC2GPIO268-bit

ADC 采样

模数转换

#include "driver/adc.h"
#include "esp_adc_cal.h"
 
#define ADC_PIN ADC1_CHANNEL_7  // GPIO35
 
void adc_init(void)
{
    adc1_config_width(ADC_WIDTH_BIT_12);           // 12位分辨率
    adc1_config_channel_atten(ADC_PIN, ADC_ATTEN_DB_11);  // 0-3.3V
}
 
uint32_t adc_read(void)
{
    return adc1_get_raw(ADC_PIN);
}
 
// 带校准读取
void adc_read_calibrated(void)
{
    esp_adc_cal_characteristics_t chars;
    esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, 1100, &chars);
 
    uint32_t voltage = esp_adc_cal_raw_to_voltage(adc1_get_raw(ADC_PIN), &chars);
    printf("Voltage: %umV\n", voltage);
}

ADC 参数

参数值
分辨率9/10/11/12 位
衰减0-3.3V / 0-2.6V / 0-1.7V / 0-1.1V
采样率~ 6kHz

ADC1 通道映射

通道GPIO用途
ADC1_CH0GPIO36外部输入
ADC1_CH1GPIO37外部输入
ADC1_CH2GPIO38外部输入
ADC1_CH3GPIO39外部输入
ADC1_CH4GPIO32外部输入
ADC1_CH5GPIO33外部输入
ADC1_CH6GPIO34外部输入
ADC1_CH7GPIO35外部输入

触摸传感器

#include "driver/touch_pad.h"
 
void touch_init(void)
{
    touch_pad_init();
    touch_pad_config(TOUCH_PAD_NUM4, 0);  // GPIO4
}
 
void touch_read(void)
{
    uint16_t touch_value;
    touch_pad_read_filtered(TOUCH_PAD_NUM4, &touch_value);
    printf("Touch value: %d\n", touch_value);
}

参考资料

官方文档

技术参考

图片参考

ESP32 GPIO 分布图


相关链接

反向链接

进阶学习


下一步