目录

  • 介绍
  • 函数实现和简化
  • 介绍

    本文展示了在Arduino环境下ESP32的DAC的使用。
    ESP32有2路8位DAC,其中DAC1在PIN25,DAC2在PIN26,DAC引脚由于是模拟引脚,因此无法通过IO_MUX映射。
    Arduino库提供了 dacWrite(uint8_t pin, uint8_t value) 这个函数,只需要传入引脚号(25或26)以及8位的输出设定值即可。
    ESP32还能通过I2S将数据连续输出到DAC,这在DAC播放音频时十分有用,这种方法详见我的另一篇文章:ESP32使用I2S及I2S输出到DAC(Arduino)
    还有一些高级用法,需要IDF库,可参考ESP-IDF编程指南DAC章节

    函数实现和简化

    使用 dacWrite 函数是最方便的方法,但该函数封装得比较完备或者说复杂,因此速度可能会牺牲一些,此函数位于 esp32-hal-dac.c 中(路径在Arduino放开发板包的文件夹里的:\esp32\hardware\esp32\1.0.6\cores\esp32,其中1.0.6是版本,我这里的可能偏旧一点),函数实现如下:

    void IRAM_ATTR __dacWrite(uint8_t pin, uint8_t value)
    {
        if(pin < 25 || pin > 26){
            return;//not dac pin
        }
        pinMode(pin, ANALOG);
        uint8_t channel = pin - 25;
    
    
        //Disable Tone
        CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL1_REG, SENS_SW_TONE_EN);
    
        if (channel) {
            //Disable Channel Tone
            CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN2_M);
            //Set the Dac value
            SET_PERI_REG_BITS(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_DAC, value, RTC_IO_PDAC2_DAC_S);   //dac_output
            //Channel output enable
            SET_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_XPD_DAC | RTC_IO_PDAC2_DAC_XPD_FORCE);
        } else {
            //Disable Channel Tone
            CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN1_M);
            //Set the Dac value
            SET_PERI_REG_BITS(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_DAC, value, RTC_IO_PDAC1_DAC_S);   //dac_output
            //Channel output enable
            SET_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE);
        }
    }
    extern void dacWrite(uint8_t pin, uint8_t value) __attribute__ ((weak, alias("__dacWrite")));
    

    可见该函数每次都要判断引脚号是否合法,然后设置引脚模式,还要清除一些东西,实际上这里的许多操作不需要每次都执行,据我自己测试,除了 SET_PERI_REG_BITS 函数,其他的在初始化时执行一次即可,所以代码可以改成以下的形式:

    #define dac1Write(value) SET_PERI_REG_BITS(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_DAC, (value), RTC_IO_PDAC1_DAC_S)
    #define dac2Write(value) SET_PERI_REG_BITS(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_DAC, (value), RTC_IO_PDAC2_DAC_S)
    
    void setup(){
      dacWrite(25, 0);//利用该函数初始化DAC1(PIN25)
    }
    
    void loop(){
      uint8_t test = 0;
      while(1){//锯齿波测试代码
        dac1Write(test++);//设置DAC1的值
      }
    }
    

    也就是在初始化DAC时利用 dacWrite 函数来让它配置好,之后只需要使用代码里这两个宏来修改输出值就可以了。
    据测试,直接使用 dacWrite 时锯齿波的频率约为 735Hz,改为 dac1Write 后频率提升至约 3380Hz,速度提升到了原来的约4.5倍。

    作者:LightAndElectricity

    物联沃分享整理
    物联沃-IOTWORD物联网 » ESP32使用DAC(Arduino)

    发表回复