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;
}
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.
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.
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...
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.
"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.
>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.
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.
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.
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?
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.
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.
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.
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.
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!