4. PWM信号频率与占空比测试

任务目标

在ESP32上配置LEDC PWM通道,输出指定频率(例如10 kHz)和占空比(例如60%),并通过示波器测量GPIO引脚的实际波形,验证频率与占空比误差在可接受范围内(频率误差<1%,占空比误差<2%)。

环境与依赖

  • 硬件:ESP32开发板(如ESP32-DevKitC)、USB转串口、示波器(带宽≥20 MHz)
  • 软件:ESP-IDF v5.x 或 Arduino ESP32 核心 2.x(本案例使用ESP-IDF原生驱动)
  • 接线:示波器探头接GPIO2(默认LEDC通道输出引脚),GND共地

关键完整代码


#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/ledc.h"
#include "esp_err.h"

#define PWM_GPIO        2
#define PWM_FREQ_HZ     10000   // 目标频率 10 kHz
#define PWM_DUTY_PCT    60      // 目标占空比 60%
#define LEDC_TIMER      LEDC_TIMER_0
#define LEDC_CHANNEL    LEDC_CHANNEL_0
#define LEDC_MODE       LEDC_LOW_SPEED_MODE
#define LEDC_DUTY_RES   LEDC_TIMER_13_BIT   // 分辨率 13 位 (0~8191)

void app_main(void)
{
    // 1. 配置定时器
    ledc_timer_config_t timer_conf = {
        .speed_mode      = LEDC_MODE,
        .duty_resolution = LEDC_DUTY_RES,
        .timer_num       = LEDC_TIMER,
        .freq_hz         = PWM_FREQ_HZ,
        .clk_cfg         = LEDC_AUTO_CLK
    };
    ESP_ERROR_CHECK(ledc_timer_config(&timer_conf));

    // 2. 配置通道
    ledc_channel_config_t ch_conf = {
        .gpio_num   = PWM_GPIO,
        .speed_mode = LEDC_MODE,
        .channel    = LEDC_CHANNEL,
        .intr_type  = LEDC_INTR_DISABLE,
        .timer_sel  = LEDC_TIMER,
        .duty       = 0,
        .hpoint     = 0
    };
    ESP_ERROR_CHECK(ledc_channel_config(&ch_conf));

    // 3. 计算并设置占空比(13位分辨率:8191 * 60% = 4914)
    uint32_t duty_val = (1 << 13) * PWM_DUTY_PCT / 100;
    ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, duty_val));
    ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));

    printf("PWM输出已启动: GPIO%d, %d Hz, %d%% 占空比\n", PWM_GPIO, PWM_FREQ_HZ, PWM_DUTY_PCT);
    printf("理论占空比寄存器值: %lu (13位分辨率)\n", (unsigned long)duty_val);

    // 保持运行
    while (1) {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

编译与烧录


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

验证方法与判定标准

  1. 示波器探头接GPIO2,地线接GND,设置时基10 µs/div,垂直刻度2 V/div。
  2. 观察波形应为方波,高电平约3.3 V,低电平接近0 V。
  3. 测量频率:读取示波器频率测量值,应在9.90~10.10 kHz范围内(误差<1%)。
  4. 测量占空比:使用示波器占空比测量功能,读数应在58%~62%之间(误差<2%)。
  5. 若超出范围,检查电源稳定性、探头补偿是否校准、GPIO2是否被其他外设占用。

常见问题

  • 无波形输出:确认GPIO2在开发板上未被占用(部分板载LED连接GPIO2,需断开跳线或换用GPIO4/5并同步修改代码)。
  • 频率偏差较大:LEDC时钟源精度有限,实测频率与配置值存在±0.5%以内偏差属正常;若偏差过大,检查是否误用LEDC_HIGH_SPEED_MODE(ESP32不支持)。
  • 占空比边缘不陡:示波器探头接地线过长会引入振铃,使用接地弹簧缩短地线回路。