• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Сброс флага прерывания ESP8266

ptihka

New member
Всем привет! Подскажите пожалуйста как сбросить флаг прерывания ESP в ардуино. Есть команды из даташит на ESP8266 , но они мне всегда возвращают "НОЛЬ" не зависимо какие прерывания включены или какие флаги подняты, может я что то делаю не так , или есть какието другие варианты?
uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_W1TC_ADDRESS);
Serial.print ("gpio_status -");
Serial.println (gpio_status);
 

aZholtikov

Active member
Всем привет! Подскажите пожалуйста как сбросить флаг прерывания ESP в ардуино.
Если я правильно помню, то последовательность такая:

ETS_GPIO_INTR_DISABLE();
uint32_t gpioStatus = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpioStatus);
ETS_GPIO_INTR_ENABLE();
 

aZholtikov

Active member
В дополнение.

 

ptihka

New member
не помогает , выполнении команды , так же "gpioStatus = 0" это первое , а второе я так понимаю Вы скинули пример не со среды ARDUINO , это наверно эклипс , я с ним не работал , надо попробовать разобраться , может там работать будет , но хотелось бы и в ардуино разобраться.
ETS_GPIO_INTR_DISABLE(); ----- это я как понял отключение прерывания , оно не должно повлиять на чтение регистра состояния , или я не прав?
uint32_t gpioStatus = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
ETS_GPIO_INTR_ENABLE();
 

aZholtikov

Active member
не помогает , выполнении команды , так же "gpioStatus = 0" это первое , а второе я так понимаю Вы скинули пример не со среды ARDUINO , это наверно эклипс , я с ним не работал , надо попробовать разобраться , может там работать будет , но хотелось бы и в ардуино разобраться.
ETS_GPIO_INTR_DISABLE(); ----- это я как понял отключение прерывания , оно не должно повлиять на чтение регистра состояния , или я не прав?
uint32_t gpioStatus = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
ETS_GPIO_INTR_ENABLE();
Да. Это не Ардуино. Это "голый" SDK Espressif.
Вы сами дали такой пример. Я ответил.
Нужно Ардуино - используйте функции Ардуино. Типа attachInterrupt(interrupt, function, mode) и тд... https://esp8266-arduinoide.ru/prog/
 

ptihka

New member
Так проблемма в том что я в ардуино не могу считать регистр прерывания, именно считать регист и соответственно обнулить его , в этом и суть вопроса , а пример кода это то как я пробовал считать , и оно не получается , вот и задал вопрос про чтение регистров в ардуино среде.
 

aZholtikov

Active member
Можно увидеть полный код обработчика прерывания, в котором осуществляется попытка чтения регистра?
 

ptihka

New member
Конечно можно.

Код:
#include <Wire.h>
#include <SparkFun_APDS9960.h>

#define LED_1 D0   // пин выхода 1
#define LED_2 D6   // пин выхода 2
#define INT_a D2   // пин преывания

SparkFun_APDS9960 apds = SparkFun_APDS9960();
uint8_t PROX_INT_HIGH = 200;  // верхний предел для прерывания датчика
uint8_t PROX_INT_LOW  = 100;  // нижний предел для прерывания датчика
int a = 0;
//uint32_t gpio_status=0;

uint8_t proximity_data = 0;   // переменная данных датчика

volatile int flag_int = 0;    // флаг прерывания

void setup() {
  Wire.begin(D5, D7);         // назначение ножек I2C
  Serial.begin(9600);         // скорость порта UART
  attachInterrupt(INT_a, myIsr, FALLING);  // функыия прерывания

  apds.init() ;               //иниыиализация датчика

  apds.setProximityIntLowThreshold(PROX_INT_LOW);   //установка предела сробатывания прерывания для датчика
  apds.setProximityIntHighThreshold(PROX_INT_HIGH);

    apds.enableProximitySensor(true);               // включение режима датчика для считывания преблеждения с включенным прерыванием

    apds.setProximityGain(PGAIN_2X);                // установка режимов чуствительности датчиков
    apds.setLEDDrive(3);

    pinMode(LED_1, OUTPUT);          //настройка портов для светодиодов
    digitalWrite(LED_1, 0);

    pinMode(LED_2, OUTPUT);
    digitalWrite(LED_2, 0);

}

void loop() {
     //ETS_GPIO_INTR_DISABLE();
  uint32 gpio_status = GPIO_REG_READ(GPIO_OUT_W1TC_ADDRESS);
     //gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
     //gpio_status = GPIO_REG_READ(GPIO_STATUS_W1TC_ADDRESS);
  Serial.print ("gpio_status - ");
  Serial.println (gpio_status);
      //ETS_GPIO_INTR_ENABLE();

if (flag_int == 1){ 
  //detachInterrupt(INT_a);
  apds.readProximity(proximity_data);
  Serial.println(proximity_data);
   flag_int = 0;
  apds.clearProximityInt(); 
//attachInterrupt(INT_a, myIsr, FALLING);
 
}
  delay(250);
 
}

IRAM_ATTR void myIsr() { 
 
  flag_int = 1;
  if (a == 0 ){
    digitalWrite(LED_2, a);
    a++;
  }
    else    {
  digitalWrite(LED_2, a);
  a=0;
    }
}
 

aZholtikov

Active member
Зачем пытаться прочитать статус регистра если прерывание всего одно? Тем более +100500 раз в секунду в loop?
P.S. Ардуиновская attachInterrupt сама очищает регистр при возникновении прерывания. Вот и 0 всегда.
P.S.S. Не мешайте Ардуино и родное SDK. Или-или.
 

ptihka

New member
Это не тот код который мне нужен , это проверочный , дело в том что "gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);" которая должно выводить какой порт включен на прерывание выводит тоже ноль , не зависимо сколько и какие прерывания включены.
P.S. Ардуиновская attachInterrupt сама очищает регистр при возникновении прерывания. Вот и 0 всегда.
она очищает не в тот момент который мне нужен , она очищает после своего выполнения , а мне нужно чтобы я флаг очистил и прерывания не вполнилось. перед включение прерывания, после его отключения.
P.S.S. Не мешайте Ардуино и родное SDK. Или-или.
да я бы не против , знал бы как обратится к регистрам при помощи ардуино , в чем и суть.
Опишу в кратце что мне нужно , может в этом подскажите. Есть датчик APDS-9960 и всего две ноги D5 & D7 || SDA & SCL соответственно , я хочу чтобы на ноге D5 висело еще и прерывание от это го же датчика.
Мои действия : отключаю прерывания , инициализирую датчик , включаю прерывания , жду пока прийдет прерывания от APDS-9960 , отключаю прерывания , обрабатываю данные по I2C , включаю прерывания и жду его от датчика и так по кругу . Загвоздка в том что после отключения прерывания и обработки I2C прерывания опять срабатывает , я так понимаю что флаг прерывания в регистре поднят и мне его нужно обнулить.
 

aZholtikov

Active member
Есть датчик APDS-9960 и всего две ноги D5 & D7 || SDA & SCL соответственно , я хочу чтобы на ноге D5 висело еще и прерывание от это го же датчика.
Боюсь это невозможно... ;-(
P.S. Что за модуль ESP с таким маленьким количеством свободных "ног"?
 

ptihka

New member
Боюсь это невозможно... ;-(
с чем это связанно?
P.S. Что за модуль ESP с таким маленьким количеством свободных "ног"?
модуль тут совсем не причем . это все строение платы , модуль esp-12s , ног то занятых совсем нет кроме SDA & SCl , но нет возможность подвести других проводов к датчику.
 

ptihka

New member
Ну в Баском у меня бы получилось , но там нет поддержки ESP , я думаю и здесь должно работать , просто я с С-языком почти не знаком , а с ардуино знаком еще меньше .
Но обстоятельства заставляют изучат и то и другое :)
 

ptihka

New member
Не ужели никто не знает как прочитать или записать непосредственно регистры ESP8266 в Arduino IDE?
 

aZholtikov

Active member
Офф документация Espressif:

7.1.6. GPIO Interrupt Handler
Follow the steps below to clear interrupt status in GPIO interrupt processing function:

uint32 gpio_status;
gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
//clear interrupt status
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status);

Больше ничего нет. Это и чтение и обнуление. И в Arduino IDE тоже.

P.S. Следим "за руками", а точнее за названием параграфа - Interrupt Handler. Это как бы намекает на то, что данные манипуляции можно (и нужно) производить ТОЛЬКО в обработчике прерывания.
 

ptihka

New member
Ну это понятно , в моем первом сообщении я так и писал теже самые команды , так делао в том что я не могу прочитать не один регистр , и даже регистр в котором указанно какие прерывания обработать а тоесть (GPIO_STATUS_ADDRESS ) , aZholtikov сами попробуйте считать хоть какой нибудь регистр , может у Вас получится. Может я что делаю не так.
 

aZholtikov

Active member
Код:
#include "Arduino.h"
#include "gpio.h"

volatile static uint32_t register_status = 0;
volatile static bool interrupt_flag = false;

void button_interrupt();

void setup()
{
  Serial.begin(115200);

  ETS_GPIO_INTR_DISABLE();
  ETS_GPIO_INTR_ATTACH(button_interrupt, NULL);
  gpio_pin_intr_state_set(GPIO_ID_PIN(5), GPIO_PIN_INTR_POSEDGE);
  gpio_pin_intr_state_set(GPIO_ID_PIN(6), GPIO_PIN_INTR_POSEDGE);
  gpio_pin_intr_state_set(GPIO_ID_PIN(7), GPIO_PIN_INTR_POSEDGE);
  ETS_GPIO_INTR_ENABLE();
}

void loop()
{
  if (interrupt_flag == true)
  {
    Serial.print("GPIO Register: ");
    Serial.println(register_status, BIN);
    interrupt_flag = false;
    delay(500); // Just for minimise printing frequency.
    ETS_GPIO_INTR_ENABLE();
  }
}

void IRAM_ATTR button_interrupt()
{
  if (interrupt_flag == false)
  {
    ETS_GPIO_INTR_DISABLE();
    uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
    register_status = gpio_status;
    GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status);
    interrupt_flag = true;
  }
}
 

ptihka

New member
Спасибо за пример , вроде что то работает , но я не могу понять логики . почему эта строка uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS); начинает работа только после прерывания я так понимаю это регистр в котором сказано какой порт включен для прерывания , а значит он должен читаться в любой момент , или я опять не так что то думаю?
 

aZholtikov

Active member
Буду краток. Не правильно понимаете.

Это регистр флагов. Наличие установленного бита на определенной позиции только показывает какая «ножка» вызвала прерывание. И его надо сразу обнулять для продолжения работы прерываний. Фсё.

Все регистры очень подробно описаны в ESP8266 Technical Reference.
 
Сверху Снизу