Forum: Compiler & IDEs Warum hat Timer Einfluss auf Kommunikation ?


von Andreas P. (Gast)


Lesenswert?

Hallo alle zusammen,
ich stehe mal wieder vor einem eigenartigen Problem!
Ich habe einen Atmel AT90CAN128 und sende damit LIN und CAN Nachrichten.
Die LIN Nachrichten "sollen" mittels eines Timers 
(ISR(TIMER0_COMP_vect)) der auf 100kHz eingestellt ist, alle 10ms eine 
LIN Botschaft versenden.
Wenn ich jetzt LIN Nachrichten versende MIT dem Timer, bekomme ich nur 
Errorflags. Wenn ich den Timer ausschalte und dann nochmal Nachrichten 
sende, bekomme ich alles richtig raus.
Bei CAN ist es egal ob Timer an oder aus, da kommt immer alles korrekt 
raus.

Meine Frage jetzt:
Kann es sein das der Timer soviel Reccoursen benötigt, das meine LIN 
Nachrichten nicht mehr sauber versendet werden können ?

von Peter D. (peda)


Lesenswert?

Andreas P. schrieb:
> Kann es sein das der Timer soviel Reccoursen benötigt

Was erwartest Du denn bei wahnsinns 10µs Interruptrate?
Rechne mal nach, wie wenig CPU-Zyklen das sind.

Dem CAN macht das nichts, da er das Protokoll komplett in Hardware 
macht.

So als Faustregel, ein Interrupt sollte nicht schneller als alle 500 
Zyklen aufgerufen werden.

Wenn Du 10ms brauchst, nimm auch nen 10ms Interrupt.


Peter

von Andreas P. (Gast)


Lesenswert?

Ich habe jetzt auch mal auf dem UART geschaut was dort ankommt.
Also die Daten kommen richtig am UART an!

@Peter:
Ich habe einen "Vergleichstimer", der wie folgt aufgebaut ist:
Ich habe eine 8MHz CLK, daher lasse ich den Timer bis 80 Zählen, dann 
soll in Interrupt ausgelöst werden (also 8MHz/80Schritte = 100kHz)
Ich kann aber max. bis 255 Schritte vergleichen, daher funktioniert 
deine Idee mit dem "alle 10ms" ausführen leider nicht.
Da ich den Counter auch noch für andere Zwecke nutzen möchte, muss 
dieser min. alle 1ms ausgelöst werden.

Wie kann ich den Counter "langsamer" machen, so das meine Reccursen 
nicht so ausgelastet werden.

1
void init_timer()
2
{
3
  hundert_taus_sek=0;
4
  zehn_taus_sek=0;
5
  millisekunden=0;
6
  hundert_sek=0;
7
  zehntel_sek=0;
8
  sekunde=0;
9
10
  TCCR0A =(1<<WGM01)|(1<<CS00); // CTC-> Clear Timer on Comparematch, Prescaler off
11
  OCR0A= 0x50; //bis 80 Zählen   ->100kHz (8MHz CLK)
12
  
13
14
    TIMSK0 |= (1<<OCIE0A);  //Compare Interrupt aktivieren
15
}
16
17
18
ISR(TIMER0_COMP_vect)
19
{
20
  hundert_taus_sek++;
21
  if(hundert_taus_sek==10)
22
  {
23
    zehn_taus_sek++;
24
    hundert_taus_sek=0;
25
26
    if( delay_count > 0 )  // Nachrichtenverzögerung (1/10ms)
27
    {
28
      delay_count--;
29
    }
30
31
    if(zehn_taus_sek==10)
32
    {
33
      PORTA ^= (1<<PA0);  //**********DEBUGG LED********+
34
      millisekunden++;
35
36
      zehn_taus_sek=0;
37
      if(millisekunden==10)
38
      {
39
        millisekunden=0;
40
        hundert_sek++;
41
        PORTA ^= (1<<PA2);  //**********DEBUGG LED********+
42
        if(hundert_sek==10)
43
        {
44
          hundert_sek=0;
45
          zehntel_sek++;
46
          PORTA ^= (1<<PA4);  //**********DEBUGG LED********+
47
          if(zehntel_sek==10)
48
          {
49
            zehntel_sek=0;
50
            sekunde++;
51
            PORTA ^= (1<<PA6);  //**********DEBUGG LED********+
52
53
            trigger_time++;
54
            if(sekunde == 43200) //12 Stunden
55
            {
56
              modus=3;
57
              new_file=1;
58
              sekunde=0;
59
              trigger_time=0;
60
            }
61
          }
62
        }
63
      }
64
    }
65
  }
66
}

von Karl H. (kbuchegg)


Lesenswert?

Andreas P. schrieb:

> Ich habe eine 8MHz CLK, daher lasse ich den Timer bis 80 Zählen, dann
> soll in Interrupt ausgelöst werden (also 8MHz/80Schritte = 100kHz)

80 Schritte ist schon verdammt wenig.
Das sind ungefähr 60 Assemblerinstruktionen. Davon gehen bei C schon mal 
gut und gerne 20 bis 30 für die ISR Preämbel/Ausstieg drauf, so dass 
kaum mehr was übrig bleibt. Für die ISR. Aber auch das Hauptprogramm 
muss ja auch noch arbeiten.

> Ich kann aber max. bis 255 Schritte vergleichen, daher funktioniert
> deine Idee mit dem "alle 10ms" ausführen leider nicht.

Du hast ja auch noch einen Vorteiler.

> Da ich den Counter auch noch für andere Zwecke nutzen möchte, muss
> dieser min. alle 1ms ausgelöst werden.

100kHz sind aber auch keine 1ms

von Andreas P. (Gast)


Lesenswert?

Hallo Karl heinz,

ich habe den Vorteiler ganz überlesen... habe jetzt einen Vorteiler von 
8 genommen --> 1MHz und lasse bis 100Schritte zählen was dann eine 
Interruptauslösung von 10kHz ergibt.
Jetzt funktioniert auch das versenden von LIN Nachrichten mit 
eingeschaltenem Timer !
1
TCCR0A =(1<<WGM01)|(1<<CS01); // CTC-> Clear Timer on Comparematch, Prescaler 8 ---> 8.000.000 / 8 = 1MHz
2
OCR0A= 0x64; //bis 100 Zählen   ->10kHz (8MHz CLK)

Ich werde die Auslösezeit trotzdem noch runterschrauben um auf der 
sicheren Seite zu sein.

!!!!!!! DANKE MAL WIEDER FÜR EURE HILFE !!!!!!!!!!!

Gruß Andreas P.

von Karl H. (kbuchegg)


Lesenswert?

Andreas P. schrieb:

> Ich werde die Auslösezeit trotzdem noch runterschrauben um auf der
> sicheren Seite zu sein.

Und noch was.
Kein Mensch sagt, dass du die ISR in 10-er Bruchteilen aufrufen musst.
Da du dann sowieso noch einen Software-Teiler hinten nachschaltest, 
kannst du anstelle von alle 100-Timer Schritte ja auch alle 200 Timer 
Schritte die ISR auslösen lassen.
In der ISR zählst du dann eben nicht bis 100 sondern nur bis 50 um die 
weiteren Aktionen auslösen zu lassen und hast dann für die 
Aktionsauslösung immer noch dasselbe Timing. Aber mit nur der Hälfte der 
ISR Aufrufe.

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.