Ich versuche, den Timer0-Überlauf-Interrupt zu verwenden, um ein kleines Projekt zu erstellen. Ich habe einen solchen Timer im ATtiny45 verwendet und es hat funktioniert, aber mit ATtiny10 kein Ergebnis.
Also habe ich ein einfaches LED-Blinkprogramm ausprobiert und selbst das hat nicht funktioniert.
Hier ist der einfache Code:
#define F_CPU 1000000UL // 1 MHz
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
volatile uint16_t overflow_val=0;
ISR (TIMER0_OVF_vect){
overflow_val++;
}
int main(void){
DDRB = (1<<PB1);
// Timer0 normal mode
TCCR0A = 0x00;
// Start timer with presc 1:1024
TCCR0B = (1<<CS02) | (1<<CS00);
TCNT0 = 0;
TIMSK0 |= (1 << TOIE0);
sei();
for(;;){
if(overflow_val >= 1)
{
if(TCNT0 >= 145){
PORTB ^= (1 << PB1);
TCNT0 = 0;
overflow_val = 0;
}
}
}
return 0;
}
Hoffe jemand kann mir helfen. Danke!
EDIT1:
Ich habe die Linie gewechselt
TCCR0B = (1<<CS02) | (1<<CS00);
zu Linie
TCCR0B = (1 << CS01); // clk/8
in meinem Code, um alle 0,524 Sekunden einen Überlauf zu erreichen. Aber die LED blinkt überhaupt nicht.
EDIT2:
Hier ist die Größe:
>avr-size test_attiny10_2.ino.elf
text data bss dec hex filename
138 0 2 140 8c test_attiny10_2.ino.elf
EDIT3:
Ich habe meine if-Anweisung im Wesentlichen wie folgt geändert:
int main(void){
...
TCCR0B = (1 << CS01);
...
for(;;){
if(TCNT0 >= 0xFFFE)
{
PORTB ^= (1 << PB1);
TCNT0 = 0;
}
}
return 0;
}
Jetzt blinkt meine LED alle 0,524 Sekunden, wie es sollte!
Also stimmt etwas mit meiner flüchtigen unit16_t Variablen overflow_val nicht . Ich habe es nicht nur direkt auf Hardware getestet, sondern auch eine Simulation mit atmelstudio durchgeführt. Auch in der Simulation tritt das Programm nie in die if-Anweisung ein, wenn ich die Variable overflow_val zum Umschalten der LED verwende.
BEARBEITEN 4
Ich glaube, irgendwas stimmt mit meiner ISR fkt nicht. Ich habe den folgenden Code getestet und die LED nie eingeschaltet.
#define F_CPU 1000000UL // 1 MHz
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
volatile uint8_t ovf_counter = 0;
void ioinit(void){
// PB1->outputs
DDRB = (1<<PB1);
// Start timer with presc 1:64
TCCR0B = (1<<CS01) | (1<<CS00);
// Initialize counter Overflow at 0xFFFF
TCNT0 = 0;
// Enable global interrupts
sei();
}
int main(void){
ioinit();
TIMSK0 |= (1<<TOIE0);
while(1){
if(ovf_counter>=2){
PORTB = (1<<PB1);
ovf_counter=0;
}
}
}
ISR(TIMER0_OVF_vect){
ovf_counter++;
TCNT0 = 0;
}
Ich weiß nicht, was falsch ist.
Wenn ich in der While(1) -Schleife den Status des Zählerregisters TCNT0 überprüfe, funktioniert es. Der Zähler läuft also wie vorgesehen über, tritt aber bei einem Überlaufereignis niemals in die ISR(TIMER0_OVF_vect) -Funktion ein.
Ich habe meinen Fehler gefunden. Ich benutzte:
ISR(TIMER0_OVF_vect){. . .}
anstatt
ISR(TIM0_OVF_vect){. . .}
Jetzt funktioniert es! Beim Überlauf von Timer0 wird die Interrupt-Routine ausgeführt. Vielen Dank für Ihre Hilfe
Es kann ähnlich aussehen, aber ATtiny45 Timer/Counter0 ist 8-Bit (es muss bis 256 + 1 für den Überlauf zählen), so dass der Prescaler 1024 beispielsweise beim Warten auf den Überlauf-Interrupt bei CLK = 1 MHz etwa 0,26 Sekunden benötigt.
ATtiny10 Timer/Counter0 ist 16-Bit (zählt bis 65536). Für die gleichen Einstellungen wie oben (1 MHz Takt, Prescaler 1024) gibt es 256 mal 0,26 Sekunden = fast 67 Sekunden bis zum Überlauf (wie von Bigjosh erwähnt).
Filo
C_Elegans
Großer Josch
Scott Seidmann
Tom Tischler
sei();
Anruf macht das.sepphans
Scott Seidmann
sepphans