Forum: Compiler & IDEs Timer und Interrupte


von Martin (Gast)


Angehängte Dateien:

Lesenswert?

Hallo!

Ich versuche vergeblich mein Timergesteuertes Programm auf meinem
ATMega8 ans laufen zu bekommen.
Es soll eine Leuchtdiode im Sekundentakt an und ausschalten.
Dieses Programm schreibe ich, um den Umgang mit Interrupts
und Timern zu verstehen.
Statt dass die Leuchtdiode an und ausgeht, bleibt sie einfach
an. Ich verstehe nicht, warum. Ich glaube, meine Interrupte
werden nicht ausgeführt und die Leuchtdiode ist an, weil sie
standartmäßig angeschaltet wird, wenn ich den Port als
Ausgang definiere, oder?

Auch der Simulator in Linux (simulavr) lässt die Lampe nicht
im sekundentakt leuchten, wenn ich ihn mit
$ simulavr -d atmega8 -c 1000000 ./a.out
starte.

Der ausdokumentierte Quellcode ist im Anhang.

Martin

von Jörg Wunsch (Gast)


Lesenswert?

Hmm, warum fängst Du nicht mit dem demo.c an, das zur avr-libc
dazugehört?  Es hat alles, was ein ,,Hello world'' Programm so
braucht
-- einschließlich Interrupts.  Und Kommentare. ;-)

von Martin (Gast)


Lesenswert?

Achso, ich wusste nicht, dass es sowas gibt.
Ich habe es mir gerade angeguckt,
bekomme aber beim kompilieren die Fehlermeldung:
#error "Don't know what kind of MCU you are compiling for"

Ich habe natürlich nicht vergessen, meinen Mikrocontroller mit
#define _AVR_ATmega8_
anzugeben. Vielleicht ist das Programm nicht für diesen geschrieben.
Wenn ich diese error-Zeile aus der demo.c lösche, bekomme ich lauter
Error-Meldungen, z.B. findet er kein OCR.
Ich kenne mich damit nicht aus. In meinem Programm ist schon das
aller-
nötigste und es klappt trotzdem nicht. Hat jemand vielleicht eine
Idee, wo der Fehler liegt?

Martin

von Jörg Wunsch (Gast)


Lesenswert?

> Ich habe natürlich nicht vergessen, meinen Mikrocontroller mit
> #define __AVR_ATmega8__
> anzugeben.

Schon falsch.  Die Compileroption -mmcu macht das für Dich.

> Wenn ich diese error-Zeile aus der demo.c lösche, bekomme ich lauter
> Error-Meldungen, z.B. findet er kein OCR.

Nun, wie Dir die #error Zeile suggerieren wollte, kennt das
Progrämmchen von sich aus noch keinen ATmega8 (einfach, weil ich
selbst keinen habe, mit dem ich es testen könnte).  Leider benennt
Atmel die Steuerregister von AVR zu AVR ein wenig anders (je nachdem,
was die jeweilige Hardware halt tatsächlich hergibt), so daß man
kleine Anpassungen für jeden AVR braucht.  Mit einem Datenblatt in der
Hand sollte das allerdings kein Thema sein, das für den ATmega8
nachzuholen.  Wahrscheinlich kannst Du einen der existierenden #ifdef
Blöcke übernehmen (oder gar nur ein || defined(_AVR_ATmega8_) mit
reinschreiben), besonderes Augenmerk solltest Du dem OC-Ausgang
widmen, da Port und Pin-Nummer dafür in der Hardware vorgegeben sind.

So als Schuß ins Blaue:

#elif defined(_AVR_ATmega8_)
#  define OC1 PB1
#  define DDROC DDRB
#  define OCR OCR1A
#  define PWM10 WGM10
#  define PWM11 WGM11

Wenn Du mir bestätigst, daß es damit funktioniert, nehme ich das in
den offiziellen Sourcecode mit auf.

von Martin (Gast)


Lesenswert?

HI!

Ja, das funktioniert bei mir. SUPER!!! Danke!
Die Leuchtdiode leuchtet bei einem 8 MHz-Quarz fast
im Sekundentakt. (in 15 Sekunden 1 Sekunde Unterschied).
Bei einem 1 MHz-Quarz ist sie VIEL langsamer.
Wo kann ich eigentlich im Programm einstellen,
welchen Quarz ich benutze?

Martin

von Jörg Wunsch (Gast)


Lesenswert?

> Ja, das funktioniert bei mir. SUPER!!! Danke!

OK, ist im offiziellen Sourcecode drin.

> Wo kann ich eigentlich im Programm einstellen, welchen Quarz ich
> benutze?

Gar nicht, weil Quarze Hardware sind und nicht Software. ;-)

(Wahrscheinlich wolltest Du was anderes fragen, aber ich komm nicht
drauf, was es sein sollte.)

von Martin (Gast)


Lesenswert?

Die Frage ist, wie ich im Programm (demo.c) festlegen kann,
dass die Leuchtdiode einmal in der Sekunde an- und
ausgeht. Das hängt natürlich vom Quarz ab, den ich
benutze. Was muss ich verändern, wenn ich einen 8 MHz-Quarz
benutze und was muss ich verändern, wenn ich einen 1 MHz-Quarz
benutze? Ich besitze nämlich diese beiden Quarze.

von Jörg Wunsch (Gast)


Lesenswert?

Dazu mußt Du Dir mal die Doku zum PWM in der Beschreibung des Timer 1
durchlesen.  Du kannst erstmal den Vorteiler des Timers ändern,
allerdings gibt das natürlich nur grobe Schritte.  Dann kannst Du die
Zählweite des Timers umschalten (10-bit = 1024, 9-bit = 512, 8-bit =
256), damit ändert sich auch die Frequenz, allerdings mußt Du das
Programm dann auch ändern, da sich der TOP-Wert des Zählers ändert.

Du kannst den PWM bei den neueren ATmegas auch auf `fast PWM'
schalten, siehe Doku.  Bringt nochmal doppelte Frequenz.

von Peter D. (peda)


Lesenswert?

"Was muss ich verändern, wenn ich einen 8 MHz-Quarz
benutze und was muss ich verändern, wenn ich einen 1 MHz-Quarz
benutze?"


Den Code so schreiben, daß er für Dich alles genau ausrechnet, z.B.:

http://www.mikrocontroller.net/forum/read-4-57760.html


Peter

von Jörg Wunsch (Gast)


Lesenswert?

Nee Peter, das hilft beim PWM so nicht weiter.  Du hast dort ein paar
Freiheitsgrade weniger.

von OldBug (Gast)


Lesenswert?

Er will doch gar keine PWM benutzen, oder sehe ich das falsch?

von Jörg Wunsch (Gast)


Lesenswert?

Hat er ja aber mittlerweile -- demo.c benutzt eine PWM und läßt die
LED auf- und abschwellen.  Fällte trotzdem noch in die Klasse ,,Hello
world!'' Programm, der PWM auf dem AVR ist so simpel.

von Martin (Gast)


Lesenswert?

Hi!

So langsam verstehe ich die demo.c. Ich habe jedoch noch einige
Fragen:

1) Ich versteh nicht, wofür die Bytes 4-7 im
"Timer/Counter 1 Control Register A" (TCCR1A) da
sind: COM1A1 COM1A0 COM1B1 COM1B0
Wird in der demo.c in folgendem Beispiel in der main verwendet:
TCCR1A = _BV (PWM10) | _BV (PWM11) | _BV (COM1A1);
         \      10 bit PWM        /  \     ?    /
          ------------------------    -----------
Nach einer Beschreibung sollen sie angeblich der
Compare Ausgang A und B sein. Heißt das, dass der Timer ständig
mit einem bestimmten Wert verglichen wird, wenn diese Bits
gesetzt sind? Was ist dann der Unterschied zwischen
COM1A1 und COM1A0? Und was bedeutet das A und das B in
COM1A1 und COM1B1?

2)
OCR ist doch die Pulsweite, oder? Bei 10 bit PWM ist für
OCR=1024 die Pulsweite am größten, oder? Wenn ich keine
Pulsweite brauche, sondern nur einen sekündlichen Impuls
(an / aus), dann kann ich die Pulsweite doch zwischen
1024 und 0 immer hin- und herspringen lassen, oder?

3)
Falls jemand vielleicht Lust hat, in meinem Programm ganz oben
nachzugucken, wieso mein Interrupt nicht funktioniert und
die Lampe ständig hell bleibt, würde ich mich sehr freuen,
falls er mir Tipps geben würde, wo der Fehler liegt.

Ich bedanke mich nochmal vielmals für eure Hilfe und
wäre sehr froh, wenn ich mein Programm ans Laufen bekomme.

Martin

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.