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
Code: Untitled.cpp Select all
#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.