ESP32 ADC

来自Jack's Lab
跳转到: 导航, 搜索

目录

1 Overview

ESP32 integrates 12-bit SAR ADCs and supports measurements on 18 channels (analog enabled pins).

Some of these pins can be used to build a programmable gain amplifier which is used for the measurement of small analog signals. (IO36 and IO39 on Quantum board)

The ULP-coprocessor in ESP32 is also designed to measure the voltages while operating in the sleep mode, to enable low power consumption; the CPU can be woken up by a threshold setting and/or via other triggers.


All ADC pins of ESP32:


Esp32-pin-adc.jpg


Quantum Board use the IO36, IO39, IO34, IO35, IO14, IO12, IO13, IO15 only



2 API

In librtc.a:

enum adc1_pad {
    ADC1_GPIO36 = 0,
    ADC1_GPIO37,
    ADC1_GPIO38,
    ADC1_GPIO39,
    ADC1_GPIO32,
    ADC1_GPIO33,
    ADC1_GPIO34,
    ADC1_GPIO35
};

enum adc2_pad { 
    ADC2_GPIO4 = 0,
    ADC2_GPIO0,
    ADC2_GPIO2,
    ADC2_GPIO15, 
    ADC2_GPIO13,
    ADC2_GPIO12,
    ADC2_GPIO14,
    ADC2_GPIO27,
    ADC2_GPIO25,
    ADC2_GPIO26
};

enum adc_atten {
    ADC_ATTEN_0DB = 0,     /* 0 ~ 1V can be measured */
    ADC_ATTEN_3DB,         /* 0 ~ 1.4V can be measured */
    ADC_ATTEN_6DB,         /* 0 ~ 2V can be measured */
    ADC_ATTEN_12DB         /* 0 ~ 4V can be measured */
};

/* Range of the return value is [0, 4096] */
uint32_t adc1_read(enum adc1_pad pad, enum adc_atten att);
uint32_t adc2_read(enum adc1_pad pad, enum adc_atten att);

/* 
 * Read the amp adc, IO36 as the ADC_PRE_AMP
 * make sure connecting a 270pF cap from
 * esp32_pin5 to esp32_pin6
 */
uint32_t adc1_amp_read();



3 Quick Start

3.1 Build

$ sudo apt-get install git wget make libncurses-dev flex bison gperf python python-serial
$ wget https://dl.espressif.com/dl/xtensa-esp32-elf-linux32-1.22.0-59.tar.gz
$ mkdir -p toolchain
$ tar zxf xtensa-esp32-elf-linux32-1.22.0-59.tar.gz -C toolchain
$ export PATH=$PATH:`pwd`/toolchain/xtensa-esp32-elf/bin
$
$ git clone --recursive git://github.com/icamgo/esp-idf.git
$ export IDF_PATH=`pwd`/esp-idf
$ cd esp-idf/examples/09_adc_read
$ make menuconfig
$ make -j2



3.2 Connections

Quantum-adc1-1024.jpg


To test the ADC pin of ESP32 on Quantum:

  • Connect the Quantum_IO35 to 3V3 (measure the power voltage)
  • Connect the Quantum_IO34 to GND (measure the GND voltage)
  • Connect the Quantum_IO36 to GND



3.3 Upload

$ make flash

You need to press the RST buttom after uploading the firmware into flash. If you guys do not like to do this please patch the /path/to/esp-idf/components/esptool_py/esptool/esptool.py :

diff --git a/esptool.py b/esptool.py
index 755f4cb..ff92c91 100755
--- a/esptool.py
+++ b/esptool.py
@@ -197,6 +197,12 @@ class ESPLoader(object):
               + '\xc0'
         self._port.write(buf)
 
+    def reset_to_app(self):
+        self._port.setDTR(False)
+        self._port.setRTS(True)
+        time.sleep(0.05)
+        self._port.setRTS(True)
+
     """ Calculate checksum of a blob, as it is defined by the ROM """
     @staticmethod
     def checksum(data, state=ESP_CHECKSUM_MAGIC):
@@ -1421,7 +1427,6 @@ def dump_mem(esp, args):
         sys.stdout.flush()
     print 'Done!'
 
-
 def write_flash(esp, args):
     """Write data to flash
     """
@@ -1503,6 +1508,7 @@ def write_flash(esp, args):
     if args.verify:
         print 'Verifying just-written flash...'
         verify_flash(esp, args, header_block)
+    esp.reset_to_app()
 
 
 def image_info(args):

Then Quantum can reset to run your app automatically after uploading the firmware into flash


3.4 Checking Output

$ picocom -b 115200 /dev/ttyUSB0
ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
ets Jun  8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0x00
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:QIO, clock div:1
load:0x3ffc0000,len:0
load:0x3ffc0000,len:920
load:0x40078000,len:3220
ho 0 tail 12 room 4
load:0x40080000,len:260
entry 0x40080034
I (63) heap_alloc_caps: Initializing heap allocator:
I (63) heap_alloc_caps: Region 19: 3FFB45D8 len 0002BA28 tag 0
I (64) heap_alloc_caps: Region 25: 3FFE8000 len 00018000 tag 1
I (74) cpu_start: Pro cpu up.
I (80) cpu_start: Single core mode
I (86) cpu_start: Pro cpu start user code
rtc v118 Oct 19 2016 15:22:11
XTAL 40M
I (121) cpu_start: Starting scheduler on PRO CPU.
Welcome to Noduino Quantum
Try to test the ADC1 pin of the ESP32 ...
ESP32 onchip ADC1 (IO36) = 0
ESP32 onchip ADC1 (IO39) = 0
ESP32 onchip ADC1 (IO34) = 0
ESP32 onchip ADC1 (IO35) = 4095
ESP32 ADC PRE AMP (IO36) = 0

ESP32 onchip ADC1 (IO36) = 0
ESP32 onchip ADC1 (IO39) = 0
ESP32 onchip ADC1 (IO34) = 0
ESP32 onchip ADC1 (IO35) = 4095
ESP32 ADC PRE AMP (IO36) = 0
......
......



4 Hacking

4.1 ibrtc.a

ADC1:

   0x4008b84c <adc1_pad_init>:	entry	a1, 32
   0x4008b84f <adc1_pad_init+3>:	extui	a2, a2, 0, 8
   0x4008b852 <adc1_pad_init+6>:	movi.n	a3, 0
   0x4008b854 <adc1_pad_init+8>:	bgeui	a2, 8, 0x4008b85f <adc1_pad_init+19>
   0x4008b857 <adc1_pad_init+11>:	l32r	a3, 0x4008b848
   0x4008b85a <adc1_pad_init+14>:	addx4	a2, a2, a3
   0x4008b85d <adc1_pad_init+17>:	l32i.n	a3, a2, 0
   0x4008b85f <adc1_pad_init+19>:	mov.n	a10, a3
   0x4008b861 <adc1_pad_init+21>:	movi.n	a11, 0
   0x4008b863 <adc1_pad_init+23>:	call8	0x4008cd84 <rtc_pads_pu>
   0x4008b866 <adc1_pad_init+26>:	mov.n	a10, a3
   0x4008b868 <adc1_pad_init+28>:	movi.n	a11, 0
   0x4008b86a <adc1_pad_init+30>:	call8	0x4008cf0c <rtc_pads_pd>
   0x4008b86d <adc1_pad_init+33>:	mov.n	a10, a3
   0x4008b86f <adc1_pad_init+35>:	movi.n	a11, 0
   0x4008b871 <adc1_pad_init+37>:	call8	0x4008cbfc <rtc_pads_funie>
   0x4008b874 <adc1_pad_init+40>:	mov.n	a10, a3
   0x4008b876 <adc1_pad_init+42>:	movi.n	a11, 0
   0x4008b878 <adc1_pad_init+44>:	call8	0x4008ca74 <rtc_pads_slpie>
   0x4008b87b <adc1_pad_init+47>:	mov.n	a10, a3
   0x4008b87d <adc1_pad_init+49>:	movi.n	a11, 0
   0x4008b87f <adc1_pad_init+51>:	call8	0x4008c8e8 <rtc_pads_slpoe>
   0x4008b882 <adc1_pad_init+54>:	retw.n

   0x4008b884 <adc1_read>:	entry	a1, 32
   0x4008b887 <adc1_read+3>:	extui	a2, a2, 0, 8   <--- 1st parameter of adc1_read, pin used to measure the voltage
   0x4008b88a <adc1_read+6>:	or	a10, a2, a2
   0x4008b88d <adc1_read+9>:	call8	0x4008b84c <adc1_pad_init>
   0x4008b890 <adc1_read+12>:	extui	a3, a3, 0, 8
   0x4008b893 <adc1_read+15>:	mov.n	a10, a2        <--- 1st parameter of adc1_read, it's uint8_t
   0x4008b895 <adc1_read+17>:	mov.n	a11, a3        <--- 2nd parameter of adc1_read, it's uint8_t
   0x4008b897 <adc1_read+19>:	movi.n	a12, 2         <--- 3rd parameter of adc1_read_test, it's 2
   0x4008b899 <adc1_read+21>:	call8	0x4008b0b4 <adc1_read_test>
   0x4008b89c <adc1_read+24>:	mov.n	a2, a10
   0x4008b89e <adc1_read+26>:	retw.n

   0x4008b8a0 <adc1_amp_read>:	entry	a1, 32
   0x4008b8a3 <adc1_amp_read+3>:	movi.n	a10, 0
   0x4008b8a5 <adc1_amp_read+5>:	call8	0x4008b84c <adc1_pad_init>
   0x4008b8a8 <adc1_amp_read+8>:	movi.n	a10, 0
   0x4008b8aa <adc1_amp_read+10>:	mov.n	a11, a10
   0x4008b8ac <adc1_amp_read+12>:	movi	a12, 0x400
   0x4008b8af <adc1_amp_read+15>:	movi.n	a13, 1
   0x4008b8b1 <adc1_amp_read+17>:	movi.n	a14, 4
   0x4008b8b3 <adc1_amp_read+19>:	call8	0x4008b220 <adc1_amp_read_full>
   0x4008b8b6 <adc1_amp_read+22>:	mov.n	a2, a10
   0x4008b8b8 <adc1_amp_read+24>:	retw.n


ADC2:

   0x4008b888 <adc2_pad_init>:	entry	a1, 32
   0x4008b88b <adc2_pad_init+3>:	extui	a2, a2, 0, 8
   0x4008b88e <adc2_pad_init+6>:	movi.n	a8, 9
   0x4008b890 <adc2_pad_init+8>:	movi.n	a3, 0
   0x4008b892 <adc2_pad_init+10>:	bltu	a8, a2, 0x4008b89d <adc2_pad_init+21>
   0x4008b895 <adc2_pad_init+13>:	l32r	a3, 0x4008b884
   0x4008b898 <adc2_pad_init+16>:	addx4	a2, a2, a3
   0x4008b89b <adc2_pad_init+19>:	l32i.n	a3, a2, 0
   0x4008b89d <adc2_pad_init+21>:	mov.n	a10, a3
   0x4008b89f <adc2_pad_init+23>:	movi.n	a11, 0
   0x4008b8a1 <adc2_pad_init+25>:	call8	0x4008cd38 <rtc_pads_pu>
   0x4008b8a4 <adc2_pad_init+28>:	mov.n	a10, a3
   0x4008b8a6 <adc2_pad_init+30>:	movi.n	a11, 0
   0x4008b8a8 <adc2_pad_init+32>:	call8	0x4008cec0 <rtc_pads_pd>
   0x4008b8ab <adc2_pad_init+35>:	mov.n	a10, a3
   0x4008b8ad <adc2_pad_init+37>:	movi.n	a11, 0
   0x4008b8af <adc2_pad_init+39>:	call8	0x4008cbb0 <rtc_pads_funie>
   0x4008b8b2 <adc2_pad_init+42>:	mov.n	a10, a3
   0x4008b8b4 <adc2_pad_init+44>:	movi.n	a11, 0
   0x4008b8b6 <adc2_pad_init+46>:	call8	0x4008ca28 <rtc_pads_slpie>
   0x4008b8b9 <adc2_pad_init+49>:	mov.n	a10, a3
   0x4008b8bb <adc2_pad_init+51>:	movi.n	a11, 0
   0x4008b8bd <adc2_pad_init+53>:	call8	0x4008c89c <rtc_pads_slpoe>
   0x4008b8c0 <adc2_pad_init+56>:	retw.n

   0x4008b8c4 <adc2_read>:	entry	a1, 32
   0x4008b8c7 <adc2_read+3>:	extui	a2, a2, 0, 8
   0x4008b8ca <adc2_read+6>:	or	a10, a2, a2
   0x4008b8cd <adc2_read+9>:	call8	0x4008b888 <adc2_pad_init>
   0x4008b8d0 <adc2_read+12>:	extui	a3, a3, 0, 8
   0x4008b8d3 <adc2_read+15>:	mov.n	a10, a2
   0x4008b8d5 <adc2_read+17>:	mov.n	a11, a3
   0x4008b8d7 <adc2_read+19>:	call8	0x4008b4b0 <adc2_read_test>
   0x4008b8da <adc2_read+22>:	mov.n	a2, a10
   0x4008b8dc <adc2_read+24>:	retw.n



4.2 ADC Registers

In components/esp32/include/soc/saradc_reg.h

#define DR_REG_SARADC_BASE                      0x3ff48800

#define SARADC_SAR_READ_STATUS1_REG          (DR_REG_SARADC_BASE + 0x0004)
/* SARADC_SAR1_READER_STATUS : RO ;bitpos:[31:0] ;default: 32'h0 ; */
#define SARADC_SAR_MEAS_WAIT1_REG          (DR_REG_SARADC_BASE + 0x0008)
/* SARADC_SAR_AMP_WAIT2 : R/W ;bitpos:[31:16] ;default: 16'd10 ; */
#define SARADC_SAR_MEAS_WAIT2_REG          (DR_REG_SARADC_BASE + 0x000c)
/* SARADC_SAR2_RSTB_WAIT : R/W ;bitpos:[27:20] ;default: 8'd2 ; */
#define SARADC_SAR_MEAS_CTRL_REG          (DR_REG_SARADC_BASE + 0x0010)
/* SARADC_SAR2_XPD_WAIT : R/W ;bitpos:[31:24] ;default: 8'h7 ; */
#define SARADC_SAR_READ_STATUS2_REG          (DR_REG_SARADC_BASE + 0x0014)
/* SARADC_SAR2_READER_STATUS : RO ;bitpos:[31:0] ;default: 32'h0 ; */
#define SARADC_ULP_CP_SLEEP_CYC1_REG          (DR_REG_SARADC_BASE + 0x001c)
/* SARADC_SLEEP_CYCLES_S1 : R/W ;bitpos:[31:0] ;default: 32'd100 ; */
#define SARADC_ULP_CP_SLEEP_CYC2_REG          (DR_REG_SARADC_BASE + 0x0020)
/* SARADC_SLEEP_CYCLES_S2 : R/W ;bitpos:[31:0] ;default: 32'd50 ; */
#define SARADC_ULP_CP_SLEEP_CYC3_REG          (DR_REG_SARADC_BASE + 0x0024)
/* SARADC_SLEEP_CYCLES_S3 : R/W ;bitpos:[31:0] ;default: 32'd40 ; */
#define SARADC_ULP_CP_SLEEP_CYC4_REG          (DR_REG_SARADC_BASE + 0x0028)
/* SARADC_SLEEP_CYCLES_S4 : R/W ;bitpos:[31:0] ;default: 32'd20 ; */
#define SARADC_SAR_START_FORCE_REG          (DR_REG_SARADC_BASE + 0x002c)
/* SARADC_SAR2_PWDET_EN : R/W ;bitpos:[24] ;default: 1'b0 ; */
#define SARADC_SAR_MEM_WR_CTRL_REG          (DR_REG_SARADC_BASE + 0x0030)
/* SARADC_RTC_MEM_WR_OFFST_CLR : WO ;bitpos:[22] ;default: 1'd0 ; */

#define SARADC_SAR_ATTEN1_REG          (DR_REG_SARADC_BASE + 0x0034)
/* SARADC_SAR1_ATTEN : R/W ;bitpos:[31:0] ;default: 32'hffffffff ; */
/*description: 2-bit attenuation for each pad  11:1dB  10:6dB  01:3dB  00:0dB*/

#define SARADC_SAR_ATTEN2_REG          (DR_REG_SARADC_BASE + 0x0038)
/* SARADC_SAR2_ATTEN : R/W ;bitpos:[31:0] ;default: 32'hffffffff ; */
/*description: 2-bit attenuation for each pad  11:1dB  10:6dB  01:3dB  00:0dB*/

#define SARADC_SAR_SLAVE_ADDR1_REG          (DR_REG_SARADC_BASE + 0x003c)
/* SARADC_MEAS_STATUS : RO ;bitpos:[29:22] ;default: 8'h0 ; */

#define SARADC_SAR_SLAVE_ADDR2_REG          (DR_REG_SARADC_BASE + 0x0040)
/* SARADC_I2C_SLAVE_ADDR2 : R/W ;bitpos:[21:11] ;default: 11'h0 ; */

#define SARADC_SAR_SLAVE_ADDR3_REG          (DR_REG_SARADC_BASE + 0x0044)
/* SARADC_TSENS_RDY_OUT : RO ;bitpos:[30] ;default: 1'h0 ; */

#define SARADC_SAR_SLAVE_ADDR4_REG          (DR_REG_SARADC_BASE + 0x0048)
/* SARADC_I2C_DONE : RO ;bitpos:[30] ;default: 1'h0 ; */
/*description: indicate I2C done*/

#define SARADC_SAR_TSENS_CTRL_REG          (DR_REG_SARADC_BASE + 0x004c)
/* SARADC_TSENS_DUMP_OUT : R/W ;bitpos:[26] ;default: 1'b0 ; */
/*description: temperature sensor dump out  only active when reg_tsens_power_up_force = 1*/

/*description: indicate temperature sensor out ready*/

#define SARADC_SAR_TOUCH_CTRL1_REG          (DR_REG_SARADC_BASE + 0x0058)
/* SARADC_HALL_PHASE_FORCE : R/W ;bitpos:[27] ;default: 1'b0 ; */
/*description: 1: HALL PHASE is controlled by SW  0: HALL PHASE is controlled
 by FSM in ULP-coprocessor*/



4.3 Study

static esp_err_t adc1_pad_init(adc1_channel_t channel)
{
    gpio_num_t gpio_num = 0;
    adc1_pad_get_io_num(channel, &gpio_num);
    rtc_gpio_init(gpio_num);
    rtc_gpio_output_disable(gpio_num);
    rtc_gpio_input_disable(gpio_num);
    gpio_set_pull_mode(gpio_num, GPIO_FLOATING);

    return ESP_OK;
}

esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
{
    RTC_MODULE_CHECK(channel < ADC1_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
    RTC_MODULE_CHECK(atten <= ADC_ATTEN_11db, "ADC Atten Err", ESP_ERR_INVALID_ARG);

    adc1_pad_init(channel);

    portENTER_CRITICAL(&rtc_spinlock);
    SET_PERI_REG_BITS(SENS_SAR_ATTEN1_REG, 3, atten, (channel * 2)); //SAR1_atten
    portEXIT_CRITICAL(&rtc_spinlock);

    return ESP_OK;
}

esp_err_t adc1_config_width(adc_bits_width_t width_bit)
{
    portENTER_CRITICAL(&rtc_spinlock);

    //SAR2_BIT_WIDTH[1:0]=0x3, SAR1_BIT_WIDTH[1:0]=0x3
    SET_PERI_REG_BITS(SENS_SAR_START_FORCE_REG, SENS_SAR1_BIT_WIDTH_V, width_bit, SENS_SAR1_BIT_WIDTH_S);

    //Invert the adc value,the Output value is invert
    SET_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DATA_INV);

    //Set The adc sample width,invert adc value,must
    //digital sar1_bit_width[1:0]=3
    SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_SAMPLE_BIT_V, width_bit, SENS_SAR1_SAMPLE_BIT_S);

    portEXIT_CRITICAL(&rtc_spinlock);

    return ESP_OK;
}

int adc1_get_voltage(adc1_channel_t channel)
{
    uint16_t adc_value;

    RTC_MODULE_CHECK(channel < ADC1_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
    portENTER_CRITICAL(&rtc_spinlock);

    //Adc Controler is Rtc module,not ulp coprocessor
    SET_PERI_REG_BITS(SENS_SAR_MEAS_START1_REG, 1, 1, SENS_MEAS1_START_FORCE_S); //force pad mux and force start
    //Bit1=0:Fsm  Bit1=1(Bit0=0:PownDown Bit10=1:Powerup)
    SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S); //force XPD_SAR=0, use XPD_FSM
    //Disable Amp Bit1=0:Fsm  Bit1=1(Bit0=0:PownDown Bit10=1:Powerup)
    SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_AMP, 0x2, SENS_FORCE_XPD_AMP_S); //force XPD_AMP=0
    //Open the ADC1 Data port Not ulp coprocessor
    SET_PERI_REG_BITS(SENS_SAR_MEAS_START1_REG, 1, 1, SENS_SAR1_EN_PAD_FORCE_S); //open the ADC1 data port
    //Select channel
    SET_PERI_REG_BITS(SENS_SAR_MEAS_START1_REG, SENS_SAR1_EN_PAD, (1 << channel), SENS_SAR1_EN_PAD_S); //pad enable
    SET_PERI_REG_BITS(SENS_SAR_MEAS_CTRL_REG, 0xfff, 0x0, SENS_AMP_RST_FB_FSM_S);  //[11:8]:short ref ground, [7:4]:short ref, [3:0]:rst fb
    SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT1_REG, SENS_SAR_AMP_WAIT1, 0x1, SENS_SAR_AMP_WAIT1_S);
    SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT1_REG, SENS_SAR_AMP_WAIT2, 0x1, SENS_SAR_AMP_WAIT2_S);
    SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_SAR_AMP_WAIT3, 0x1, SENS_SAR_AMP_WAIT3_S);
    while (GET_PERI_REG_BITS2(SENS_SAR_SLAVE_ADDR1_REG, 0x7, SENS_MEAS_STATUS_S) != 0); //wait det_fsm==0
    SET_PERI_REG_BITS(SENS_SAR_MEAS_START1_REG, 1, 0, SENS_MEAS1_START_SAR_S); //start force 0
    SET_PERI_REG_BITS(SENS_SAR_MEAS_START1_REG, 1, 1, SENS_MEAS1_START_SAR_S); //start force 1
    while (GET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DONE_SAR) == 0) {}; //read done
    adc_value = GET_PERI_REG_BITS2(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DATA_SAR, SENS_MEAS1_DATA_SAR_S);
    portEXIT_CRITICAL(&rtc_spinlock);

    return adc_value;
}


gpio_num_t adc2ch2gpionum[10] = {4, 0, 2, 15, 13, 12, 14, 27, 25, 26};

portMUX_TYPE adc_spinlock = portMUX_INITIALIZER_UNLOCKED;

esp_err_t rtc_gpio_output_disable(gpio_num_t gpio_num);
esp_err_t rtc_gpio_input_disable(gpio_num_t gpio_num);

static esp_err_t adc2_pad_init(adc2_channel_t channel)
{
    //adc2_pad_get_io_num(channel, &gpio_num);
    gpio_num_t gpio_num = adc2ch2gpionum[channel];

    rtc_gpio_init(gpio_num);

    REG_CLR_BIT(RTC_IO_TOUCH_PAD0_REG, RTC_IO_TOUCH_PAD0_TO_GPIO);
    REG_SET_BIT(RTC_IO_TOUCH_PAD0_REG, RTC_IO_TOUCH_PAD0_MUX_SEL);
    REG_CLR_BIT(RTC_IO_TOUCH_PAD0_REG, RTC_IO_TOUCH_PAD0_FUN_SEL);

    rtc_gpio_output_disable(gpio_num);
    rtc_gpio_input_disable(gpio_num);
    gpio_set_pull_mode(gpio_num, GPIO_FLOATING);

    return ESP_OK;
}

esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
{
    adc2_pad_init(channel);

    portENTER_CRITICAL(&adc_spinlock);

    //SAR2_atten
    SET_PERI_REG_BITS(SENS_SAR_ATTEN2_REG, 3, atten, (channel * 2));

    portEXIT_CRITICAL(&adc_spinlock);
    return ESP_OK;
}

esp_err_t adc2_config_width(adc_bits_width_t width_bit)
{
    portENTER_CRITICAL(&adc_spinlock);

    //SAR2_BIT_WIDTH[1:0]=0x3, SAR1_BIT_WIDTH[1:0]=0x3
    SET_PERI_REG_BITS(SENS_SAR_START_FORCE_REG, SENS_SAR2_BIT_WIDTH_V, width_bit, SENS_SAR2_BIT_WIDTH_S);

    //Invert the adc value,the Output value is invert
    SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DATA_INV);

    //Set The adc sample width,invert adc value,must
    //digital sar2_bit_width[1:0]=3
    SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_SAMPLE_BIT_V, width_bit, SENS_SAR2_SAMPLE_BIT_S);

    portEXIT_CRITICAL(&adc_spinlock);

    return ESP_OK;
}

int adc2_get_voltage(adc2_channel_t channel)
{
    uint16_t adc_value;

    portENTER_CRITICAL(&adc_spinlock);

    //Adc Controler is Rtc module,not ulp coprocessor
    SET_PERI_REG_BITS(SENS_SAR_MEAS_START2_REG, 1, 1, SENS_MEAS2_START_FORCE_S); //force pad mux and force start

    //Bit1=0:Fsm  Bit1=1(Bit0=0:PownDown Bit10=1:Powerup)
    SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S); //force XPD_SAR=0, use XPD_FSM

    //Disable Amp Bit1=0:Fsm  Bit1=1(Bit0=0:PownDown Bit10=1:Powerup)
    SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_AMP, 0x2, SENS_FORCE_XPD_AMP_S); //force XPD_AMP=0

    //Open the ADC2 Data port Not ulp coprocessor
    SET_PERI_REG_BITS(SENS_SAR_MEAS_START2_REG, 1, 1, SENS_SAR2_EN_PAD_FORCE_S); //open the ADC2 data port

    //Select channel
    SET_PERI_REG_BITS(SENS_SAR_MEAS_START2_REG, SENS_SAR2_EN_PAD, (1 << channel), SENS_SAR2_EN_PAD_S); //pad enable
    
    //[11:8]:short ref ground, [7:4]:short ref, [3:0]:rst fb
    SET_PERI_REG_BITS(SENS_SAR_MEAS_CTRL_REG, 0xfff, 0x0, SENS_AMP_RST_FB_FSM_S);
    
    SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT1_REG, SENS_SAR_AMP_WAIT1, 0x1, SENS_SAR_AMP_WAIT1_S);
    SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT1_REG, SENS_SAR_AMP_WAIT2, 0x1, SENS_SAR_AMP_WAIT2_S);
    SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_SAR_AMP_WAIT3, 0x1, SENS_SAR_AMP_WAIT3_S);

    while (GET_PERI_REG_BITS2(SENS_SAR_SLAVE_ADDR1_REG, 0x7, SENS_MEAS_STATUS_S) != 0); //wait det_fsm==0

    SET_PERI_REG_BITS(SENS_SAR_MEAS_START2_REG, 1, 0, SENS_MEAS2_START_SAR_S); //start force 0
    SET_PERI_REG_BITS(SENS_SAR_MEAS_START2_REG, 1, 1, SENS_MEAS2_START_SAR_S); //start force 1

    while (GET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DONE_SAR) == 0) {}; //read done

    adc_value = GET_PERI_REG_BITS2(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DATA_SAR, SENS_MEAS2_DATA_SAR_S);

    portEXIT_CRITICAL(&adc_spinlock);

    return adc_value;
}



5 Reference

For more information please refer to





























个人工具
名字空间

变换
操作
导航
工具箱