1. GPIO引脚功能自检

GPIO引脚功能自检 学习卡片

任务目标

编写ESP32固件自检程序,依次将每个可用GPIO引脚配置为输入模式并读取电平,通过外部跳线将引脚连接至已知电平(GND或3.3V),从而检测引脚是否存在短路或断路故障,并在串口输出每个引脚的测试结果。

硬件准备

  • ESP32开发板(如ESP32-WROOM-32)
  • USB转串口线(用于烧录与查看日志)
  • 杜邦线若干(用于将GPIO连接到GND或3.3V)

测试原理

将待测GPIO配置为输入模式并启用内部上拉电阻,读取电平应为高(1);随后启用内部下拉电阻,读取电平应为低(0)。若两种状态下读数均正确,说明引脚无短路、断路;若读数与预期不符,则判定引脚异常。此方法无需外部上拉/下拉电阻,仅依赖ESP32内部弱上拉/下拉,适合快速产线自检。

关键完整代码

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"

#define TEST_GPIO_MAX 40  // ESP32可用GPIO编号范围0~39

static const char *TAG = "GPIO_SELFTEST";

// 可测试的GPIO列表(排除电源、Flash、Strapping等不可用引脚)
static const gpio_num_t test_gpios[] = {
    GPIO_NUM_0, GPIO_NUM_2, GPIO_NUM_4, GPIO_NUM_5,
    GPIO_NUM_12, GPIO_NUM_13, GPIO_NUM_14, GPIO_NUM_15,
    GPIO_NUM_16, GPIO_NUM_17, GPIO_NUM_18, GPIO_NUM_19,
    GPIO_NUM_21, GPIO_NUM_22, GPIO_NUM_23, GPIO_NUM_25,
    GPIO_NUM_26, GPIO_NUM_27, GPIO_NUM_32, GPIO_NUM_33,
    GPIO_NUM_34, GPIO_NUM_35, GPIO_NUM_36, GPIO_NUM_39
};
#define TEST_GPIO_COUNT (sizeof(test_gpios) / sizeof(test_gpios[0]))

static bool test_single_gpio(gpio_num_t gpio) {
    // 测试上拉:读高
    gpio_set_direction(gpio, GPIO_MODE_INPUT);
    gpio_set_pull_mode(gpio, GPIO_PULLUP_ONLY);
    vTaskDelay(pdMS_TO_TICKS(10));
    int level_pullup = gpio_get_level(gpio);

    // 测试下拉:读低
    gpio_set_pull_mode(gpio, GPIO_PULLDOWN_ONLY);
    vTaskDelay(pdMS_TO_TICKS(10));
    int level_pulldown = gpio_get_level(gpio);

    // 恢复默认状态(无上下拉)
    gpio_set_pull_mode(gpio, GPIO_FLOATING);

    return (level_pullup == 1 && level_pulldown == 0);
}

void app_main(void) {
    ESP_LOGI(TAG, "GPIO引脚功能自检开始");
    int pass_count = 0;
    int fail_count = 0;

    for (int i = 0; i < TEST_GPIO_COUNT; i++) {
        gpio_num_t gpio = test_gpios[i];
        bool result = test_single_gpio(gpio);
        if (result) {
            pass_count++;
            ESP_LOGI(TAG, "GPIO %d: PASS", gpio);
        } else {
            fail_count++;
            ESP_LOGE(TAG, "GPIO %d: FAIL (上拉=%d, 下拉=%d)", 
                     gpio, 
                     gpio_get_level(gpio) == 1 ? 1 : 0,  // 仅用于日志显示
                     gpio_get_level(gpio) == 0 ? 0 : 1);
        }
    }

    ESP_LOGI(TAG, "测试完成: 通过 %d, 失败 %d", pass_count, fail_count);
    if (fail_count == 0) {
        ESP_LOGI(TAG, "结果: 全部通过");
    } else {
        ESP_LOGE(TAG, "结果: 存在失败引脚");
    }
}

编译与烧录

idf.py set-target esp32
idf.py build
idf.py -p /dev/ttyUSB0 flash monitor

验证方法与判定标准

  1. 将ESP32开发板通过USB连接电脑,确保串口驱动已安装。
  2. 执行上述编译烧录命令,打开串口监视器(波特率默认115200)。
  3. 观察日志输出:每个GPIO引脚会打印PASS或FAIL状态。
  4. 通过标准:所有测试引脚均显示PASS,且最终汇总显示“通过 24, 失败 0”。
  5. 故障模拟验证:用杜邦线将某个被测引脚(如GPIO4)直接短接到GND,重新运行测试,该引脚应显示FAIL(因上拉读不到高电平),证明检测有效。

注意事项

  • GPIO 6~11 连接外部Flash,GPIO 1、3 为UART0调试口,GPIO 34~39 仅支持输入模式(无内部上拉/下拉),因此上述列表已排除这些引脚。
  • GPIO 0 为Strapping引脚,测试时需确保开发板未进入下载模式。
  • 若某引脚FAIL,先检查是否因外部电路干扰(如开发板上的LED、按键等),必要时断开外设后重测。