Forum: Mikrocontroller und Digitale Elektronik ATTiny 85 Interrupt unterbrechungen


von Carsten M. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

vielleicht kann mir einer von euch mit meinem Problem weiterhelfen.

Kurz zum Aufbau meiner Schaltung.

Der uC soll en PB0 eine PWM eines RC-Empfängers auswerten. Dazu wird ein 
Interrupt bei PB0=high ausgelöst. Dieser startet den Counter0. Ist 
PB0=low
wird der Counter gestoppt und das Register ausgewertet.

Das Programm läuft soweit durch. Jedoch wird der Ausgang 
zwischenzeizlich auf low gesetzt, obwohl dieses nicht sein dürfte.

Was mache ich da falsch?
Es scheint egal zu sein, ob ich den Timer starte und stopppe oder 
einfach das Register auf Null setze, wenn der Interrupt ausgelöst wird.

Ich habe erst an den Stack gedacht, aber das Programm sollte diesen 
nicht überfordern.

Gruß
Carsten

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Möglicherweise ne Race-Condition? Du greifst nicht-atomar auf 16-Bit 
Variablen zu, die in der ISR geändert werden.

AVR kann einen int nicht in einer Instruktion lesen/schreiben. Wenn eine 
ISR innerhalb des Zugriffs reinhaut, gibt's Phantasiewerte.

Johann

von Andreas R. (rebirama)


Lesenswert?

Du verwendest PB2 statt PB0!

Das hier hält definitiv keinen Timer an :-)
TCCR0B |= (0<<CS00) | (0<<CS01) | (0<<CS02);

Außerdem sollte der Timer beim initialisieren noch nicht gestartet 
werden, sondern erst bei der ersten flanke.

Ob der Rest deines Progs so stimmt, weiß ich nicht, vorallem die 
Timereinstellung, Auflösung etc.

Ich hätt es wahrscheinlich anders gelöst:
INT0 als "on change" verwenden.
je nach Zustand von PB2 Timer starten oder {stopen, auslesen, 
rücksetzen}.
Den gemessenen Timerwert einfach in ne globale volatile Variable stecken 
und gemütlich in der Main auswerten. Eventuell noch eine 
Plausibilitätsprüfung (zu kurze Pulse sind ungültig oder so).
Wenn dus paranoid Wasserdicht machen willst musst du noch Funktionen 
gegen eine Interruptüberlast einbauen. (z.B. Taubschalten des Interrupts 
für eine Gewisse zeit nach der letzten fallenden Flanke). Wenn du 
nämlich durch irgend einen dämlichen Zufall 10k Pulse pro Sekunde auf 
deiner Int-Leitung hast, kommt deine Main nicht mehr dran!

Außerdem nimm statt "int" "uint8_t", dann hast du auch keine Probs mit 
"atomar". Dein Timer ist eh nur 8 Bit breit.

von Carsten M. (Gast)


Lesenswert?

Hallo,

danke für die schnellen Antworten.

Laut Datenblatt soll der Timer mit
"TCCR0B |= (0<<CS00) | (0<<CS01) | (0<<CS02)" gestoppt werden.
zb.
TCCR0B |= (1<<CS00) | (0<<CS01) | (0<<CS02) startet den Timer sofort.

Ich werde das mit "uint8_t" mal testen.

Des weiteren bin ich der Meinung das der Counter0 doch ein 8-bit Timer 
ist.
Zumindest habe ich das Datenblatt so verstanden.

Gruß
Carsten

von Michael U. (amiga)


Lesenswert?

Hallo,

Du hast zwar das Datenblatt verstanden, die Bitmanipulation in C aber 
nicht...

Eine 0 konnst Du hinschieben wie Du willst, es bleibt 0.
Ein Register mit 0 ver-odert ändert sich also garnicht.

TCCR0B &= ~((1<<CS00) | (1<<CS01) | (1<<CS02));

passt da eher.

Gruß aus Berlin
Michael

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.