ESP32 Control LED Brightness (PWM) with ESP-IDF
main.c
#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
// *** 修正: 替換為新的 ADC 驅動 API ***
#include "esp_adc/adc_oneshot.h"
// **********************************
#include "driver/ledc.h"
#define SAMPLE_CNT 32
// 注意:GPIO32 是 ESP32 ADC1 的 Channel 4
static const adc_channel_t adc_channel = ADC_CHANNEL_4;
#define LEDC_GPIO 27
static ledc_channel_config_t ledc_channel;
// *** 修正: 使用新的 ADC oneshot 句柄 ***
static adc_oneshot_unit_handle_t adc1_handle;
static void init_hw(void)
{
// 1. 配置並校準 ADC
adc_oneshot_unit_init_cfg_t init_config = {
.unit_id = ADC_UNIT_1, // 使用 ADC1
};
// 初始化 ADC 模組
ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc1_handle));
adc_oneshot_chan_cfg_t config = {
.bitwidth = ADC_BITWIDTH_DEFAULT, // 默認為 10 bit
// *** 修正: 使用新的衰減常數 ADC_ATTEN_DB_12 (取代已棄用的 DB_11) ***
.atten = ADC_ATTEN_DB_12,
};
// 配置 ADC 通道
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, adc_channel, &config));
// 2. 配置 LEDC (PWM)
ledc_timer_config_t ledc_timer = {
.duty_resolution = LEDC_TIMER_10_BIT,
.freq_hz = 1000,
.speed_mode = LEDC_LOW_SPEED_MODE, // 建議使用 LOW_SPEED_MODE
.timer_num = LEDC_TIMER_0,
.clk_cfg = LEDC_AUTO_CLK,
};
ledc_timer_config(&ledc_timer);
ledc_channel.channel = LEDC_CHANNEL_0;
ledc_channel.duty = 0;
ledc_channel.gpio_num = LEDC_GPIO;
ledc_channel.speed_mode = LEDC_LOW_SPEED_MODE;
ledc_channel.hpoint = 0;
ledc_channel.timer_sel = LEDC_TIMER_0;
ledc_channel_config(&ledc_channel);
}
void app_main()
{
init_hw();
while (1)
{
int adc_raw = 0;
int adc_val = 0;
// 讀取多次取樣並平均
for (int i = 0; i < SAMPLE_CNT; ++i)
{
// *** 修正: 使用新的 ADC oneshot 讀取 API ***
adc_oneshot_read(adc1_handle, adc_channel, &adc_raw);
adc_val += adc_raw;
// *****************************************
}
adc_val /= SAMPLE_CNT;
// 將 ADC 值 (0-1023) 作為 PWM 的 Duty (0-1023)
ledc_set_duty(ledc_channel.speed_mode, ledc_channel.channel, adc_val);
ledc_update_duty(ledc_channel.speed_mode, ledc_channel.channel);
// *** 修正: 替換為正確的 FreeRTOS 宏 ***
vTaskDelay(pdMS_TO_TICKS(500));
// 替代方法: vTaskDelay(500 / portTICK_PERIOD_MS);
// 推薦使用 pdMS_TO_TICKS() 宏,因為它更簡潔且安全。
}
}






沒有留言:
張貼留言