Forum: Mikrocontroller und Digitale Elektronik AVR timer1 faktor 10 zu schnell


von oliver (Gast)


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?

von Der kleine Niels (Gast)


Lesenswert?

ich hab nix gerechnet, aber da steht einmal 3599 und einmal 3559... 
vielleicht ists das?

von Karl H. (kbuchegg)


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);

von Stefan B. (stefan) Benutzerseite


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?

von Der kleine Niels (Gast)


Lesenswert?

Da fällt mir auf:
3,6864MHz klingt nach STK500 Takt... liegt vielleicht dort der Hund 
begraben?

von Karl H. (kbuchegg)


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.

von oliver (Gast)


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!

von Karl H. (kbuchegg)


Lesenswert?

oliver schrieb:
> 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.

Moment.
Du willst 10 Sekunden?

Zeig doch mal das komplette Programm

von oliver (Gast)


Lesenswert?

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!

von Peter (Gast)


Lesenswert?

denn teste doch erstmal mit einem sleep(10000).

sende('test1\n');
sleep(10000);
sende('test2\n');

von oliver (Gast)


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

von Karl H. (kbuchegg)


Lesenswert?

Und was denkst du, soll das hier
1
  if(timer_seconds%10 == ((int)(timer_seconds%10)))
machen?
Das ist für jede beliebige Zahl in timer_seconds immer wahr

1
  if( timer_seconds%10 == 0 )

von Peter (Gast)


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

von oliver (Gast)


Lesenswert?

OHOH Asche über mein haupt oder wie sagt man hier....

modulo gibt mir immer einen int zurück....

von oliver (Gast)


Lesenswert?

ich wollte mir nen flag setzen, damit ich bei grenzwertüberschreitung 
ein spezielles protokoll versende (einmalig)

dafür das train-flag

von Peter (Gast)


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]

von oliver (Gast)


Lesenswert?

stecken beide noch innerhalb eines ifs

evlt könnte ich auch zwei bedinungen (grenzwertüberschreitung und flag) 
innerh. eines ifs abfragen

von Karl H. (kbuchegg)


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
    }

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.