Forum: Compiler & IDEs 16 Bit Timer läuft nicht an


von Gizmo (Gast)


Lesenswert?

Hi

Ich möchte den 16 Bit Timer des ATMEGA32 zum laufen bekommen, aber 
irgendwie springt das ding nicht an.

Der Timer soll im CTC Mode mit Prescaler 1024 arbeiten.

Hier ist mal meine Initialisierungs Routine:


void initTimer1(void)
{
  /*Prescaler 1024*/
//  TCCR1B |= (1<<CS12) | (1<<CS10);

  TCCR1A = 0x00;
  TCCR1B |= (1<<CS12); // CTC-Mode Prescale 1024 (15625)
  OCR1AH = ( (15625/5) >> 8 );
  OCR1AL = ( (15625/5) & 0x00FF );
  TIMSK |= (1<<OCIE1B);


}

Hier die Interrupt Routine:



ISR (SIG_OUTPUT_COMPARE1A)
{


  unsigned char counter;
  for(counter = 0; counter < (sizeof(time_counter_)/sizeof(unsigned 
int)); counter++)
  {
    if(time_counter_[counter] > 1) time_counter_[counter]--;
  }


  //  sprintf(led_blink_buffer, "%s\n\r" ,led_blink);
  //  usartPuts(led_blink_buffer);
  return;
}

Es wäre sehr nett, wenn ihr mir helfen könntet.


Gruß Gizmo

von Johannes M. (johnny-m)


Lesenswert?

Gizmo wrote:
> Hier ist mal meine Initialisierungs Routine:
> [...]
>   TIMSK |= (1<<OCIE1B);
> [...]
>
> Hier die Interrupt Routine:
>
> ISR (SIG_OUTPUT_COMPARE1A)
Fällt Dir da nichts auf?

Abgesehen davon sollte man die "neuen" Vektornamen verwenden.

Und den Einzelzugriff auf die H- und L-Register mit dem ganzen 
Bitgeschiebe macht man in C auch nicht, dafür gibt es die 
16-Bit-Zugriffe, bei denen der Compiler einem auch noch die Sache mit 
der korrekten Zugriffsreihenfolge abnimmt (die bei Dir aber [zufällig?] 
korrekt ist).

Also:
1
OCR1A = 15625/5;

Laufen wird der Timer wohl schon, nur merkst Du nichts davon. Ich gehe 
auch mal davon aus, dass die globale Interrupt-Freigabe irgendwo anders 
gemacht wird...

von Gizmo (Gast)


Angehängte Dateien:

Lesenswert?

Hi Johannes

erst mal danke für die schnelle Antwort.

die globalen Interrupts werden bei mir vor der Hauptschleife
per sei() aktiviert.

ich habe mir eine Testroutine für den Timer geschrieben in der das TOV1 
Flag im TIFR Register abfrage.

Hier mal die Test Routine:

void timer1test(void)
{
/*  char timer1_overflow_buffer[50];
  char timer1_overflow_flag_set[10] = "1";
  char timer1_overflow_flag_not_set[10] = "0";*/

  if(TIFR & (1<<TOV1))
  {
    PORTB |= (1<<PORTB4);

    //sprintf(timer1_overflow_buffer, "TOV1 = %s\n\r" 
,timer1_overflow_flag_set);
    //usartPuts(timer1_overflow_buffer);
  }
  else
  {
    PORTB &= ~(1<<PORTB4);

    //sprintf(timer1_overflow_buffer, "TOV1 = %s\n\r" 
,timer1_overflow_flag_not_set);
    //usartPuts(timer1_overflow_buffer);
  }
}

diese Routine wird in der Hauptschleife aufgerufen, wird aber nie 
aufgerufen, dass heißst der Timer läuft nicht.

Wie meinst du das mit den 16-Bit Zugriffen ? Ich kenne dass nur über 
Bitschieberei. Hast da vielleicht n stück Code für mich ? das ich mir 
mal anschauen kann, wie du das machst ?

Ich hänge auch mal mein ganzes c File an.1

von Werner B. (werner-b)


Lesenswert?

1. Du gibt den OCIE1B Interrupt frei, aber deine ISR ist für den OCIE1A

2. Wenn der Timer im CTC Modus läuft, läuft er nie über, sondern wird 
beim Match auf 0 zurückgesetzt. Darum kann nie das TOV Flag

von Johannes M. (johnny-m)


Lesenswert?

Werner B. wrote:
> 1. Du gibt den OCIE1B Interrupt frei, aber deine ISR ist für den OCIE1A
Tja, eigentlich hatte ich gehofft, dass Gizmo den Hinweis in meinem 
ersten Posting versteht... War doch eigentlich ein Wink mit dem 
Zaunpfahl.

> 2. Wenn der Timer im CTC Modus läuft, läuft er nie über, sondern wird
> beim Match auf 0 zurückgesetzt. Darum kann nie das TOV Flag
Doch, schau mal in den betreffenden Tabellen im Datenblatt nach. Das TOV 
wird auch im CTC-Betrieb gesetzt.

EDIT:
Sorry, hab noch mal zur Sicherheit nachgesehen: In den CTC-Betriebsarten 
wird das TOV tatsächlich nicht gesetzt, wenn OCRnx nicht gleich MAX 
ist (nur in den PWM-Betriebsarten sieht das z.T. anders aus). Allerdings 
gebietet eigentlich allein die Logik, das Compare-Flag abzufragen...

von Stefan E. (sternst)


Lesenswert?

Johannes M. wrote:

>> 2. Wenn der Timer im CTC Modus läuft, läuft er nie über, sondern wird
>> beim Match auf 0 zurückgesetzt. Darum kann nie das TOV Flag
> Doch, schau mal in den betreffenden Tabellen im Datenblatt nach. Das TOV
> wird auch im CTC-Betrieb gesetzt.

Jein. TOV wird bei MAX gesetzt, aber MAX wird gar nicht erreicht, außer 
du manipulierst den Zählerstand "von Hand". Lässt du den Zähler "in 
Ruhe" im CTC-Modus laufen, wird TOV nicht gesetzt.

Nur so nebenbei: der OP lässt den Zähler gar nicht im CTC-Modus laufen, 
auch wenn es im Kommentar steht.

von Johannes M. (johnny-m)


Lesenswert?

Stefan Ernst wrote:
> Jein. TOV wird bei MAX gesetzt, aber MAX wird gar nicht erreicht, außer
> du manipulierst den Zählerstand "von Hand". Lässt du den Zähler "in
> Ruhe" im CTC-Modus laufen, wird TOV nicht gesetzt.
Jupp, siehe EDIT oben...

von Gizmo (Gast)


Angehängte Dateien:

Lesenswert?

ich habe jetzt mal die sachen die euch aufgefallen sind entsprechend 
abgeändert, aber der Timer läuft immer noch nicht. Ich hänge noch einmal 
den auktuelen code an.
Was vielleicht wichtig ist der ATMEGA32 läuft mit internem Oszilator mit 
8 Mhz.

Ich danke euch

gruß Gizmo

von Stefan E. (sternst)


Lesenswert?

Wie soll er auch laufen, wenn du initTimer1 nicht aufrufst.

von Johannes M. (johnny-m)


Lesenswert?

Gizmo wrote:
> ich habe jetzt mal die sachen die euch aufgefallen sind entsprechend
> abgeändert,
Nö, hast Du nicht!
1
  OCR1AH = ( (15625/5) >> 8 );
2
  OCR1AL = ( (15625/5) & 0x00FF );
ist immer noch so umständlich wie vorher. Und den alten Vektornamen hast 
Du auch noch drin
1
ISR (SIG_OUTPUT_COMPARE1A)

Und wenn Du glaubst, die 1000 Leerzeilen in Deinem Code wecken in mir 
große Lust, mir das Programm mal genauer anzusehen, dann liegst Du 
leider falsch... Ich bin kein Masochist.

EDIT:
OK, ich sehe, Stefan hat sich tatsächlich die Mühe gemacht...

von Gizmo (Gast)


Lesenswert?

so der Timer läuft jetzt.
Der Fehler lag an folgender Programmzeile:

TCCR1B |= (1<<CS12) | (1<<CS10) | (1<<WGM12); // CTC-Mode Prescale
1024(15625)

man darf aber nich verodern.

so ist es richtig:
TCCR1B = (1<<CS12) | (1<<CS10) | (1<<WGM12); // CTC-Mode Prescale 1024 
(15625) richtig

der laufende Code ist im Anhang enthalten.

Das Shiften finde ich persöhnlich besser da es allgemein gehalten ist

Gruß Gizmo

von Johannes M. (johnny-m)


Lesenswert?

Gizmo wrote:
> TCCR1B |= (1<<CS12) | (1<<CS10) | (1<<WGM12); // CTC-Mode Prescale
> 1024(15625)
>
> so ist es richtig:
> TCCR1B = (1<<CS12) | (1<<CS10) | (1<<WGM12); // CTC-Mode Prescale 1024
> (15625) richtig
Wenn das Register vorher jungfräulich ist (Reset-Zustand), dann macht 
das keinen Unterschied.

> Das Shiften finde ich persöhnlich besser da es allgemein gehalten ist
Hä??? Muss ich nicht verstehen, oder?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.