首页 文章

ESP8266 GPIO扩展器丢失中断

提问于
浏览
0

我有一个程序,让LED脉冲 . 我还用一个按钮连接PC8574 GPIO扩展器 . 我想评估按键 . 但是,我只能读取INT(中断)的状态,同时程序处于使LED更亮并再次变暗(两个for循环之间)之间的部分

我知道问题是for循环的延迟,但我不知道如何避免这种情况 .

是否可以更频繁地评估中断相关代码或者像真正的中断一样 - 总是在按下实际键时?如果是这样,怎么样?

我用这个库:https://github.com/WereCatf/PCF8574_ESP

/*LED_Breathing.ino Arduining.com  20 AUG 2015
Using NodeMCU Development Kit V1.0
Going beyond Blink sketch to see the blue LED breathing.
A PWM modulation is made in software because GPIO16 can't
be used with analogWrite().
*/

#include <pcf8574_esp.h>
#include <Wire.h>
TwoWire testWire;
// Initialize a PCF8574 at I2C-address 0x20, using GPIO5, GPIO4 and testWire for the I2C-bus
PCF857x pcf8574(0x20, &testWire);

#define LED     D1        // Led in NodeMCU at pin GPIO16 (D0).

#define BRIGHT    300     //max led intensity (1-500)
#define INHALE    1250    //Inhalation time in milliseconds.
#define PULSE     INHALE*1000/BRIGHT
#define REST      1000    //Rest Between Inhalations.

#define PIN_INT D5
#define PIN_SDA D7
#define PIN_SCL D8

//----- Setup function. ------------------------
void setup() {                
  Serial.begin(115200);
  Wire.pins(PIN_SDA, PIN_SCL);//SDA - D1, SCL - D2
  Wire.begin();

  pinMode(PIN_INT, INPUT_PULLUP);

  pcf8574.begin( 0xFF); 
  pcf8574.resetInterruptPin();
  pinMode(LED, OUTPUT);   // LED pin as output.    
}


bool CheckKey(byte key, byte num){ //0, 1, 2, 3
  return key & (1 << num);
}

//----- Loop routine. --------------------------
void loop() {
  //ramp increasing intensity, Inhalation: 
  for (int i=1;i<BRIGHT;i++){
    digitalWrite(LED, LOW);          // turn the LED on.
    delayMicroseconds(i*10);         // wait
    digitalWrite(LED, HIGH);         // turn the LED off.
    delayMicroseconds(PULSE-i*10);   // wait
    delay(0);                        //to prevent watchdog firing.
  }


  if( digitalRead(PIN_INT)==LOW ){
    delay(50);
    byte b = pcf8574.read8();
    Serial.println( "INT: " + String(b));

    byte keys = ((~b)) & 0x0F;

    if( CheckKey(keys, 8) ){
      Serial.println( "KEY 7");
      delay(2000);
    }
  }

  //ramp decreasing intensity, Exhalation (half time):
  for (int i=BRIGHT-1;i>0;i--){
    digitalWrite(LED, LOW);          // turn the LED on.
    delayMicroseconds(i*10);          // wait
    digitalWrite(LED, HIGH);         // turn the LED off.
    delayMicroseconds(PULSE-i*10);  // wait
    i--;
    delay(0);                        //to prevent watchdog firing.
  }
  delay(REST);                       //take a rest...
}

1 回答

  • 1

    您可以通过Arduino的 attachInterrupt() 函数将PCF8574 INT引脚用作ESP8266的中断,但是您不会从中获得太多收益,因为为了检测按下了哪个键,您需要调用 pcf8574.read8() ,并且您可以't do that from the interrupt handler. The ESP8266 Arduino core is based on the Espressif NONOS SDK, so you can' t单独的线程来监控按键 . 我建议定义一个辅助函数来检查当前是否正在按下某个键,然后在主循环中尽可能多地调用该函数,例如:在你的两个for循环中的每一个的每次迭代 . 当按键时,LED亮度斜坡会略微中断,但我认为人眼不会注意到它 .

    所以辅助函数可以定义为:

    byte GetKeyPress(void) {
      if (digitalRead(PIN_INT) == LOW) {
        return ~pcf8574.read8();
      }
      else {
        return 0;
      }
    }
    

    然后,在 loop() 函数的开头声明一个静态变量 static byte keyPress; ,并在两个for循环中的每一个中调用上面的函数:

    if (keyPress == 0) {
      keyPress = GetKeyPress();
    }
    

    当你想要处理按键时(例如在代码中的两个for循环之间),你可以这样做:

    if (keyPress) {
      /* Do your stuff. */
      keyPress = 0;
    }
    

相关问题