mikrocontroller.net

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


Autor: oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Der kleine Niels (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.
  TCCR1A = 0x00;
  TCCR1B = (1<<WGM12) | (1<<CS12)  | (1<<CS10);  // 1024 ??

  TCNT1 = 0;
  OCR1A = 3599;

  TIMSK = (1<<OCIE1A);

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Der kleine Niels (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
denn teste doch erstmal mit einem sleep(10000).

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

Autor: oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

void main()
{
//initialisierungen uart, timer
uputs("Reset");
for(;;);
}

ISR(TIMER1_COMPA_vect)

{
  timer_seconds++;
  if(timer_seconds%10 == ((int)(timer_seconds%10)))
  {
    //temp =   (float)adc_read(0)/1024*5*350/0.03;
    //sprintf(s,"temp: %f\r\n",temp);uputs(s);
    value_dB = adc_read(0);    
    fill_fifo(value_dB, fifo_buffer);
    
    if(value_dB >  THRESHOLD_VALUE) 
    {
      if(!train_begin)
      {
        //uputs("T00000000000100000000000101EA00000001 ZUG BEGIN\r\n");
        train_begin = 1;
        //uputs(s);
      }
      if(train_begin)
      {
        sprintf(s,"T00000000000100000000000101dB%08u",fifo_buffer[0]);
        //uputs(s);
      }  
    }
    if(value_dB <= THRESHOLD_VALUE)   // fill FIFO-Buffer
    {
      train_begin = 0;
    }
  }
  if(timer_seconds == 300)  // nach 5min transmit und reset timer_seconds
  {
    uputs("    ***  5 min\r\n");
    timer_seconds == 0;
    uputs(s);
  }//300

}  // ISR



Initialisierung siehe erster beitrag

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

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

  if( timer_seconds%10 == 0 )

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
      if(!train_begin)
      {
        //uputs("T00000000000100000000000101EA00000001 ZUG BEGIN\r\n");
        train_begin = 1;
        //uputs(s);
      }
      if(train_begin)
      {
        sprintf(s,"T00000000000100000000000101dB%08u",fifo_buffer[0]);
        //uputs(s);
      }  

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

oder ist es anders gemeint als geschrieben

Autor: oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OHOH Asche über mein haupt oder wie sagt man hier....

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

Autor: oliver (Gast)
Datum:

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

dafür das train-flag

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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]

Autor: oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
stecken beide noch innerhalb eines ifs

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Machs so
    if(value_dB >  THRESHOLD_VALUE) 
    {
      if(!train_begin)
      {
        train_begin = 1;
        sprintf( s, "T00000000000100000000000101dB%08u", fifo_buffer[0]);
        uputs( s );
      }  
    }
    else
    {
      train_begin = 0;
    }

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.
#ifndef TRUE
#define FALSE 0
#define TRUE  1
#endif

...


    if( value_dB >  THRESHOLD_VALUE ) 
    {
      if( sendOverflowMessage )
      {
        sendOverflowMessage = FALSE;
        sprintf( s, "T00000000000100000000000101dB%08u", fifo_buffer[0] );
        uputs( s );
      }  
    }
    else
    {
      sendOverflowMessage = TRUE;
    }

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.