ATmega32 & timer (in C)

Hi
Ich möchte einen Timer verwenden, um sekunden zu zählen.
Zu Testzwechen lasse (würde ich gerne) eine LED mit 0,5Hz blinken lassen.

Code:
#ifdef F_CPU
#undef F_CPU
#endif
#define F_CPU  (1000000*16)

#include <avr/io.h>
#include <avr/interrupt.h>

#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--;
 }
}

Funktioniert leider nicht...
aber WARUM??

ps.: ATmega32 läuft mit 16MHz
 
0,5Hz sind 2 Sekunden...das wären dann 2000 Millisekunden, nicht 50000. ;)
 
Hm, Redeagle,
Ich habe weder die Definition noch die Deklaration der Interruptroutine
in Deinem Code gefunden.
Muss nicht in dieser die Zählvariable runtergezählt
werden?

Was benutzt Du für 'nen Compiler?
Siehst Du beim Compilieren 'ne Fehlermeldung?

Golgotha.
 
1. "SIGNAL (SIG_OUTPUT_COMPARE1A)" wird beim interrupt ausgeführt
2. Es gibt keine Fehler beim Kompilieren
3. Ich habe nur zum Testen verwendet...

... den Das Problem: Die LED's blinken viel zu schnell.
(und damit meine ich "sie leuchte nur ganz schwach" - zuschnell)

Compiler avr-gcc
 
wie sieht denn die beschaltung des ports aus? haben solche controler einen internen pull up widerstand? sonst würde der port floaten und dann kanns schon mal sein dass da irgend was raus kommt.

edit: zur erklärung: ein pull up widerstand zeigt dem uC wie hoch die spannung an einem port sein soll. das heißt den widerstand hängt man auf VCC bzw auf eine spannung, die der port liefern soll. somit ist der port zwar dann standardmäßig auf high, aber das kann man ja dann im porgramm einfließen lassen.
 
Jo, es sind standardmäßig pull-up - widerstände vorhanden.

Wenn ich ohne interrupts arbeitre (also mit zeitschleifen) geht das auch alles...
Da ich aber neben einer blinkenden LED noch ne menge anderer daten verarbeiten muss, muss ich das Blinken eben per timer&interrupt machen...

ps.: die Hartware ist OK, habe den timer auch schon in BASIC benutzt, möchte nur diesmal mit C arbeiten...
 
Dein Code sieht so aus, als hättest du das Prinzip der Timer im AVR Design noch nicht wirklich verstanden, sry ;)

Du kannst eine LED wie in deiner MAIN mit einer Endlosschleife/warten realisieren und nutzt für deine SLEEP Funktion die funktionen _delay_loop_2() aus per #include <util/delay.h> (Achtung, lies die AVRLibc Doku im WinAVR Verzeichnis für diesen Befehl, eine ganze Sekunde geht nur mit mehren Aufrufen!). Dadurch ist der qC zu 100% mit Nichtstun ausgelastet, nicht so prikelnd :rolleyes:

Du kannst aber Timer nutzen, damit kannst du eine Led blinken lassen und gleichzeitig was anderes machen, z.B. Berechnungen. Denn Timer sind in extra Hardwareblöcken und werden nur per Timer-Registern konfiguriert und laufen dann von allein. Um die LED so langsam zu schalten, müsstest du aber ein wenig cheaten, nämlich mit einem Interrupt für den Timer, in dem ein zusätzlicher 16Bit Zähler hochgezählt wird. Timer sind nämlich eigentlich für Frequenzgeneration gedacht, die parallel zur normalen qC Ablauf laufen soll.

Ich empfehle dir mal bei www.mikrocontroller.net vorbeizuschauen, eine wirklich bemerkenswert gute Seite für AVR, ARM, MSP und alles was programmierbar ist und Pins hat ;-)
 
Das Prinzip habe ich schon verstanden...
Ich kämpfe nur damit, das nirgends (selbst bei Atmel) beschrieben steht, wofür die einzelnen register zuständig sind...

Da es sich bei dem Programm um ein Schulprojekt handelt das am 16.01 fertig sein muss, bin ich jetzt aus Basic umgestiegen, da Funktionierts

ps.: es leigt wahrscheinlich nicht am code... Ich habe meinen Kompiler dabei erwischt, wie er manchmal die Interrupt-routine nicht mitkompiliert hat... (warum weiß ich auch nicht)

trotzem danke für eine mühen
 
Dann druck dir in der Schule mal das zugehörige Manual zum ATMEGA32 aus. Das ist wirklich nützlich mal was "in der Hand" zu haben.

Viel Erfolg mit dem Projekt, finde ich gut, dass sowas in der Schule behandelt wird!
 
Zurück
Oben