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.
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.