Forum: Mikrocontroller und Digitale Elektronik PIC18F458 CAN-BUS


von Matthias W. (macho2000)


Lesenswert?

Hallo zusammen,
ich arbeite zur Zeit an einem Projekt, welches verschiedenste Messdaten 
auf einem LCD-Display grafisch darstellt. Die Daten werden über I2C, 
1-wire und CAN übertragen. Soweit funktionieren auch alle einzel 
Komponenten fehlerfrei, nur habe ich jetzt im Zusammenspiel ein 
Konzeptionelles Problem.

Die Hardware:

- PIC18F458 @ 20MHz
- 1-wire: DS18S20 für die Temperatur
- I2C: DS1337 als Uhr, MCHP24FC1024 zur Datenspeicherung
- CAN: im Moment noch ein CAN Entwicklungswerkzeug, später aber ein 2ter 
PIC der im ca. 10ms Raster Messdaten liefert (3 Botschaften) und 
zufälliger Steuerkomandos, CAM Routinen nach AN738

Das aktuelle Konzept:

In meiner Hauptschleife werden der I2C Bus und der DS1820 ausgelesen und 
das LCD mit allen dargestellten Messwerten einmal aktualisiert! Ein 
Durchlauf dauert ca.90ms. Die CAN-Messdaten sind in globalen Variablen 
gespeichtert. Kommt eine neue Botschaft, so wird ein Interrupt ausgelöst 
und die Botschaft in die entschrechenden Variablen zerlegt! Das Display 
zeigt also immer den Inhalt der letzten Botschaft, egal viel Botschaften 
während der 90ms angekommen sind.

Nun das Problem:

Eine Unterbrechung des Programms durch den Interrut ist kritisch wenn zB 
das Software 1-Wire Protokoll(ca.10ms)läuft. Daher habe ich mir gedacht, 
ich verbiete die Interrupts wärend diesem Programmabschnitt, wohl 
wissend, dass mir später vielleicht 1-2 Botschaften verloren gehen!

void low_isr (void){

  if ((PIR3bits.RX0IF == 1) || (PIR3bits.RX1IF == 1)){
    CAN_RX_Message();
    }
      }


.
.
.
  PIE3bits.RX0IE = 0;  // Enable Interrupt CAN-RX0 (1 En, 0 Dis)
  PIE3bits.RX1IE = 0;  // Enable Interrupt CAN-RX1 (1 En, 0 Dis)

  uintTAir = DS1820_GetTemp(); // Dauer 10ms

  PIE3bits.RX0IE = 1;  // Enable Interrupt CAN-RX0 (1 En, 0 Dis)
  PIE3bits.RX1IE = 1;  // Enable Interrupt CAN-RX1 (1 En, 0 Dis)
(*)
  // Auslesen der Tasten
  ReadButtons();
.
.
.

Soweit funktioniert es auch! Nur wenn ich den Abstand mit dem ich 
Botschaften sende unter 12ms senke, kommt kein weiterer Interrupt mehr 
zustande, auch wenn ich die Übertragung wieder verlangsame. Ich habe 
auch schon versucht, an der Stelle (*) die CAN-Overflow bitts zu 
löschen, aber kein erfolg. So langsam verzweifel ich an dieser Stelle...

Hat jemand noch einen Tip, oder eine Idee, wie man es grundsätzlich 
anders angehen sollte...

Danke

Matthias

von Andreas K. (a-k)


Lesenswert?

Es gibt keinen Grund, die Interrupts für die gesamte Dauer der 1-Wire 
Abfrage auszuschalten. Einzig innerhalb eines 1-Wire Bits gibt es 
kritische Zeitbedingungen. Zwischen den einzelnen Bits bleibt jedoch 
Zeit.

Abhängig von der Laufzeit der Interrupt-Handler kann es auch möglich 
sein, während der Dauer des ~500µs langen 1-Wire Resets wichtige 
Interrupts freizugeben, nur muss man dann die obere Grenze beachten, 
sonst geht dem Device, wenn parasitär versorgt, irgendwann die Luft aus.

von Obelix (Gast)


Lesenswert?

1. Könntest du nicht einen I²C Temperatursensor verwenden? Dann sparst 
du dir die 1-Wire-Schnittstelle.

2.
> Nur wenn ich den Abstand mit dem ich
> Botschaften sende unter 12ms senke, kommt kein weiterer Interrupt mehr
> zustande, auch wenn ich die Übertragung wieder verlangsame.

Könnte es sein, dass wenn dein CAN-Controller zu viele Nachrichten 
verliert, er in einen Bus-Off oder Sleep-Modus geht?

von Matthias W. (macho2000)


Lesenswert?

Hallo zusammen,

danke für die alternativen Vorschläge zur Umschiffung der Problematik. 
Es ist schon möglich die Zeit für die Deaktivierung des CAN-Interrupt zu 
verringern, nur geht es mir bei dem Problem ums Prinzip. Wie gehe ich 
damit um, wenn ich für eine kurze Zeit keine Interrupt zulassen kann, 
und genau in diesem Zeitfenster einen Nachricht eintrifft?

Ich habe nun den Sonntag noch einmal viel Zeit in dieses Problem 
investiert und bin etwas schlauer. Immer wenn der Bus stehen bleibt, hat 
COMSTAT den Wert 128 (RXB0_Overflow). Obwohl ich das Register COMSTAT 
und PIR3 lösche wird kein neuer Interrupt ausgelöst. Komisch...

Das CAN-Modul selber deaktiviert sich nicht, da es weiterhin ACK sendet!

Da muss ich wohl noch etwas Zeit investieren...

Danke soweit schon mal

Matthias

von Andreas K. (a-k)


Lesenswert?

Matthias Werner wrote:

> damit um, wenn ich für eine kurze Zeit keine Interrupt zulassen kann,
> und genau in diesem Zeitfenster einen Nachricht eintrifft?

Na und? Entscheidend ist doch nur, dass in der Zeit in der Interrupts 
abgeschaltet sind, nicht mehr Messages eintreffen als der Puffer / die 
beiden Puffer (je nach Modus) verdauen können.

Aber du hast recht, dass diese Situation auftreten kann und das System 
damit klar kommen sollte. Wäre nicht der erste CAN Controller, der in 
solcher Situation Ärger macht (z.B. PIC18F2580, LPC2300).

von Matthias W. (macho2000)


Lesenswert?

Hallo Andreas,

ich hoffe mal das mein Controller I.O. ist :)

Leider habe ich in der Woche keine Zeit daran weiterzuarbeiten. Ich 
werde am Wochenende nochmal eingehend nach dem Fehler suchen und danach 
hier berichten.

Gruß

MAtthias

von Matthias W. (macho2000)


Lesenswert?

HAllo,

also ich glaube ich habe es jetzt verstanden das Problem. -> Mein 
CAN-Modul im PIC ist wohl beschädigt.

Ich hatte bei meinem ersten Treiber geraume Zeit vesehentlich den CAN-RX 
PIN als Ausgang deklariert. Der CAN Tranciever zog dann dank fehlendem 
Vorwiderstand das PIN auf 0 oder 1. Ich wunderte mich immer warum der 
PIC so heiß wird und bei zuvielen CAN Messages abstürtzt ;)

NAchdem ich Treiber und Layout nun berichtigt habe, hatte ich oben 
beschriebenes Problem. Bei der Anlyse des PICs heute morgen musste ich 
aber feststellen, dass sich keine Filter und Filtermasken mehr setzen 
lassen, und immer alle Messages direkt an RX0 gehen.

Jetzt habe ich den CAN auf Extended Messages umgestellt. Die Filterung 
funktioniert auch hier nicht mehr, aber der Bus stürzt unter gleichen 
bedingungen nicht mehr ab!

Sehr komisch..., da ist wohl was kaputt gegangen innerlich!

Danke nochmal für die Hilfe

Gruß

MAtthias

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.