【问题标题】:ESP8266 GPIO expander missing interruptsESP8266 GPIO 扩展器缺少中断
【发布时间】:2018-10-26 18:30:18
【问题描述】:

我有一个程序可以让 LED 发出脉冲。我还用一个按钮连接了 PC8574 GPIO 扩展器。我想评估按键。但是,我只能在程序处于使 LED 变亮和再次变暗之间(在两个 for 循环之间)时读取 INT(中断)的状态

我知道问题在于 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...
}

【问题讨论】:

  • 你根本不使用任何中断。您正在 for 循环之间轮询输入。

标签: arduino interrupt gpio nodemcu arduino-esp8266


【解决方案1】:

您可以通过 Arduino 的 attachInterrupt() 函数将 PCF8574 INT 引脚用作 ESP8266 的中断,但您不会从中获得太多收益,因为要检测按下了哪个键,您需要调用 pcf8574.read8(),你不能从中断处理程序中做到这一点。 ESP8266 Arduino 内核基于 Espressif NONOS SDK,因此您不能有单独的线程来监控按键。我建议定义一个辅助函数来检查当前是否正在按下某个键,然后在主循环中尽可能频繁地调用该函数,例如在你的两个 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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-07
    • 2017-01-05
    • 2010-11-13
    • 2013-05-21
    • 1970-01-01
    • 1970-01-01
    • 2015-05-16
    • 2018-05-10
    相关资源
    最近更新 更多