《ESP32 学习笔记》 之Arduino环境下 如何优雅的输出 频率占空比可调 的PWM波

  • Arduino环境下,我们如何优雅的输出频率可变的PWM波?

  • 支持ADC功能的引脚请查看:引脚定义

这里我们就要借助 esp32-hal-ledc.c 和 esp32-hal-ledc.h 两个文件来完成 esp32-hal库 内置的 PWM 功能

1.在esp32-hal-ledc.c这个文件中,我们可以看到每个通道的和组、定时器的关系,共0~15个通道:

        ** LEDC Chan to Group/Channel/Timer Mapping
        ** ledc: 0  => Group: 0,  Channel: 0, Timer: 0
        ** ledc: 1  => Group: 0,  Channel: 1, Timer: 0
        ** ledc: 2  => Group: 0,  Channel: 2, Timer: 1
        ** ledc: 3  => Group: 0,  Channel: 3, Timer: 1
        ** ledc: 4  => Group: 0,  Channel: 4, Timer: 2
        ** ledc: 5  => Group: 0,  Channel: 5, Timer: 2
        ** ledc: 6  => Group: 0,  Channel: 6, Timer: 3
        ** ledc: 7  => Group: 0,  Channel: 7, Timer: 3
        ** ledc: 8  => Group: 1,  Channel: 0, Timer: 0
        ** ledc: 9  => Group: 1,  Channel: 1, Timer: 0
        ** ledc: 10 => Group: 1, Channel: 2, Timer: 1
        ** ledc: 11 => Group: 1, Channel: 3, Timer: 1
        ** ledc: 12 => Group: 1, Channel: 4, Timer: 2
        ** ledc: 13 => Group: 1, Channel: 5, Timer: 2
        ** ledc: 14 => Group: 1, Channel: 6, Timer: 3
        ** ledc: 15 => Group: 1, Channel: 7, Timer: 3

2. 在esp32-hal-ledc.h中,我们可以看到PWM相关的一些函数:

#ifndef _ESP32_HAL_LEDC_H_
#define _ESP32_HAL_LEDC_H_

#ifdef __cplusplus
extern "C" {
#endif

#include 
#include 

typedef enum {
    NOTE_C, NOTE_Cs, NOTE_D, NOTE_Eb, NOTE_E, NOTE_F, NOTE_Fs, NOTE_G, NOTE_Gs, NOTE_A, NOTE_Bb, NOTE_B, NOTE_MAX
} note_t;

//channel 0-15 resolution 1-16bits freq limits depend on resolution
double      ledcSetup(uint8_t channel, double freq, uint8_t resolution_bits);//设置通道频率和分辨率
void        ledcWrite(uint8_t channel, uint32_t duty);//设置通道占空比
double      ledcWriteTone(uint8_t channel, double freq);//设置通道频率
double      ledcWriteNote(uint8_t channel, note_t note, uint8_t octave);//输出需要的音阶
uint32_t    ledcRead(uint8_t channel);//读取某个通道的占空比
double      ledcReadFreq(uint8_t channel);//读取通道频率
void        ledcAttachPin(uint8_t pin, uint8_t channel);//将通道与引脚绑定
void        ledcDetachPin(uint8_t pin);//解绑引脚与通道的关系


#ifdef __cplusplus
}
#endif

#endif /* _ESP32_HAL_LEDC_H_ */

3.其中ledcWriteNote函数为输出一些音阶,可以接上蜂鸣器发出一些简单的音频, 函数如下:

double ledcWriteNote(uint8_t chan, note_t note, uint8_t octave){
    const uint16_t noteFrequencyBase[12] = {
    //   C        C#       D        Eb       E        F       F#        G       G#        A       Bb        B
        4186,    4435,    4699,    4978,    5274,    5588,    5920,    6272,    6645,    7040,    7459,    7902
    };

    if(octave > 8 || note >= NOTE_MAX){
        return 0;
    }
    double noteFreq =  (double)noteFrequencyBase[note] / (double)(1 << (8-octave));
    return ledcWriteTone(chan, noteFreq);
}
  • 例子代码功能:在Arduino环境下输出频率可变的PWM波

/*
@功能:输出两路PWM,可调占空比
@时间:2020/3/5
@作者:刘泽文
@QQ:2822604962
*/
#include 
 
#define LED1 19
#define LED2 22
#define LED1_OFF   digitalWrite(LED1, HIGH)//关灯1
#define LED1_ON    digitalWrite(LED1, LOW)//开灯1
#define LED1_PWM   digitalWrite(LED1, !digitalRead(LED1))//灯1闪烁
#define LED2_OFF   digitalWrite(LED2, HIGH)//关灯2
#define LED2_ON    digitalWrite(LED2, LOW)//开灯2
#define LED2_PWM   digitalWrite(LED2, !digitalRead(LED2))//灯2闪烁

int freq1 = 2000;    // 频率
int channel1 = 0;    // 通道0,共16个通道,0~15
int resolution1 = 10;   // 分辨率,取值0~20,duty最大取值为2^resolution-1

int freq2 = 2000;    // 频率
int channel2 = 1;    // 通道1,共16个通道,0~15
int resolution2 = 10;   // 分辨率,取值0~20,duty最大取值为2^resolution-1

void setup()
{
  ledcSetup(channel1, freq1, resolution1); // 设置通道0
  ledcSetup(channel2, freq2, resolution2); // 设置通道1
  ledcAttachPin(LED1, channel1);  // 将通道0与引脚19连接
  ledcAttachPin(LED2, channel2);  // 将通道1与引脚22连接
}

void loop()
{
  // 逐渐变亮
  for (int dutyCycle = 0; dutyCycle <= 1023; dutyCycle = dutyCycle + 5)
  {
    ledcWrite(channel1, dutyCycle);  // 输出PWM
    ledcWrite(channel2, 1023 - dutyCycle);  // 输出PWM
    delay(5);
  }

  // 逐渐变暗
  for (int dutyCycle = 1023; dutyCycle >= 0; dutyCycle = dutyCycle - 5)
  {
    ledcWrite(channel1, dutyCycle);  // 输出PWM
    ledcWrite(channel2, 1023 - dutyCycle);  // 输出PWM
    delay(5);
  }
}
  • 将代码上传到你的ESP32板卡上

实验效果:LED1 与 LED2 为呼吸灯状态,且亮度互补~

你可能感兴趣的:(ESP32,学习笔记)