Go Down

Topic: Tastendruckabfrage in der ISR an einem PCF8574 (Read 1 time) previous topic - next topic

TerraHoff


Hallo an Alle!!

Hallo Uwe!

Bin schon am verzweifeln,  ich bekomme es einfach nicht hin.

Ich habe den Code, jetzt so geschrieben, dass die Abfrage in der Interruptroutine stattfindet.
Der µC hängt sich wieder auf. Ich vermute es liegt an der Wire Bibliothek.

Gibt es nicht irgendeine andere möglichkeit?
Kann man nicht innerhalb der Interruptroutine ein Flag setzen und ausserhalb abfragen?

Gruß Sven

Code: [Select]
[

#define I2C_Adresse 0x20


#include <Wire.h>

byte tmp_data;
int i = 3;
byte current_data;
byte read_data;
volatile char Key = '\0';
int row_select= 0;
int c;

int interrupt0 = 0;  // Interrupt-Nummer (es gibt 2 Interrupts INT 0(PIN2) und INT 1(PIN3))

// Daten für jede Zeile der Tastatur vom PCF8574
const int pcf8574_row_data[4] =
{
  B01101111, B01011111, B00111111
};
const char KeyCode[4][5] =
{
  "026",
  "7S3",
  "48E",
  "159"
};

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

  Wire.begin();
 
  pinMode(PIN2, INPUT);
  digitalWrite(PIN2, HIGH);
 
  i2c_write(0x0F);
 
  attachInterrupt(interrupt0, interruptroutine, FALLING); //Der Interrupt-Modus steht jetzt auf RISING, was bedeutet,
                                                        // dass nur auf die ansteigende Flanke des Tasters reagiert wird.
  Serial.print("Testing keypad/PCF8574 I2C port expander arduino lib\n\n");
}

void loop()
{
     
     
    if (Key != '\0')
     {
     
     Serial.print("\n Key = ");
     Serial.print(Key);
     
    Key= '\0';
     
     }
 
}
void interruptroutine() //InterruptKeyCode
{
   
for(c=0;c<3;c++)
{
    // Suche Zeile LOW
    i2c_write(pcf8574_row_data[i]);
   
    // Lesen PCF8574 Port-Daten
    read_data = i2c_read();     // receive a byte as character
     
    // UM XOR zu erhalten und um zu erkennen ob eine Spalte LOW ist
    tmp_data = read_data ^ current_data; // current_data = Aktuelle daten
   
 
   
    tmp_data = tmp_data >>i;
 
     if (tmp_data == 1)
     {
      Key = KeyCode[row_select][c];
     
     
      tmp_data = '0/';
     }
 
   
  i--;
     if(i < 0)
  { 
    i = 3;
  }
   
   }
   
 
   //Nächste Zeile
      row_select++;
     if(row_select == 4)
  {
                       // Wenn du bei der letzten Zeile angekommen bist
    row_select = 0;    // dann beginnne wieder bei der ersten Zeile
  }
       

 

void i2c_write(int data)
{
  current_data = data;

  Wire.beginTransmission(I2C_Adresse); //Beginnt eine Übertragung als Master an die in address angegebene
       //Slave-Adresse.
  Wire.write(data);        //Speichert Daten in einer Warteschleife, die dann an eine Slave-
       //Adresse gesendet werden. Wire.write() wird nach wire.beginTransmission //aufgerufen.
  Wire.endTransmission();        //Beendet den Übertragungsblock
}

int i2c_read()
{
  Wire.requestFrom(I2C_Adresse, 1); //Fordert von einem Gerät Informationen an. address bezeichnet
//dabei die 7-Bit-Geräteadresse, quantity die Anzahl von Bytes, //die erwartet werden.
  return Wire.read(); //Empfängt das nächste Byte, das auf dem Bus für das Gerät vorliegt
//und gibt dieses als »Byte« zurück.
}
   
]


pylon

Hast Du Deinen Code mal ohne Interrupts getestet? Gibt der Chip über I2C überhaupt Antwort? Was ist der Rückgabewert von Wire.endTransmission()?

TerraHoff

Hallo pylon!

Ja, den Code habe ich ohne Interrupt getestet. Ohne Interrupt kann ich jede Taste abfragen, solbald ich es mit dem Interrupt probiere hägt sich der µC.

Hier der Code ohne Interrupt:

Code: [Select]
#include <Wire.h>

#define I2C_Adresse 0x20

byte tmp_data;
int i =3;
byte current_data;
byte read_data;
static char Key = '\0';
int row_select= 0;
int c;
int v;


// Daten für jede Zeile der Tastatur vom PCF8574
const int pcf8574_row_data[4] =
{
  B01101111, B01011111, B00111111
};
const char KeyCode[4][5] =
{
  "026",
  "7S3",
  "48E",
  "159"
};

void setup()
{
  Wire.begin();        )
  Serial.begin(9600);  // start serial for output
 
   pinMode(PIN2, INPUT);
  digitalWrite(PIN2, HIGH);
 
}

void loop()
{

 
  if (Key != '\0')
     {
     
     Serial.print("\n Key = ");
     Serial.print(Key);
   
    Key= '\0';
     
     }
 


 
for(c=0;c<3;c++)
{
 
 
  i2c_write(pcf8574_row_data[c]);
 
 
     
 
  read_data = i2c_read();    // receive a byte as character
   
    // UM XOR zu erhalten und die aktuellen Daten zu vergleichen und um zu erkennen,
    // wenn eine Spalte LOW ist
   
  tmp_data = read_data ^ current_data; // current_data = Aktuelle daten
   
   
    tmp_data = tmp_data >>i;
 
     if (tmp_data == 1)
     {
      Key = KeyCode[row_select][c];
     
      delay(500);
      tmp_data = '0/';
     }
   
  i--;
     if(i < 0)
  { 
    i = 3;
  }
   
   }
       //Nächste Zeile
      row_select++;
     if(row_select == 4)
  {                               // Wenn du bei der letzten Zeile angekommen bist,
    row_select = 0;      // beginnne wieder bei der ersten Zeile
  }

}


void i2c_write(int data)
{
  current_data = data;

  Wire.beginTransmission(I2C_Adresse);  //Beginnt eine Übertragung vom Master zum Slave.
  Wire.write(data); //Speichert die Daten in einer Warteschleife, die dann an eine Slave-
//Adresse gesendet wird. Wire.write
  Wire.endTransmission(); //Beendet den Übertragungsblock
}

int i2c_read()
{
  Wire.requestFrom(I2C_Adresse, 1); //Fordert von einem Gerät Informationen an.
//dabei die 7-Bit-Geräteadresse, quantity die Anzahl von Bytes,               //die erwartet werden.
  return Wire.read(); //Empfängt das nächste Byte, das auf dem Bus für das Gerät vorliegt
//und gibt dieses als »Byte« zurück.
}

TerraHoff

Hallo!

Kann mir denn niemand helfen?   :(

Gruß Sven


jurs


Kann mir denn niemand helfen?   :(


Was Du da vorhast, mit einem per Portexpander angeschlossenen Keypad innerhalb einer Interruptbehandlung per I2C-Kommunikation mit einer nicht interruptfesten fremden Library die Tasten abzufragen, halte ich für ein aussichtsloses Unterfangen.

Mein Vorschlag:
Entweder schließt Du Dein Keypad ohne Portexpander direkt an 7 I/O Pins des Arduino an und wertest den Zustand innerhalb einer Interruptbehandlung selbst aus, falls Du genügend freie I/O Pins hast. Oder Du verabschiedest Dich von der Idee, die Tastaturabfrage über Portexpander und I2C-Kommunikation unbedingt innerhalb einer Interruptbehandlung machen zu wollen und machst die Abfrage in der loop-Funktion.

Wenn Dein Programmdesign nicht komplett verhunzt ist, läuft die loop-Funktion doch selbst in einem komplexen Programm (das natürlich frei von "delay()" sein muss) mindestens auf einer "Drehzahl" von 1000 pro Sekunde, d.h. Du kannst innerhalb von einer Millisekunde in der loop() auf einen Tastendruck reagieren, und das ist um zwei Zehnerpotenzen schneller als die normale menschliche Reaktionszeit.

Go Up