if(~PINB & 1 << PB0)
Ich schreibe Pin-Abfragen immer so:
if(!(PINB&(1<<PB0)))
Das Variable die in einer ISR verwendet und verändert werden können, als volatile deklariert werden müssen ist schon klar.
Als erstes einmal ein freundliches 'Hallo' an alle hier.
Ich bin schon seit einiger Zeit hier unterwegs habe aber noch nie etwas gepostet, ein stiller Leser quasi
Da ich nun aber vor einem wirklich blöden Problem stehe und auch nach langer Suche nicht weiterkomme
erhoffe ich mir hier eine Lösung zu bekommen.
Mein Problem ist folgendes: Ich arbeite gerade an einer Uhr welche an einem Port 2 BCD-Wandler (74141 equivalent) steuert, µC ist ein ATMega16.
Da ich an einem Port für die beiden 74141 die Einer und Zehner einzeln hochzählen muss(?) habe ich mich an Bitoperationen bedient und folgenden Code in der ISR genutzt:
Problematisch wird es wenn ich die Variable der Einer im main() inkrementieren will.Code:PORTD |= (Minuten_Zehner << 4) | Minuten_Einer;
Der folgende Code zählt allerdings die Zehner hoch und setzt die Einer auf Null. Meine Gedanken haben sich ziemlich darauf versteift dass es daran liegt,
wie ich den Port im ISR ansteuere. Liege ich damit überhaupt richtig oder bin ich schon total festgefahren?
PS: Der 74141 wandelt die Eingänge A bis D binär in 0 bis 9 dezimal um und zieht diese auf GND falls es jemanden interessiert.Code:if(~PINB & 1 << PB0) { Minuten_Einer ++; } else{}
Geändert von tirell (13.07.2013 um 17:24 Uhr)
if(~PINB & 1 << PB0)
Ich schreibe Pin-Abfragen immer so:
if(!(PINB&(1<<PB0)))
Das Variable die in einer ISR verwendet und verändert werden können, als volatile deklariert werden müssen ist schon klar.
Hallo Hubert, ja die Variablen sind global als volatile unsigned char deklariert.
Hallo tirell,
ist deine Abfrage in der main in einer Schleife? Dann kann es sein, dass die Minuten_Einer solange gezählt werden wie die Bedingung erfüllt ist. Da du sie in deiner Bitoperation nicht filterst zählen dadurch auch die Zehner, wenn der Wert in Minute_Einer über 15 ist.
Weiterhin ist mir noch aufgefallen, dass du PORTD "veroderst". Ich würde es wie folgt lösen:
Damit hast du dann aber noch nicht die Ursache behoben. Wie gesagt aber nur, wenn die PINB Abfrage in einer Schleife liegt. In diesem Fall musst du nach der Inkrementierung warten, bis die Bedingung wieder "erloschen" ist.Code:PORTD = (Minuten_Zehner << 4) | Minuten_Einer & 0xF;
Viele Grüße
Andreas
Alles klar, Problem gelöst. Du hast mich auf den richtigen Ansatz gebracht mit dem warten,
habe probehalber mal ein delay nach der Inkrementierung eingefügt und nun funktioniert es.
Hier ist nochmal der korrigierte Code
Code:PORTD &= 0x00; // output minutes ones and tens PORTD = (s2 << 4) | (s1 & 0xF); // output minutes ones and tens PORTA &= 0x00; // output hours ones and tens PORTA = (m2 << 4) | (m1 & 0xF); // output hours ones and tensWird Zeit die Tasten zu entprellen, dadurch sollte sich das Problem endgültig lösen.Code:while(1) { if(!(PINB & (1 << PB0))) // read input { m1 ++; _delay_ms(1000); } else{} }
Vielen Dank für die guten Ansätze!
Hallo tirell,
mit Tasten-Entprellen hat das Problem, dass du hast aber nichts zu tun. Ich denke kein Mensch kann die Taste nur einen Takt-Zyklus halten. Und auch das Delay ist nur eine Pfusch-Lösung. Du musst eine Sperre einbauen die das zählen so lange verhindert, bis PB0 wieder losgelassen wurde.
Und erst dann brauchst du natürlich noch eine Entprellung.
Viele Grüße
Andreas
Hallo, das stimmt natürlich. Habe mich an dem Tutorial hier bezüglich des Auslesens von Tasterbetätigungen orientiert und meinte das fälschlicherweise als Entprellung
Funktioniert jetzt alles bestens und wie erwünscht.
Lesezeichen