Ich hab hier eine Geschichte, die ich mal als Vorbereitung für eine Erklärung erarbeitet hatte.
Kommst Du damit zurecht?
volatile unsigned int pinscore[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // Vorbelegung Zähler mit 0
volatile byte pinlaststate[8] = {1, 1, 1, 1, 1, 1, 1, 1}; // Vorbelegung für PinStatusAbfrage
long lastmillis = 0;
void setup(void) {
Serial.begin(115200); // serieller Monitor
Serial.println("INIT"); // Ausgabe, "Start"
pinMode(A8, INPUT_PULLUP); // PIN A8 bis A15 auf dem MEGA
pinMode(A9, INPUT_PULLUP); // als INPUT deklarieren und
pinMode(A10, INPUT_PULLUP); // den internen PULLUP aktivieren
pinMode(A11, INPUT_PULLUP); // PINs stehen auf PLUS (HIGH)
//pinMode(A12, INPUT_PULLUP); // ausgewertet wird, wenn PIN auf
//pinMode(A13, INPUT_PULLUP); // GND (LOW) steht, da hier immer garantiert 0
//pinMode(A14, INPUT_PULLUP); // A8 = PCINT16 / A15 = PCINT23
//pinMode(A15, INPUT_PULLUP); // AVR-Pin: 89-82
cli(); // schaltet Interrups ab
PCMSK1 = B00000111; // aktiviert PIN A8 bis A15 / entspricht PORT K
//PCMSK2 |= (1 << PCINT16); // alternativ: aktiviert nur PIN A8
//PCMSK2 |= (1 << PCINT17); // alternativ: aktiviert nur PIN A9
PCICR |= (1 << PCIE1); // aktiviert PinChangeInterrupt (im) ControlRegister
sei(); // schaltet Interrupts wieder ein
}
ISR(PCINT1_vect) { // Name ist zwingend festgelegt
#define debug_isr 1 // In der ISR debuggen? Ja=1 Nein=0
// // Hinweis: 'define' statt 'const int' spart Cycles während der Ausführung!
static long pinlastmillis[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // static: wird nur hier gebraucht - spart bytes
const byte pindebounce[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // festlegen der Bouncezeit je PIN in ms
// const int pindebounce = 40; // Wenn nur eine Zeit ausreicht
unsigned char portstate = PINC; // PINK ist nicht die Farbe sondern der PINportK
// // kopiert den Zustand in eine Variable
if (debug_isr) {
Serial.print(F("Start: ")); // Gibt den Inhalt des Port aus ...
Serial.print(portstate); // ... als byte
Serial.print(F(" - "));
Serial.println(portstate, BIN); // ... im binaeren Format
}
for (int i = 5; i <= 7; i++) { // Auswertung: jeden einzelnen PIN
if (pinlaststate[i] != ((portstate << i) & 0x80 )) { // Hat sich der PINZustand verändert?
if (millis() - pinlastmillis[i] > pindebounce[i]) { // Wenn ja: Ist die Bouncezeit abgelaufen?
/* if (millis() - pinlastmillis[i] > pindebounce) { */// (Alternative wenn nur eine Bouncetime)
pinlaststate[i] = ((portstate << i) & 0x80 ); // Dann speichere aktuellen Zustand und ...
pinlastmillis[i] = millis(); // ... speichere aktuelle millis und ...
if (debug_isr) { // ... wenn debug aktiviert ...
Serial.print(pinlaststate[i]); // ... gebe Zustand aus und ...
Serial.print(F(" / pinlastmillis: ")); // ... zeige ...
Serial.println(pinlastmillis[i]); // ... eingetragene ms und ...
} // ... egal ob debug or not ....
if (0 == pinlaststate[i]) { // ... prüfe ob der Zustand jetzt 0 ist
pinscore[i]++; // wenn ja, dann zähle für den PIN +1
}
}
}
}
if (debug_isr) {
Serial.print(F("Score in isr: ")); // Ab hier Ausgabe, was jetzt im Zählerarray steht
for (int i = 7; i >= 5; i--) {
Serial.print(pinscore[i]);
Serial.print(F(" / "));
}
Serial.println();
}
}
void loop(void) {
static long lastmillis = 0;
//delay(2000); // delay um zu zeigen, das Interrupt unabhängig von delay()
if (millis() - lastmillis >= 2000) { // gibt nur alle 60secunden eine Ausgabe - gezählt wird trotzdem
Serial.print(F("Score in loop: ")); // Ausgabe des Inhalts des Zählers, um zu zeigen, das und wie man an die
for (int i = 5; i <= 7; i++) { // Zählerinhalte innerhalb von loop kommt.
Serial.print(pinscore[i]);
// pinscore[i] = 0;
Serial.print(";");
}
Serial.println();
lastmillis = millis();
}
}
Nicht perfekt und ich hab grad nachgesehen, die ist schon ein paar Tage alt und mit heutigem Wissen eindeutig Verbesserungswürdig.