AVR timer1 faktor 10 zu schnell

Gast #1697607
Lesenswert?

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?
#1697624
Lesenswert?

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 #1697626
Lesenswert?

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?
#1697639
Lesenswert?

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 #1697690
Lesenswert?

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 #1697699
Lesenswert?

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 #1697712
Lesenswert?

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 #1697726
Lesenswert?

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]
#1697736
Lesenswert?

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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren