AVR timer1 faktor 10 zu schnell

Gast #1697607
hi leute.
Mein timer 1 läuft auf einem ATMEGA 32 mit 3,6864MHz im CTC Mode.

Hier die initialisierung:

void timer1_init()
{
  TCCR1A = 0x00;
  TCCR1B = (1<<WGM12) | (1<<CS12)  | (1<<CS10);  // 1024 ??
  TCNT1H = 0;
  TCNT1L = 0;
  OCR1AH = ((3599) >> 8);
  OCR1AL =  (3559);
  TIMSK = (1<<OCIE1A);
}

leider erhalte ich genau den Faktor 10. zu schnell!!

Meine Berechnung für OCR1 ist: (1s*F_CPU/prescaler)-1

gibts Ideen, woran es liegen könnte?
Im Code ist erst mal so kein Fehler erkennbar, ausser der von Nils 
etdeckte Ziffernsturz. Aber der macht keinen Faktor 10 aus.

Auch die Berechnung stimmt.

Ev. ein Messfehler? Wie gehts weiter? In welchem Umfeld benutzt du den 
Code?

Die Gefahr von unterschiedlichen Zahlen bei der Zuweisung an High und 
Low Register kannst du vermeiden, indem du die Aufdröselung den Compiler 
machen lässt.
1
  TCCR1A = 0x00;
2
  TCCR1B = (1<<WGM12) | (1<<CS12)  | (1<<CS10);  // 1024 ??
3

4
  TCNT1 = 0;
5
  OCR1A = 3599;
6

7
  TIMSK = (1<<OCIE1A);
Persönliche Seite
oliver schrieb:

> Mein timer 1 läuft auf einem ATMEGA 32 mit 3,6864MHz im CTC Mode.
>
> Hier die initialisierung:
>
> void timer1_init()
> {
>   TCCR1A = 0x00;

OK.

>   TCCR1B = (1<<WGM12)

Table 47
4 0 1 0 0 CTC OCR1A Immediate MAX

OK.

> | (1<<CS12)  | (1<<CS10);  // 1024 ??

Table 48
1 0 1 clkI/O/1024 (From prescaler)

OK.

>   TCNT1H = 0;
>   TCNT1L = 0;

OK.

>   OCR1AH = ((3599) >> 8);
>   OCR1AL =  (3559);
                 ^
n. OK.

OCR1A Wert um alle 1s einen Timer/Counter1, Output Compare A Match 
Interrupt zu bekommen: 3686400 / 1024 - 1 = 3599

>   TIMSK = (1<<OCIE1A);

OK.

> leider erhalte ich genau den Faktor 10. zu schnell!!

Wie gemessen? Bist du sicher, dass die nicht im Code gezeigte ISR 
angesprungen wird und nicht der AVR sich alle 100ms resettet?
Der kleine Niels schrieb:
> Da fällt mir auf:
> 3,6864MHz klingt nach STK500 Takt... liegt vielleicht dort der Hund
> begraben?

Hab ich mir auch schon gedacht.
Aber spielen wir das mal durch.
Bei einem Faktor von 10, selbst wenn man nicht rechnet, müsste die 
CPU-Frequenz dann entweder 368kHz oder 36Mhz sein.
Das eine ist zu klein, das andere zu gross. 368kHz würde die CPU zwar 
noch mitmachen, aber ob sie mit 36Mhz noch läuft, bezweifle ich mal.

Faktor 10 ist aber auch ein ungewöhnlicher Faktor.
Gast
der Controller läuft definitiv mit externem takt lt fuses.

gemessen, naja, ich habe eine serielle ausgabe, die mir halt jede 
sekunde etwas anzeigt, anstatt alle 10s.

Desweiteren habe ich keinen Reset, da ich diesen am anfang der main per 
RST ausgeben lasse, dies funktioniert auch gut z.b. per resetknopfdruck.

also: kein reset!
Gast
ich arbeite mit einem externen Takt von 3,6864MHz.

Die Baudraten, die ich bisher und jetzt auch! daraus errechne, 
funktionieren super! D.H., der Takt ist wohl sauber!
Gast
1
void main()
2
{
3
//initialisierungen uart, timer
4
uputs("Reset");
5
for(;;);
6
}
7

8
ISR(TIMER1_COMPA_vect)
9

10
{
11
  timer_seconds++;
12
  if(timer_seconds%10 == ((int)(timer_seconds%10)))
13
  {
14
    //temp =   (float)adc_read(0)/1024*5*350/0.03;
15
    //sprintf(s,"temp: %f\r\n",temp);uputs(s);
16
    value_dB = adc_read(0);    
17
    fill_fifo(value_dB, fifo_buffer);
18
    
19
    if(value_dB >  THRESHOLD_VALUE) 
20
    {
21
      if(!train_begin)
22
      {
23
        //uputs("T00000000000100000000000101EA00000001 ZUG BEGIN\r\n");
24
        train_begin = 1;
25
        //uputs(s);
26
      }
27
      if(train_begin)
28
      {
29
        sprintf(s,"T00000000000100000000000101dB%08u",fifo_buffer[0]);
30
        //uputs(s);
31
      }  
32
    }
33
    if(value_dB <= THRESHOLD_VALUE)   // fill FIFO-Buffer
34
    {
35
      train_begin = 0;
36
    }
37
  }
38
  if(timer_seconds == 300)  // nach 5min transmit und reset timer_seconds
39
  {
40
    uputs("    ***  5 min\r\n");
41
    timer_seconds == 0;
42
    uputs(s);
43
  }//300
44

45
}  // ISR

Initialisierung siehe erster beitrag
Gast
1
      if(!train_begin)
2
      {
3
        //uputs("T00000000000100000000000101EA00000001 ZUG BEGIN\r\n");
4
        train_begin = 1;
5
        //uputs(s);
6
      }
7
      if(train_begin)
8
      {
9
        sprintf(s,"T00000000000100000000000101dB%08u",fifo_buffer[0]);
10
        //uputs(s);
11
      }

das geht auch etwas lesbarer
1
      if(!train_begin)
2
      {
3
        //uputs("T00000000000100000000000101EA00000001 ZUG BEGIN\r\n");
4
        train_begin = 1;
5
        //uputs(s);
6
      }
7
      sprintf(s,"T00000000000100000000000101dB%08u",fifo_buffer[0]);
8
      //uputs(s);

oder ist es anders gemeint als geschrieben
Gast
aber das 2.If ist ja dann immer wahr, damit braucht du es nicht

[c]
      if(!train_begin)
      {
        //uputs("T00000000000100000000000101EA00000001 ZUG BEGIN\r\n");
        train_begin = 1;
        //uputs(s);
      }
      if(train_begin)
[\c]
Machs so
1
    if(value_dB >  THRESHOLD_VALUE) 
2
    {
3
      if(!train_begin)
4
      {
5
        train_begin = 1;
6
        sprintf( s, "T00000000000100000000000101dB%08u", fifo_buffer[0]);
7
        uputs( s );
8
      }  
9
    }
10
    else
11
    {
12
      train_begin = 0;
13
    }

dann klappts auch mit dem 'nur einmal ausgeben'.

Das else ist ein deutliches Indiz, dass der von ihm abhängige Teil in 
irgendeiner Form mit dem if davor verknüpft ist und das man diese beiden 
Ausführungspfade in ihrer Gesamtheit sehen muss um zu verstehen was da 
vor sich geht. Lass dir diese 'Dokumentationsmöglichkeit' nicht 
entgehen, sie hat nur Vorteile. Schon alleine der Umstand, dass die 2-te 
Bedingung damit automatisch das Gegenteil von der ersten ist, ohne dass 
du sie hinschreiben musst, ist den Minderaufwand schon wert.

Wenn du die Variable dann auch noch 'sendOverflowMessage' oder so 
ähnlich nennst, dann kann man das auch lesen. Sonst fragt sich jeder, 
wie da jetzt ein Zug ins Spiel kommt und ob da wohl der ICE damit 
gemeint ist.
1
#ifndef TRUE
2
#define FALSE 0
3
#define TRUE  1
4
#endif
5

6
...
7

8

9
    if( value_dB >  THRESHOLD_VALUE ) 
10
    {
11
      if( sendOverflowMessage )
12
      {
13
        sendOverflowMessage = FALSE;
14
        sprintf( s, "T00000000000100000000000101dB%08u", fifo_buffer[0] );
15
        uputs( s );
16
      }  
17
    }
18
    else
19
    {
20
      sendOverflowMessage = TRUE;
21
    }

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 16 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.