-
Problem mit timer
Ich möchte mit einem ATmega32 (bei 16MHz) eine LED blinken lassen.
Dazu habe ich den code von Roboternetz genommen und leicht verändert.
Allerdings blinken die LEDs nicht im Sekundentakt:
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#ifndef F_CPU
#define F_CPU (1000000*16) //Die *16 wurden von mir hinzugefügt
#endif
#define IRQS_PER_SECOND 2000 /* 500 µs */
#define IRQS_PER_10MS (IRQS_PER_SECOND / 100)
///////////////////////////////////////////////////////////////////////////////////////////////
static volatile uint8_t timer_10ms;
void timer1_init();
void wait_10ms (const uint8_t);
////////////////////////////////////////////////////////////////////////////////////////////////
void main()
{
uint16_t i,j,k,l; //zähler
DDRC = 0xFF;//An C liegen die LEDs
PORTC = 0x02;//LEDs aus
DDRA = 0xFF;
PORTA= 0x00;
DDRB = 0xFF;
PORTB= 0x00;
DDRD = 0xFF;
PORTD= 0x00;
timer1_init();
sei();
while (1)
{
// LED an
PORTC |= 0xF0;
// 1 Sekunde warten
for(l=0; l<0xFFFF; l++){
for(k=0; k<0xFFFF; k++){
for(j=0; j<0xFFFF; j++){
for(i=0; i<0xFFFF; i++){ wait_10ms (255);
}}}}
// LED aus
PORTC &= 0x0F;
// 1 Sekunde warten
for(l=0; l<0xFFFF; l++){
for(k=0; k<0xFFFF; k++){
for(j=0; j<0xFFFF; j++){
for(i=0; i<0xFFFF; i++){ wait_10ms (255);
}}}}
}
return;
}
//-----------------------------------------------------------------------------------------------
void timer1_init()
{
TCCR1A = 0;
#if defined (CTC1) && !defined (WGM12)
TCCR1B = (1 << CTC1) | (1 << CS10);
#elif !defined (CTC1) && defined (WGM12)
TCCR1B = (1 << WGM12) | (1 << CS10);
#endif
OCR1A = (unsigned short) ((unsigned long) F_CPU / IRQS_PER_SECOND-1);
#if defined (TIMSK1)
TIMSK1 |= (1 << OCIE1A);
#elif defined (TIMSK)
TIMSK |= (1 << OCIE1A);
#endif
}
//-----------------------------------------------------------------------------------------------
void wait_10ms (const uint8_t t)
{
timer_10ms = t;
while (timer_10ms);
}
/////////////////////////////////////////////////////////////////////////
SIGNAL (SIG_OUTPUT_COMPARE1A)
{
static uint8_t interrupt_num_10ms;
if (++interrupt_num_10ms == IRQS_PER_10MS)
{
interrupt_num_10ms = 0;
if (timer_10ms != 0)timer_10ms--;
}
return;
}
wo istz das Problem??
-
Hi...
Keiner ne idee?? Bin schon die ganze zeit am suchen...
derzeitiger stand
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#ifdef F_CPU
#undef F_CPU
#endif
#define F_CPU (1000000*16)
#define MHZ *1000000
// und IRQS_PER_SECOND ein Vielfaches von 100.
// Ausserdem muss gelten F_CPU / IRQS_PER_SECOND <= 65536
#define IRQS_PER_SECOND 1000
// Anzahl IRQs pro 10 Millisekunden
#define IRQS_PER_10MS (IRQS_PER_SECOND / 100)
///////////////////////////////////////////////////////////////////////////////////////////////
// Zähler-Variable. Wird in der ISR erniedrigt und in wait_10ms benutzt.
static volatile uint16_t timer;
// Prototypen
void timer1_init();
void wait (const uint16_t);
////////////////////////////////////////////////////////////////////////////////////////////////
void main()
{
DDRC = 0xFF;//An C liegen die LEDs
PORTC = 0x02;//LEDs aus
// Timer1 initialisieren
timer1_init();
// Interrupts aktivieren
sei();
while (1)
{
// LED an
PORTC |= 0xF0;
// 1 Sekunde warten
wait(50000);
// LED aus
PORTC &= 0x0F;
// 1 Sekunde warten
wait(50000);
}
return;
}
//-----------------------------------------------------------------------------------------------
void timer1_init()
{
// Timer1: keine PWM
TCCR1A = 0;
TCCR1B = (1 << WGM12) | (1 << CS10);
OCR1A = (unsigned short) ((unsigned long) (16 MHZ) / IRQS_PER_SECOND - 1);
TIMSK |= (1 << OCIE1A);
}
//-----------------------------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
void wait(const uint16_t t)
{
timer = t;
while (timer);
}
////////////////////////////////////////////////////////////////////////
SIGNAL (SIG_OUTPUT_COMPARE1A)
{
static uint8_t interrupt_num;
if(++interrupt_num == IRQS_PER_SECOND/100) //eine Zeiteinheit vergangen (10ms/100ms)
{
interrupt_num = 0;
if(timer != 0)timer--;
}
}
warum funktioniert das nicht??
-
Die 4-fach-Schleife durchläuft (2^16)^4 = 1.8e19 mal die wait_10ms (255).
wait_10ms (255) wartet 255*10ms also 2.55 Sekunden.
Insgesamt wartet die 4-Schleife also 4.7e19 Sekunden = ca. 1.5e12 Jahre, das ist etwa das 300-fache Alter der Erde...
-
Darauf bib ich auch gekommen.
Aber warum blinken die LEDs dann so schnell, das es wie schwaes leuchten aussieht??
=> weit_10ms wartet keine 10ms, sondern nur ein bruchteil, aber warum??
-
Falls Du Optimierungen eingeschaltet hat, wird der Compiler Dir Deine while-Schleife wegoptimieren.
-
Ich seh nicht, daß da was wegoptimiert wird.
Versuch mal die Klammer um #define F_CPU wegzulassen. Bzw funktioniert der Originalcode? Mit 16MHz-Quarz sollte der flott aber noch erkennbar blinken. Ansonsten nur die 1000000 durch ne 16000000 ersetzen.
Funktioniert der Beispielcode von
https://www.roboternetz.de/wissen/in...n_f%C3%BCr_AVR
?
Zuden gibt es einen Fehler inder wait (uint16_t)
https://www.roboternetz.de/wissen/in...-atomarer_Code
-
Ja, aber so wie der Code aussieht werden die LEDs nur per wait im Zeitverhalten gesteuert. Der Timerinterrupt hat da keine Auswirkungen.
wait() wartet in der jetzigen Implementierung natürlich ewig.