【问题标题】:Can't set individual PWM frequencies on ESP32 with Arduino framework (on Platformio)无法使用 Arduino 框架在 ESP32 上设置单独的 PWM 频率(在 Platformio 上)
【发布时间】:2021-12-27 21:18:12
【问题描述】:

我正在尝试使用 Arduino 框架在 ESP32 上设置 4 个不同的 PWM(在 GPIO 4、25、26、27 上)。我无法在 GPIO 25 和 26 上设置频率,它们最终会接收到与其他 2 相同的频率(即 GPIO 25 以与 GPIO 4 相同的频率振荡,而 GPIO 26 与 GPIO 27 以相同的频率振荡)。 相关代码部分:

关于头文件:

#define DC_IO_PORTS_QUANTITY 4

typedef enum DC_IO_NUM
{
    DC_IO0,
    DC_IO1,
    DC_IO2,
    DC_IO3

} DC_IO_NUM;

typedef enum DC_IO_PIN
{
    DC_IO0_PIN = 4,
    DC_IO1_PIN = 25,
    DC_IO2_PIN = 26,
    DC_IO3_PIN = 27

} DC_IO_PIN;
//...
void DC_IO_Init(uint8_t resolution, uint16_t freq); //initializes all PWMs with the same frequency and resolution, with 50% duty-cycle
void Set_DC_IO_Freq(DC_IO_NUM dc_iox, uint16_t freq);
//...

关于源文件:

const DC_IO_NUM DC_IO_NUM_TABLE[DC_IO_PORTS_QUANTITY]={DC_IO0, DC_IO1, DC_IO2, DC_IO3};
const DC_IO_PIN DC_IO_PIN_TABLE[DC_IO_PORTS_QUANTITY]={DC_IO0_PIN, DC_IO1_PIN, DC_IO2_PIN, DC_IO3_PIN};

uint16_t full_duty_cycle=1;
uint16_t old_duty_cycle[DC_IO_PORTS_QUANTITY]={0};
uint8_t old_res=0;

void DC_IO_Init(uint8_t resolution, uint16_t freq)
{
    uint16_t half_duty_cycle;

    old_res=resolution;

    uint16_t bit_val=1;
    for(uint8_t k=1;k<resolution;k++)
    {
        bit_val *= 2;
        full_duty_cycle += bit_val;
    }

    half_duty_cycle = full_duty_cycle/2; //50%

    for(uint8_t i=0; i<DC_IO_PORTS_QUANTITY; i++)
    {
        old_duty_cycle[i] = half_duty_cycle;

        ledcSetup(DC_IO_NUM_TABLE[i], freq, old_res);
        ledcWrite(DC_IO_NUM_TABLE[i], old_duty_cycle[i]);
        ledcAttachPin(DC_IO_PIN_TABLE[i], DC_IO_NUM_TABLE[i]);
    }
    vTaskDelay(10);
}
//...
void Set_DC_IO_Freq(DC_IO_NUM dc_iox, uint16_t freq)
{
    ledcSetup(dc_iox, freq, old_res);
    ledcWrite(dc_iox, old_duty_cycle[dc_iox]);
    ledcAttachPin(DC_IO_PIN_TABLE[dc_iox], DC_IO_NUM_TABLE[dc_iox]);
    vTaskDelay(10);
}
//...

在 main.cpp setup() 上:

DC_IO_Init(16, 100); //all pwms on 100Hz 16bits
Set_DC_IO_Freq(DC_IO0,50); //PWM0:=GPIO4 on 50Hz
Set_DC_IO_Freq(DC_IO2,200); //PWM2:=GPIO26 on 200Hz
Set_DC_IO_Freq(DC_IO3,300); //PWM3:=GPIO27 on 300Hz

但是,在示波器上,我可以看到 PWM1 为 50Hz,而 PWM2 为 300Hz...

【问题讨论】:

  • 虽然 PWM 有 16 个通道,但在我看来只有 4 个定时器,所以一次只有 4 个不同的频率:github.com/espressif/arduino-esp32/blob/master/cores/esp32/…我不确定这是什么问题,呵呵。
  • 实际上有 8 个定时器,4 个低速和 4 个高速,它们可以通过多路复用器进行配置,这样每个高速 PWM 都可以连接到四个高速定时器和每个低速 PWM 中的任何一个可以连接到四个低速定时器中的任何一个。然而,在 Arduino 实现中,映射似乎是固定的(或者至少我不知道如何更改它),因此它们成对分配,因此 PWM0 和 1 必须具有相同的频率,PWM2 和 3 必须具有相同的频率等等。因此,如果您使用 PWM 0,2,4 而不是 0,2,3 应该没问题。

标签: arduino esp32 platformio arduino-esp32


【解决方案1】:

根据 ESP32 技术参考手册,2021 年 4.5 版,第 382 页:

图 14-1 显示了 LED_PWM 控制器的架构。从图中可以看出,LED_PWM 控制器包含八个高速通道和八个低速通道。有四个高速 高速通道的时钟模块,可以从中选择一个 h_timerx。低速通道还有四个低速时钟模块,可以从中选择一个 l_timerx。

(重点是我的)

有一张漂亮的图片显示了 4 个定时器进入一个多路复用器,该多路复用器驱动 8 个 pwm 输出,用于慢时钟和快时钟。

所以,我认为您看到了最好的结果 - 两种不同的 PWM 速率。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-18
    • 2023-01-23
    • 1970-01-01
    • 2016-01-27
    相关资源
    最近更新 更多