ESP32 ADC
(→ADC Registers) |
(→Study) |
||
(未显示1个用户的6个中间版本) | |||
第359行: | 第359行: | ||
<br><br> | <br><br> | ||
− | === | + | === Study === |
<source lang=cpp> | <source lang=cpp> | ||
第365行: | 第365行: | ||
{ | { | ||
gpio_num_t gpio_num = 0; | 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; | return ESP_OK; | ||
第378行: | 第378行: | ||
RTC_MODULE_CHECK(channel < ADC1_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG); | 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); | RTC_MODULE_CHECK(atten <= ADC_ATTEN_11db, "ADC Atten Err", ESP_ERR_INVALID_ARG); | ||
+ | |||
adc1_pad_init(channel); | adc1_pad_init(channel); | ||
+ | |||
portENTER_CRITICAL(&rtc_spinlock); | portENTER_CRITICAL(&rtc_spinlock); | ||
SET_PERI_REG_BITS(SENS_SAR_ATTEN1_REG, 3, atten, (channel * 2)); //SAR1_atten | SET_PERI_REG_BITS(SENS_SAR_ATTEN1_REG, 3, atten, (channel * 2)); //SAR1_atten | ||
第389行: | 第391行: | ||
{ | { | ||
portENTER_CRITICAL(&rtc_spinlock); | 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 | //Invert the adc value,the Output value is invert | ||
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DATA_INV); | SET_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DATA_INV); | ||
+ | |||
//Set The adc sample width,invert adc value,must | //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); | portEXIT_CRITICAL(&rtc_spinlock); | ||
return ESP_OK; | 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; | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | |||
+ | <source lang=c> | ||
+ | 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; | ||
} | } | ||
</source> | </source> |
2016年12月15日 (四) 14:12的最后版本
目录 |
[编辑] 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:
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
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