PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Inkrementierung will nicht so recht



tirell
13.07.2013, 11:53
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:

PORTD |= (Minuten_Zehner << 4) | Minuten_Einer;

Problematisch wird es wenn ich die Variable der Einer im main() inkrementieren will.
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?

if(~PINB & 1 << PB0)
{
Minuten_Einer ++;
}
else{}

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.

Hubert.G
13.07.2013, 12:08
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.

tirell
13.07.2013, 12:10
Hallo Hubert, ja die Variablen sind global als volatile unsigned char deklariert.

Bumbum
13.07.2013, 15:56
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:



PORTD = (Minuten_Zehner << 4) | Minuten_Einer & 0xF;

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.

Viele Grüße
Andreas

tirell
13.07.2013, 17:23
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


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 tens




while(1)
{
if(!(PINB & (1 << PB0))) // read input
{
m1 ++;
_delay_ms(1000);
}
else{}
}


Wird Zeit die Tasten zu entprellen, dadurch sollte sich das Problem endgültig lösen.
Vielen Dank für die guten Ansätze! :)

Bumbum
14.07.2013, 10:45
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

tirell
16.07.2013, 20:31
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.