PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] ATMEGA8 Timer etwas zu schnell



Tux12Fun
07.04.2020, 20:02
Hallo,

ich habe folgenden Teil von einem ATMEGA32-16 auf den ATMEGA8 übernommen.

Nur leider läuft der Timer nicht bei 8 Sekunden über sondern bei 2 wenn ich mit dem Handy richtig stoppe.

Vielleicht könnt Ihr mir dazu auch einen Tipp geben. Am ATMEGA hängt ein 32,768kHz Crystal an TOSC1/TOSC2

Und so sieht mein bereits reduzierter :-) und getesteter Quellcode aus


//-U lfuse:w:0xe2:m -U hfuse:w:0xd9:m

#define MCU atmega8
#define F_CPU 2000000UL

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/power.h>


#define BT_EN_REGISTER DDRC
#define BT_EN_PORT PORTC
#define BT_EN_PIN PC0

#define LED_REGISTER DDRC
#define LED_PORT PORTC
#define LED_RED_PIN PC5
#define LED_GREEN_PIN PC4
#define LED_BLUE_PIN PC3


// Timer2 Interrupt (Occurs every 8 Seconds)
ISR(TIMER2_OVF_vect) {
LED_PORT ^= (1 << LED_RED_PIN);
}


int main(void){
// Direction Registers
DDRB = 0x00; // B as input
DDRC = 0x00; // D as Input
DDRD = 0x00; // D as Input

// Set Output Registers
LED_REGISTER |= (1 << LED_RED_PIN); // LED as output
LED_REGISTER |= (1 << LED_GREEN_PIN); // LED as output
LED_REGISTER |= (1 << LED_BLUE_PIN); // LED as output

// Ports to LOW (GND no Pullup)
PORTB = 0x00;
PORTC = 0x00;
PORTD = 0x00;

// Configure Timer2 (Countdown Timer)
ASSR = (1<< AS2); // Timer2 asynchron takten
_delay_ms(2000); // Einschwingzeit des 32kHz Quarzes
//TCCR2 = 6; // Vorteiler 256 -> 2s Überlaufperiode
TCCR2 |= (1 << CS22) | (1 << CS21) | (1 << CS20); // Prescaler 1024 -> 8s Überlaufperiode
while((ASSR & (1<< TCR2UB))); // Warte auf das Ende des Zugriffs
TIFR = (1<<TOV2); // Interrupts löschen (*)
TIMSK |= (1<<TOIE2); // Timer overflow Interrupt freischalten


// Release Interrupts
sei();

while (1){
LED_PORT &= ~(1<<LED_GREEN_PIN);
LED_PORT |= (1<<LED_BLUE_PIN);
// WICHTIG!
// Wenn der Timer2 im asynchronen Modus periodisch zum Wecken aus dem Sleep Mode
// genutzt wird, dann muss vor dem Wiedereintritt mindestens
// 1 Oszillatortakt des Timers abgewartet werden (~30us), um die Interruptlogik
// wieder zu aktivieren, anderenfalls wacht der AVR nicht mehr auf.
// Die folgenden zwei Zeilen tun dies.
// Nur wenn sichergestellt ist, dass der Interrupt + Hauptschleife länger als 30µs dauern,
// kann man den Test weglassen
OCR2 = 0; // Dummyzugriff
while((ASSR & (1<< OCR2UB))); // Warte auf das Ende des Zugriffs

// Go to sleep
set_sleep_mode(SLEEP_MODE_PWR_SAVE);
sleep_mode(); // in den Schlafmodus wechseln

// hier wachen wir wieder auf

LED_PORT &= ~(1<<LED_BLUE_PIN);
LED_PORT |= (1<<LED_GREEN_PIN);
}

}


Aktuelles Verhalten. Programm startet und geht in den Tiefschlaf. (Blaue LED an)
Dann fängt die Rote LED im an zu blinken. 2 Sekunden an, 2 Sekunden aus.
Erwartet hätte ich über den Vorteiler den ich mal berechnet habe 8 Sekunden.

Searcher
08.04.2020, 07:04
_delay_ms(2000); // Einschwingzeit des 32kHz Quarzes
//TCCR2 = 6; // Vorteiler 256 -> 2s Überlaufperiode
TCCR2 |= (1 << CS22) | (1 << CS21) | (1 << CS20); // Prescaler 1024 -> 8s Überlaufperiode


Erwartet hätte ich über den Vorteiler den ich mal berechnet habe 8 Sekunden.

Würde ich auch erwarten.
Wechselt die Blinkfrequenz der roten LED mit Vergrößern des _delay_ms Wertes?
TCCR2 würde ich nicht verodern sondern den Prescale Wert direkt zuweisen.

Gruß
Searcher

Klebwax
08.04.2020, 10:20
Nur leider läuft der Timer nicht bei 8 Sekunden über sondern bei 2 wenn ich mit dem Handy richtig stoppe.

Die Überschrift führt da massiv in die Irre. Ein Faktor 4 ist nicht "etwas". Die Ursache ist da natürlich eine andere. Für "etwas" müsste man nach den Kondensatoren am Quarz oder an ähnlicher Stelle in der Hardware schauen, bei einem Faktor 4, einer Potenz von 2, ist es mit 99,9% Software. Da ist Datenblatt lesen angesagt.

MfG Klebwax

Siro
08.04.2020, 12:46
Hallo Tux12Fun,

ich hab mit Atmels noch nichts gemacht, aber eine Idee hätte ich evtl.
Bist Du Dir sicher, dass der Controller auch wirklich mit dem externen Quarz läuft ?
Lässt sich einfach feststellen: Ein Bein vom Quarz ablöten, wenn er dann immer noch läuft, stimmt mit der Konfiguration was nicht,
dann läuft er mit dem internen RC-Oszillator.
Man muss bei den Atmels wohl einige Einstellungen mit den FUSES machen,
diese Zeile scheint in deinem Code (1. Zeile) auskommentiert zu sein.

Siro

oberallgeier
08.04.2020, 13:32
.. eine Idee hätte ich evtl .. muss bei den Atmels wohl einige Einstellungen mit den FUSES .. scheint in deinem Code (1. Zeile) auskommentiert zu sein ..Darüber wunderte ich mich auch schon ne Weile. Die Einstellung ergibt-ergäbe

Int. RC Osc. 2 MHz; Start-up time: 6 CK + 64 ms

Zumindest stimmt damit der im Code genannte Takt von 2 MHz. WENN der Controller die auskommentierte Einstellung auch wirklich intus hat. Weiter bemerkenswert ist dabei aber der Unterschied zwischen dem auskommentierten
//TCCR2 = 6; // Vorteiler 256 -> 2s Überlaufperiode
und dem
TCCR2 |= (1 << CS22) | (1 << CS21) | (1 << CS20); // Prescaler 1024 -> 8s Überlaufperiode

das ist genau der Faktor vier - von dem hier die Rede ist.

Wie Klebwax schreibt : ".. bei einem Faktor 4, einer Potenz von 2, ist es mit 99,9% Software ..".

Oder meine (früher oft benutzte) Plattitüde : ".. Controller programmieren ohne Datenblatt ist eines der letzten Abenteuer unserer Tage ..". Wobei ich sicher bin, dass hier das Datenblatt gelesen wurde - nur die Fuses zu setzen/lesen ist manchmal "abenteuerlich" *gg*

@Tux12Fun : Viel Erfolg.

Tux12Fun
08.04.2020, 16:54
Hallo,

tut mir leid, dass ich erst jetzt zum antworten kann.

Der Microcontroller läuft tatsächlich mit 2Mhz und die kommentierte Zeile mit den Fuses ist gesetzt.
Diese habe ich mit avrdude geschrieben und mir dort einfach notiert, damit ich die Einstellungen im parat habe.

Der Vorteiler mit 6 war aus einem Beispiel das ich damals abgekupfert habe und ist auch wirklich Kommentar.
Gesetzt ist Prescaler 1024 ich werde als nächstes mal den Versuch mit dem verdoppeln des delays machen.

Der Quarz ist auch tatsächlich aktiv. Ziehe ich den Quarz aus dem Steckbrett bleibt die LED stehen.
Wenn ich das alles richtig verstanden habe wechselt der Controller beim sleep Mode auf den externen Quarz

Ich habe auch fleißig im Datenblatt gesucht. Ob ich noch etwas falsch mache, da der Code auf dem ATMEGA32 läuft
und auf dem ATMEGA8 eben nicht.

Ja die Abweichung zwischen 2 Sekunden und 8 ist enorm und ich hätte gerne wieder 8 Sekunden

- - - Aktualisiert - - -

Ich habe nun mal den delay_ms erhöht allerdings hat das keine Auswirkung. Dann habe ich den Prescaler auf 6 gesetzt LED blinkt ca jede Sekunde.

Dann auf 7 das müsste wenn ich richtig gerechnet habe CS22 CS21 CS20 sein also 8 Sek. Aber die LED blinkt wie zuvor alle 2 Sekunden.

Quarz ziehen führt zum sofortigen Stop

- - - Aktualisiert - - -

Rätsel gelöst und ihr habt mit Hardware recht. Kaum fügt man 2x 27pf und Masse hinzu läuft es korrekt. Beim Atmega32 brauchte ich die nicht 🙈

Bumbum
08.04.2020, 17:04
Hallo,

kannst du mal mit einer simplen Delay-Schleife ohne Interrupts prüfen, ob der Controller wirklich auf 2 MHz läuft?

Viele Grüße
Andreas

Tux12Fun
08.04.2020, 17:32
Hallo Bumbum,
Ja das tut er bis er in den sleep mode geht

Bumbum
09.04.2020, 17:06
Hallo Tux12Fun,

ich bin mir jetzt nicht sicher ob ich dein Programm richtig verstanden habe. Im Overflow-Interrupt wird die rote LED eingeschaltet und nach dem Sleep wieder aus?

Könnte es sein, dass der Controller noch von etwas anderem wieder aufgeweckt wird? Das sollte über das Verhältnis An- und Auszeit der LED herauszufinden sein? Falls ja solltest du im Datenblatt mal die Wake-Sourcen prüfen. Wenn dies nicht möglich ist wäre eine weitere Lösung dann ein Flag im Overflow-IRQ "getoggelt". Die LED steuerst du dann nach dem Sleep über dieses Flag.

Ich würde dafür auch mal das Rücksetzen des Timers in der Hauptschleife rausnehmen. Vielleicht pfuscht dass dazwischen? Der Timer sollte sich nach einem Overflow automatisch zurücksetzen. Wenn du da zwischendurch den Timer änderst kann dein Takt nicht mehr passen.

Viele Grüße
Andreas
Viele Grüße
Andreas