Forum: Mikrocontroller und Digitale Elektronik grundlegendes ISR-Problem


von Krischan (Gast)


Lesenswert?

Hallo!
Ich wollte anfangen, ISRs zu benutzen.
Dazu habe ich einfach mal den Code aus dem Artikel geklaut 
(http://www.mikrocontroller.net/articles/Interrupt#.28AVR-.29_Beispiele_f.C3.BCr_die_praktische_Programmierung), 
geringfügig verändert:
1. Port B ist Ausgabe
2. Timer ist jetzt Timer 0
und versucht, dass auf einem Atmega8 im STK500 zum Laufen zu bringen.
Das Programm sollte die LED an PB1 blinken lassen.

Ihr ahnt es bereits: Die PortB-LEDs gehen an, auch PB1, aber es blinkt 
nicht.

Ich hab dann mal die Forensuche bemüht, aber die Leute haben meist 
fortgeschrittenere Probleme mit ISR, nicht sowas simples...

Um die Antworten auf einige typische Fragen vorweg zu nehmen:
Atmega8 ist als Device ausgewählt
uC ist auf 1 MHz intern gefust

Ich freue mich über jede Hilfe!
Gruß,
Krischan



#define F_CPU 1000000

#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>

// globale Variablen

volatile uint8_t flag = 0;

int main() {

// IO konfigurieren


    DDRB = 0xFF;

    PORTB = 0xFF;


// Timer2 konfigurieren

    TCCR0 = (1<<CS02) | (0<<CS01) | (0<<CS00); // Vorteiler 256 -> ~65ms 
Überlaufperiode @ 1 MHz
    TIMSK |= (1<<TOIE0);            // Timer Overflow Interrupt 
freischalten

// Interrupts freigeben

    sei();

// Endlose Hauptschleife

    while(1) {
        if (flag == 1) { // Neuer Timerzyklus ?
            flag = 0;

            // hier steht jetzt in Normalfall ein grosser Programmblock 
;-)
            PORTB ^= (1 << PB1);    // LED toggeln
        }
    }
}

// Timer2 overflow Interrupt
// hier wird der Hauptschleife ein neuer Timerinterrupt signalisiert

ISR( TIMER0_OVF_vect ) {
    flag = 1;
}

von Hmm (Gast)


Lesenswert?

65ms? Also 130ms Periode. Mensch, musst Du schnell gucken können! Wir 
könnten da nur eine scheinbar dauerhaft leuchtende LED sehen.

von Krischan (Gast)


Lesenswert?

7 Hz wären noch als Blinken/Flackern zu sehen und ich wäre zufrieden.

von Hmm (Gast)


Lesenswert?

Mag sein. Miss einfach nach.

von Hmm (Gast)


Lesenswert?

Ich rate mal, das die Blinkrequenz um die 60Hz ist.

von Thomas E. (thomase)


Lesenswert?

Krischan schrieb:
> 7 Hz wären noch als Blinken/Flackern zu sehen und ich wäre zufrieden.
Mach das trotzdem mal länger:
if (flag >= 8)
{...

ISR( TIMER0_OVF_vect )
{      flag++;
}

mfg.

von Krischan (Gast)


Lesenswert?

Danke, Thomas, das war eine gute Idee.
Leider liegt der Fehler nicht an dieser Stelle - ich habe den Wert auch 
mal auf 80 gesetzt, mit dem gleichen Ergebnis: die LEDs sind alle gleich 
hell. Da stimmt grundsätzlich irgendwas nicht, eine LED, die in 50% der 
Zeit an/aus gepulst ist, müsste, unabhängig von der Frequenz der Pulse, 
mit 50% insgesamt wahrgenommener Helligkeit scheinen.
Aber bei mir sind alle LEDs gleich hell.
Es scheint so, als würde das Programm die ISR garnicht wahrnehmen.

von Eumel (Gast)


Lesenswert?

Krischan schrieb:
> eine LED, die in 50% der
> Zeit an/aus gepulst ist, müsste, unabhängig von der Frequenz der Pulse,
> mit 50% insgesamt wahrgenommener Helligkeit scheinen.


Nö, dein Auge ist ziemlich nichtlinear.

Aber sehen sollte man den Unterschied schon...

von Joe S. (bubblejoe)


Lesenswert?

Schreib die ISR mal vor das main.

von Hmm (Gast)


Lesenswert?

Wieso "alle" LEDs? Da wird doch nur ein Portpin getoggelt.

Aber wie schon gesgt: Nachmessen. Das gibt die zuverlässigsten 
Informationen.

von Krischan (Gast)


Lesenswert?

Funktioniert leider auch nicht. Hätte ja gelacht, wenns das gewesen 
wäre, das wäre dann ein Compilerfehler gewesen, oder? Mein erster... 
Aber, wie gesagt, leider nicht.

Ich benutze übrigens AVR GCC.

von Krischan (Gast)


Lesenswert?

"Alle" LEDs, weil ich in das mit
   DDRB = 0xFF;
   PORTB = 0xFF;
so eingestellt habe. Du hast recht, es wird nur PB1 getoggelt, aber der 
Rest ist 1, nicht 0.
Ich habe Dir zuliebe auch mal nachgemessen, an PB1 liegt Vdd=4,94 V an.

von Hmm (Gast)


Lesenswert?

>Ich habe Dir zuliebe auch mal nachgemessen, an PB1 liegt Vdd=4,94 V an.

Wieso "mir zuliebe"? DU willst doch das es blinkt.

Jedenfalls kann die LED bei einer statischen Spannung von 4.94V 
natürlich nicht blinken. Du hast Dir hoffentlich schon gedacht, das Du 
nicht mit nem Multimeter sondern dem Oszi messen sollst, hoffe ich.

von Andreas W. (geier99)


Angehängte Dateien:

Lesenswert?

Dein Programm sollte funktionieren,
ich habe legendlich den Vorteiler vergrößert:
TCCR0 = (1<<CS02) | (0<<CS01) | (1<<CS00);  //1024 ==> 262ms ==> 3,8 Hz

Probier doch bitte mal die anghängte hex-datei aus.

Gruss
 Andreas
PS: Habe jetzt mein STK500 nicht rausgekramt aber im Simulator 
funktioniert es.

von Krischan (Gast)


Lesenswert?

Es stimmt, dass ich das will, dass es blinkt.
Ich glaube allerdings nicht, dass die Fehlerursache im Bereich "es 
blinkt zu schnell" zu suchen ist. Siehe dazu der Post weiter oben (der 
mit den 50%) und Eumels Korrektur dazu.

Ich habe mit einem Multimeter gemessen. Das Ding ist träge genug und 
nimmt eine (hochfrequente) Pulsweitenmodulation - und das hätten wir ja 
schließlich, falls die LED zu schnell blinkt - als gemittelte Spannung 
wahr. Das weiß ich aufgrund früherer Erfahrungen

Da bei einem 50% duty cycle mit annähernd 5V Vdd = Vmax um die 2,5V 
Spannung zu erwarten wären, spricht das meiner Meinung nach für die 
Theorie, dass die ISR irgendwie vom Programm misachtet wird.

von Krischan (Gast)


Lesenswert?

Hallo Andreas,
Dein .hex funktioniert, wie es zu erwarten gewesen wäre.
Das ist gut!
Und jetzt wird es interessant:
Wenn ich Deine Änderungen in meinen Code übernehme, die Sache kompiliere 
und flashe, dann bekomme ich wieder mein eintöniges "Es tut sich 
nichts"-Ergebnis.
Darf ich Dich bitten, den Quellcode zu posten?

von Hmm (Gast)


Lesenswert?

Wenn Du nicht messen willst oder kannst, dann bleibt Dir noch der 
Simulator. Am Code sehe ich jedenfalls kein Problem. Dann kann es noch 
die Schaltung sein.

Deine Vermutung, dass garnicht gepulst wird halte ich für durchaus nicht 
abwegig. Aber das ein Programm einen Interrupt ignoriert, das gibt es 
nicht. Sobald Interrupts enabled sind und der fragliche Overflow auch, 
muss die CPU den Interrupt behandeln.

Wenn man also Deinen, durch das Multimeter behaupteten, statischen Pegel 
als gegeben annimmt und das das Programm an sich gehen müsste, dann 
kommt man auf einen Widerspruch, der sich allenfalls noch im Simulator 
oder auch mit dem Oszi aufklären lässt.

von Thomas E. (thomase)


Lesenswert?

Krischan schrieb:
> Es stimmt, dass ich das will, dass es blinkt.
Das Programm blinkt auch. Da ist alles in Ordnung. Timer0 hat 2 
Register. Da kann selbst der grösste Idiot wenig falsch machen. Auch hat 
man bei den 4 relevanten Bits nur 16 Möglichkeiten. Und bei fast allen 
funktioniert es irgendwie.

Also die übliche Checkliste:
Richtige Taktquelle eingestellt?
CKDIV8-Fuse? Geht glaube ich beim 8er ein bisschen anders, können wir 
aber schon abhaken.
Richtiger Controller eingestellt(Compiler)?
Richtiger Controller eingestellt(Brenner)?
Wird die richtige Datei geflasht? Äusserst beliebter Fehler!
Funktioniert die Hardware? Teste mal mit einem Miniprogramm:

while(1)
{
DDRB = 0xFF;
PORTB = 0;
_delay_ms(500);
PORTB = 0xFF;
}

Wenn das nicht blinkt ist deine Hardware im A...

mfg.

von Hmm (Gast)


Lesenswert?

Bleibt noch die weitere Möglichkeit das der hier gepostete Code nicht 
der tatsächlich ablaufende Code ist.
Das ist durchaus nicht unwahrscheinlich. Einfach mal das falsche 
Hex-File im Programmierdialog ausgewählt. Ist schon mehreren Leuten so 
gegangen.

von Thomas E. (thomase)


Lesenswert?

Thomas Eckmann schrieb:
> while(1)
> {
> DDRB = 0xFF;
> PORTB = 0;
> _delay_ms(500);
> PORTB = 0xFF;
 //Da fehlt noch ein Delay
> _delay_ms(500);
> }

> Also die übliche Checkliste:
Watchdog und BOD fehlen noch.

mfg.

von Andreas W. (geier99)


Angehängte Dateien:

Lesenswert?

hier ist mein komplettes Projekt.

von Krischan (Gast)


Lesenswert?

Die übliche Checkliste.

Richtiger Controller eingestellt(Compiler)?

War Atmega128 eingestellt.

Don't taunt the Checkliste!




Es blinkt jetzt.

Das ist top, weil, es blinkt jetzt, andererseits auch ein bisschen 
traurig, weil, ahh, Gott... ich hab den ganzen Nachmittag schon dran 
gesessen und gedacht, dass kann nicht sein...

Ich gehe mit einem lachenden und einem weinenden Auge ins Bett.

Euch allen, in diesem Sinne, eine Gute Nacht, und Danke!

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.