am new to the esp32. At first glance i though that 240mhz can get me really accurate delays, but turns out it uses 80mhz timer clock, and i have to use divider = 2 so it is 40mhz at the end(25ns each clock), and i cant make my code work.
I have a esp-wroom-32 module(esp32 dev module) and use arduino IDE, my task is to generate 2 pulses on different pins with as much accuracy as possible:
1) make GPIO_NUM_2 and GPIO_NUM_4 go HIGH
2)Generate single shot pulses on a button press with predefined delay:
2.1) Generate negative pulse ~100nS on pin 2 (after that pulse pin2 stays HIGH)
2.2) Wait certain amount of uS: from 3uS to 35uS with precise accuracy.(30nS or less each step i want to increase or decrease delay)
(like to
2.3)Generate another ~100nS pulse on pin4 (after that pulse pin4 stays HIGH)
Currently i came up with the following test code using a timer, but for some reason it does not works as i want:
1)it does not increment delay by 25ns each time (but it starts to work a little better at 22uS or more)
2) minimum delay is ~6.6us, after a while it jumps to 7.7 etc
- #include "driver/timer.h"
- int i = 0; // value added to match each loop
- static bool IRAM_ATTR onTimer(void *args) //ISR function
- {
- //2nd signal pulse
- REG_WRITE(GPIO_OUT_W1TC_REG, BIT4); //GPIO4 LOW(CLEAR)
- __asm__ __volatile__ (
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- );
- REG_WRITE(GPIO_OUT_W1TS_REG, BIT4); //GPIO4 HIGH (SET) !!!!!!!!!!!!!!
- timer_pause(TIMER_GROUP_0, TIMER_0);
- return false;
- }
- void setup() {
- ////TIMERS SETUP////
- timer_config_t config = {
- .alarm_en = TIMER_ALARM_EN, //ISR on
- .counter_en = TIMER_PAUSE, //timer off after init
- //.intr_type = TIMER_INTR_LEVEL, //can be ignored
- .counter_dir = TIMER_COUNT_UP, //up
- .auto_reload = TIMER_AUTORELOAD_EN, /hardware will load counter value after an alarm event;
- .divider = 2, //from 2 to 65536 if 2 = 40mhz =25ns
- }; //default clock source is APB (80mhz)
- timer_init(TIMER_GROUP_0, TIMER_0, &config); //init
- timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0); //start value
- timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 250); //match value
- timer_isr_callback_add(TIMER_GROUP_0, TIMER_0, onTimer, NULL, 0); // add isr func
- timer_enable_intr(TIMER_GROUP_0, TIMER_0); // enable isr
- ////PINS SETUP////
- //set it as gpio
- gpio_pad_select_gpio( GPIO_NUM_2);
- gpio_pad_select_gpio( GPIO_NUM_4);
- //output
- gpio_set_direction( GPIO_NUM_2, GPIO_MODE_OUTPUT);
- gpio_set_direction( GPIO_NUM_4, GPIO_MODE_OUTPUT);
- //pullup to 3.3
- gpio_set_pull_mode( GPIO_NUM_2, GPIO_PULLUP_ONLY);
- gpio_set_pull_mode( GPIO_NUM_4, GPIO_PULLUP_ONLY);
- //out current = 40ma
- gpio_set_drive_capability( GPIO_NUM_2, GPIO_DRIVE_CAP_3);
- gpio_set_drive_capability( GPIO_NUM_4, GPIO_DRIVE_CAP_3);
- //set as high
- gpio_set_level( GPIO_NUM_2, 1); //HIGH
- gpio_set_level( GPIO_NUM_4, 1); //HIGH
- }
- void loop() {
- delay(500);
- timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 100+i); //set new match value (100 should be ~2.5uS)
- timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0); //reset starting value to 0
- delay(50);
- //1st signal PULSE
- REG_WRITE(GPIO_OUT_W1TC_REG, BIT2); //GPIO2 LOW(CLEAR)
- __asm__ __volatile__ (
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- );
- REG_WRITE(GPIO_OUT_W1TS_REG, BIT2); //GPIO2 HIGH (SET)
- //start timer
- timer_start(TIMER_GROUP_0, TIMER_0);
- }
Maybe there is better peripheral to do that task?
There is so many ways it seems to do that task: with DMA, RTC, LED pwm, creating some assembly code(i am not familiar with it) that can utilize 240mhz so we can get 4.16ns step.
All those ways just overwhelms me.