Ich versuche, Pinwechsel-Interrupts zu verwenden, um gedrückte Tasten zu erkennen. Bis jetzt habe ich noch nie mit solchen Interrupts gearbeitet und es gibt einige Probleme. Deshalb möchte ich sicherstellen, dass dies die richtige Verwendung ist.
Wenn ich das Datenblatt richtig verstanden habe, müssen die folgenden Schritte ausgeführt werden, um einen Pin-Wechsel-Interrupt zu verwenden:
- Legen Sie im PCMSK-Register fest, welche PINs Sie steuern möchten
- Aktivieren Sie das PIN-Register für die Pinwechsel-Interrupt-Steuerung (PCICR).
- Interrupts aktivieren
- Verwenden Sie den entsprechenden Interrupt-Vektor
Projekt: Einfache Stimmungslampe, Farben über 4 Tasten gesteuert.
Installieren:
- Atmega168A-PU
- 4 Mini-Druckschalter
- MOSFETS zur Steuerung meiner 3 Watt RGB LED
Hier ist der Code, den ich verwende und der nicht wie erwartet funktioniert:
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define BUTTON1 (1<<PC5)
#define BUTTON2 (1<<PC4)
#define BUTTON3 (1<<PC3)
#define BUTTON4 (1<<PC2)
#define GREEN (1<<PB1)
#define BLUE (1<<PB2)
#define RED (1<<PB3)
void init() {
// enable LED
DDRB |= GREEN;
DDRB |= BLUE;
DDRB |= RED;
// button pullups
PORTC |= BUTTON1;
PORTC |= BUTTON2;
PORTC |= BUTTON3;
PORTC |= BUTTON4;
// pin change interrupts for buttons
PCMSK1 |= PCINT13;
PCMSK1 |= PCINT12;
PCMSK1 |= PCINT11;
PCMSK1 |= PCINT10;
// enable pin change for buttons
PCICR |= PCIE2;
sei();
}
ISR(PCINT2_vect) {
PORTB = BLUE;
}
void ledTest() {
PORTB ^= RED;
_delay_ms(250);
PORTB ^= RED;
_delay_ms(250);
PORTB ^= RED;
_delay_ms(250);
PORTB ^= RED;
PORTB ^= BLUE;
_delay_ms(250);
PORTB ^= BLUE;
_delay_ms(250);
PORTB ^= BLUE;
_delay_ms(250);
PORTB ^= BLUE;
PORTB ^= GREEN;
_delay_ms(250);
PORTB ^= GREEN;
_delay_ms(250);
PORTB ^= GREEN;
_delay_ms(250);
PORTB ^= GREEN;
}
int main() {
init();
ledTest();
_delay_ms(500);
PORTB |= GREEN;
while(1) {
_delay_ms(100);
}
}
Hinweis: Die Tasten sollten entprellt werden. Da ich dies Schritt für Schritt versuche und es für das Einschalten der LED keine Rolle spielen sollte, habe ich es hier ignoriert.
Frage: Ist die Art und Weise, wie ich versuche, die Interrupts zu verwenden, korrekt?
Probleme mit meinem Setup:
- Die Schaltflächen 1-3 werden vollständig ignoriert.
- Button4 löst einen Reset der Atmosphäre aus
Dinge, die ich überprüft habe:
- Tasten sind in keiner Weise mit der Reset-PIN verbunden
- Die Tasten sind ordnungsgemäß mit GND verbunden, wenn sie gedrückt werden
- Tasten sind nicht mit GND verbunden, wenn sie nicht gedrückt werden
Schaltflächen funktionieren gut, wenn ich sie ohne Unterbrechung verwende, z.
if (! (PINC & BUTTON4)) {PORTB ^ = BLUE; }}
- 16 MHz externer Kristall / interner Kristall
- Fehler im Routing
- Ich benutze einen 100nF Kondensator zwischen PWR und GND auf der Atmosphäre
- VCC (7), GND (8), GND (22), AVCC (20) sind verbunden (da ich AREF nicht benötige, ist es nicht verbunden)