0%

[ESP32]DAC使用

概述

ESP32 具有两个8位数模转换器通道(DAC),其中 GPIO25 为通道1 、GPIO26为通道2。

DAC驱动器允许将这些通道设置为任意电压。

当使用“内置DAC模式”时,还可以通过I2S驱动器以DMA风格的写入采样数据来驱动DAC通道。

有关其他模拟输出选项,请参见Sigma-delta调制模块和LED控制模块。这两个模块均产生高频PWM输出,可以对其进行硬件低通滤波,以生成低频任意电压模拟输出。

Arduino层编程

极为简单,就只需调用一个函数:void dacWrite(uint8_t pin, uint8_t value) 即可。
其中 pin 只能为 25 与 26 号引脚。由于是8位转换器,所以可知value的范围:0-255。
而底层则是直接调用寄存器,可以提高程序的执行效率。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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);
}
}

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <Arduino.h>

uint8_t val = 0;

void setup()
{
Serial.begin(9600);
dacWrite(25,0);
delay(500);
}

void loop()
{
delay(1000);
val+=20;
if(val>200) val=0;
dacWrite(25,val);
}

再来一个呼吸灯例程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <Arduino.h>
#include <esp32-hal-dac.h>//DAC功能引用该库,可以不进行#include<>引用

//查看源码后得到,DAC引脚只能是这两个引脚
#define LED1 25
#define LED2 26

void setup(){
//长时候发现,DAC的IO口也可以不进行初始化
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
}

void loop()
{
// 逐渐变亮
for (int dutyCycle = 0; dutyCycle <= 255; dutyCycle = dutyCycle + 1)
{
dacWrite(LED1, dutyCycle); // 输出DAC
dacWrite(LED2, 255 - dutyCycle); // 输出DAC
delay(5);
}

// 逐渐变暗
for (int dutyCycle = 255; dutyCycle >= 0; dutyCycle = dutyCycle - 1)
{
dacWrite(LED1, dutyCycle); // 输出DAC
dacWrite(LED2, 255 - dutyCycle); // 输出DAC
delay(5);
}
}

后续

接下来我会使用这两个DAC结合外围电路实现恒压源和恒流源,敬请期待