Forum: Mikrocontroller und Digitale Elektronik Can Interruppt


von am grundsätzlichstem (Gast)


Lesenswert?

Hallo,
ich versuche mich am At90Can128 den Can einsatzfähig zu kriegen!
Das Senden habe ich soweit hinbekommen. Das heißt die Hardware und die 
Bautrate stimmt;-)
Nun möchte ich mir eine  kleine lib schreiben! weiß aber nicht wie ich 
diese Aufbauen soll! Für das senden der Mobs soll ich mir eine globale 
Variable anlegen die nach dem Senden von der ISR das frei sein 
signalisiert?
Wie geht das mit dem empfangen? wie macht man das am sinnvollsten? damit 
keine Pakete verlohren gehen?
Ich habe einfach ein grundsätzliches Struktur Problem:-\

Vielen lieben Dank

von guest (Gast)


Lesenswert?


von Thomas F. (igel)


Lesenswert?


von am grundsätzlichstem (Gast)


Lesenswert?

Würde es aber gern selber richtig machen ohne lib von anderen!
Ist denke ich eine gute Übung!!!

Danke werde es mir durchlesen!

von guest (Gast)


Lesenswert?

am grundsätzlichstem schrieb:
> Würde es aber gern selber richtig machen ohne lib von anderen!
> Ist denke ich eine gute Übung!!!

!!! Dann kopier die Lib halt nicht sonder schau Dir die Sourcen an und 
versuch sie zu verstehen !!!

von am grundsätzlichstem (Gast)


Lesenswert?

Also kann man es nur so machen wie in der Lib?
Oder gibt es auch andere Wege?
Um etwas licht im Konzeptbau wäre ich Dankbar!
Lg

und Danke

von Erwin D. (Gast)


Lesenswert?

am grundsätzlichstem schrieb:
> Also kann man es nur so machen wie in der Lib?

Es gibt niemals nur einen Weg. Aber in den Sources der Bibliothek kannst 
du dich mit den Funktionsprinzipien vertraut machen. Wenn du es dann 
verstanden hast, kannst du es auch selbst implementieren in einer Art 
und Weise, die dir zusagt.

von Guido (Gast)


Lesenswert?

So als Idee:

struct _tData
{
  char data[8];
  uint32 canId;
  uint msgLen; //0 for RTR
}tData;

typedef int (*tRxCallback)(int, *tData);

Can_SetBaudrate(uint32 Baudrate, bool elfBitOr29Bit);
Can_ConfigureTxMob(int mobIdx);
Can_ConfigureRxMob(int mobIdx, uint32 acceptanceMask, tRxCallback* 
pFunc);
int Can_GetErrorCount();
Can_StartRx();
Can_StopRx();
Can_Send(int mobIdx, tData* txData);
Can_Reset();

Du müsstes halt noch überlegen, ob du zum Bearbeiten der empfangenen 
Daten kurz den Empfangsinterrupt sperren willst oder einen Ringbuffer 
einrichtest oder ob du einfach zyklisch abfragst - Frage der 
Anforderungen und des Designs...

von Steffen R. (steffen_rose)


Lesenswert?

Guido schrieb:
> uint msgLen; //0 for RTR

Man kann auch Datentelegramme mit Länge 0 senden. Wird z.B. bei CANopen 
für das Sync-Telegramm genutzt. Dann schon eher eines der oberen Bits 
als RTR Flag nutzen.

Desweiteren mußt du zu allererst festlegen, welches Detailwissen die 
darüberliegende Applikation haben soll. Bei dir ist die Applikation für 
die Aufteilung der MOBs zuständig. Kann man so machen oder aber auch 
verbergen.

Hier konfigurierst du etwas:
Can_ConfigureTxMob(int mobIdx);

Hier
Can_Send(int mobIdx, tData* txData);
aber den Rest.

Ich würde entweder bei Can_Send() alles machen oder bei deiner 
Aufteilung
in Can_ConfigureTxMob() alles außer den eigentlichen Daten.

Kommt auf deinen Anwendungsfall an.

Die Baudrate Can_SetBaudrate() hat keinen bezug zu Base Frames (11 bit) 
oder Extended Frames (29 Bit). Willst Du das global einstellen, würde 
ich eine Init() Funktion erstellen. Normalerweise kann man aber beide 
Typen gemischt einsetzen, auch wenn es nicht so empfohlen wird.
CANopen nutzt für zusätzliche Flags die Bits 29..31 in der 32Bit CAN-ID 
Variablen.

von Guido (Gast)


Lesenswert?

Steffen R. schrieb:
> Man kann auch Datentelegramme mit Länge 0 senden

stimmt, war mir entfallen, er braucht also auch ein RTR Flag

>Baudrate Can_SetBaudrate() hat keinen bezug zu Base Frames (11 bit)
>oder Extended Frames (29 Bit)
ja das stimmt auch. Aber manche Controller können nur 29 oder 11bit 
senden aber beides empfangen. So einen hatte ich vor Augen, als ich die 
Funktion aufgeschrieben hatte. Aber ein Can_Init wäre da besser, stimmt 
schon.

...war ja auch nur so eingetippt, als Denkanstoss für den Kollegen ;)


>Hier konfigurierst du etwas:
>Can_ConfigureTxMob(int mobIdx);
>
>Hier
>Can_Send(int mobIdx, tData* txData);
>aber den Rest.
Mit Can_ConfigureTxMob konfigueriert man ein Mob als Tx-Objekt, mit 
modIdx sagt man welches.
Mit Can_Send sagt man, was man auf welchem Mob senden will
finde ich erstmal nicht anstössig.

Es gibt ja auch mehrere Wege, die zum Ziel führen...

>Desweiteren mußt du zu allererst festlegen, welches Detailwissen die
>darüberliegende Applikation haben soll.
Ich tendiere immer dazu, erstmal die Hardware abzubilden. Mehr wollte
ich mit meinem Denkanstoss erstmal nicht bezwecken.

Man kann ja immer nochmal eine Schicht drüber zu legen, die noch mehr
und weiter abstrahiert.

von am grundsätzlichstem (Gast)


Lesenswert?

Danke für die Anregung!
Ich bin aber glaube ich noch auf einen niedrigen Niveau!
Weiß einfach nicht wie ich das empfangen handeln soll damit ich Keine 
Botschaft verliere!
Danke

von Guido (Gast)


Lesenswert?

aus meiner Sicht gibt es 2 Konzepte, die erwähnenswert sind:

1. asynchon "multi-threaded"
Empfangs-Interrupt: Botschaften auslesen und in einen Ringbuffer 
stellen.
Dein Hauptprogramm liest den Ringbuffer aus und bearbeitet die Daten.
Beide Programmteile können unsynchonisiert nebeneinander laufen


2. Echtzeit
Du kannst dir auch einen 5ms Timer mmachen. Wenn der das 1. mal abläuft,
liest du die empfangenen Botschaften aus und startest ihn neu.
Wenn er das 2. mal abläuft bearbeitest du die zuvor ausgelesenen
Daten. Also immer Auslesen-Bearbeiten-Auslesen-Bearbeiten usw
Auch hier muss man nichts synchronisieren.


Es gibt noch andere Möglichkeiten, aber die finde ich irrelevant.
Nimm dir mal irgend ein Beispiel und versuche nachzuvollziehen,
wie die es gemacht haben.

In welchem Zyklus kommen denn deine Botschaften??

von am grundsätzlichstem (Gast)


Lesenswert?

Guido schrieb:
> aus meiner Sicht gibt es 2 Konzepte, die erwähnenswert sind:
>
> 1. asynchon "multi-threaded"
> Empfangs-Interrupt: Botschaften auslesen und in einen Ringbuffer
> stellen.
> Dein Hauptprogramm liest den Ringbuffer aus und bearbeitet die Daten.
> Beide Programmteile können unsynchonisiert nebeneinander laufen
>
> 2. Echtzeit
> Du kannst dir auch einen 5ms Timer mmachen. Wenn der das 1. mal abläuft,
> liest du die empfangenen Botschaften aus und startest ihn neu.
> Wenn er das 2. mal abläuft bearbeitest du die zuvor ausgelesenen
> Daten. Also immer Auslesen-Bearbeiten-Auslesen-Bearbeiten usw
> Auch hier muss man nichts synchronisieren.
>
> Es gibt noch andere Möglichkeiten, aber die finde ich irrelevant.
> Nimm dir mal irgend ein Beispiel und versuche nachzuvollziehen,
> wie die es gemacht haben.
>
> In welchem Zyklus kommen denn deine Botschaften??

Finde die erste Variante am Besten!
Wie macht man sowas?
Die Botschaften kommen im 10ms Takt.
Danke

von Guido (Gast)


Lesenswert?

am grundsätzlichstem schrieb:
> Finde die erste Variante am Besten!
> Wie macht man sowas?

Besorg dir eine Ringbuffer-Implementierung oder schreib selbst eine. 
Lies ggf ein Buch dazu. Dann probier deinen Ringbuffer aus -erstmal ohne 
CAN. Wenn es funktioniert, lies CAN-Daten im Interrupt aus und schreib 
sie in den Ringbuffer.

Tip: Schreib den Ringbuffer so, dass du beliebige Datenstrukturen dort
reinschreiben und die Implementierung so wiederverwenden kannst.

von Peter (Gast)


Lesenswert?

am grundsätzlichstem schrieb:
> Die Botschaften kommen im 10ms Takt.
Musst du auch in einem bestimmten Intervall senden?

von am grundsätzlichstem (Gast)


Lesenswert?

Peter schrieb:
> Musst du auch in einem bestimmten Intervall senden?

Ja auch das sollte in 10ms Takt passieren.

Habe jetzt etwas mit den Interrupt gespielt und es scheint zu klappen!

von Guido (Gast)


Lesenswert?

am grundsätzlichstem schrieb:
> Ja auch das sollte in 10ms Takt passieren.

Geht es um ein Datenprotokoll oder um einfache Werte (Messwerte, 
Zustände etc) die du vom Bus lesen willst?

von am grundsätzlichstem (Gast)


Lesenswert?

Guido schrieb:
> Geht es um ein Datenprotokoll oder um einfache Werte (Messwerte,
> Zustände etc) die du vom Bus lesen willst?

Es geht um  Messwerte usw.
Lg

von Guido (Gast)


Lesenswert?

am grundsätzlichstem schrieb:
> Ja auch das sollte in 10ms Takt passieren.
...
> Es geht um  Messwerte usw.

dann ist aus meiner Sicht die Variante mit dem 5ms Timerinterrupt
passender.

von Steffen R. (steffen_rose)


Lesenswert?

Guido schrieb:
>>Baudrate Can_SetBaudrate() hat keinen bezug zu Base Frames (11 bit)
>>oder Extended Frames (29 Bit)
> ja das stimmt auch. Aber manche Controller können nur 29 oder 11bit
> senden aber beides empfangen.

Ich wüßte keinen, der diese Hardwarebeschränkung hat. Nur einige APIs 
und Protokolle beschränken das Format. Falls du allerdings ein Beispiel 
hast, wäre ich interessiert.

Guido schrieb:
> Es gibt ja auch mehrere Wege, die zum Ziel führen...

Natürlich. Daher diese Unterhaltung hier. ;-)

Um den passenden Weg zu wählen, müßte man aber schon vorher ein grobes 
Konzept haben. Und dieses wirkt sich nach meinem Verständnis auch 
bereits auf die unterste Schicht aus.

Guido schrieb:
> Ich tendiere immer dazu, erstmal die Hardware abzubilden.

Guido schrieb:
> Man kann ja immer nochmal eine Schicht drüber zu legen, die noch mehr
> und weiter abstrahiert.

Ja klar. Dann würde ich die unterste Schicht aber spezieller an den 
jeweiligen CAN Controller anpassen und mit der Verallgemeinerung in der 
höheren Schicht beginnen. OK, da du auf MOB's referenzierts, geht dein 
Vorschlag auch in diese Richtung.

am grundsätzlichstem schrieb:
> Weiß einfach nicht wie ich das empfangen handeln soll damit ich Keine
> Botschaft verliere!

Per Interrupt und eine Softwarequeue, sofern du den RAM hast.
Polling Betrieb in welcher Form auch immer macht schnell mal bei Bursts 
Probleme.

Solltest Du jedoch RAM sparen wollen und daher die Nachrichten solange 
wie möglich im CAN Controller puffern wollen, kalkuliere das Timing mit 
0-Byte Nachrichten. Das Konzept würde ich aber nur ins Auge fassen, wenn 
du ein MOB pro CAN ID nutzt und der Zyklus kalkulierbar ist.
Wir nutzen eher Eventbasierende Kommunikation. Da kann man schnell 
reagieren ohne den Bus zyklisch zu belasten. Aber man muss mit der 
kürzestmöglichen Zeit rechnen.


Thema zyklisch senden: Überlege, was du im Fehlerfall machen willst. 
Evtl. benötgst du low level einen Sendenabbruch, um die Sendenachricht 
zu erneuern.

von am grundsätzlichstem (Gast)


Lesenswert?

Habe das WE über etwas rum probiert.
Habe folgendes gemacht und möchte von Euch Profis die meinung hören!
Also habe 2 empfangs-MOB definiert und den Filter  so eingestellt das 
jeweils 3 Id durch kommen.
Dazu  habe ich mir ein globales Botschaften Array angelegt.
Dazu 6  globale Bit.
Wenn nun mein Empfangsinterrupt kommt sortiere ich in der ISR die daten 
ein und setzte mein Globales Empfangsbit.
In der Main erkenne ich das und mache mit den Daten was.
Im Timerinterrupt schubse ich das Senden meiner Nachrichten an.
Was sagt ihr dazu? Völliger Mist? Akzeptabel? Oder?

Vielen Dank Für Eure Hilfe

von Steffen R. (steffen_rose)


Lesenswert?

Ich möchte dir nicht zusehr in deine Entwicklung hineinreden.
Wie Guido so schön schrieb, es gibt immer mehrere Wege.

Daher nur punktuell Hinweise zu deinem Konzept.

am grundsätzlichstem schrieb:
> Wenn nun mein Empfangsinterrupt kommt sortiere ich in der ISR die daten
> ein und setzte mein Globales Empfangsbit.

Denke über das Szenario nach, dass die Nachricht erneut eintrifft, 
während du die alte im Hauptprogramm auswertest.

am grundsätzlichstem schrieb:
> Im Timerinterrupt schubse ich das Senden meiner Nachrichten an.

Ich würde im Timerinterrupt nur eine Info für das Hauptprogramm setzen 
und dort senden. Deinen Weg würde ich nur ins Auge fassen, wenn du eine 
hohe Genauigkeit deiner Zykluszeit benötigst.

von am grundsätzlichstem (Gast)


Lesenswert?

Steffen R. schrieb:
> am grundsätzlichstem schrieb:
>> Wenn nun mein Empfangsinterrupt kommt sortiere ich in der ISR die daten
>> ein und setzte mein Globales Empfangsbit.
>
> Denke über das Szenario nach, dass die Nachricht erneut eintrifft,
> während du die alte im Hauptprogramm auswertest.

Deine Bedenken kann ich bei viel Daten nachvollziehen. Aber das 
Hauptprogramm sollte aus meiner Sicht doch nie länger als 10ms brauchen 
oder?

Würde das Problem dann nicht auch mit einer FIFO auftreten?
Was würdest du anders machen?

Steffen R. schrieb:
> Ich würde im Timerinterrupt nur eine Info für das Hauptprogramm setzen
> und dort senden. Deinen Weg würde ich nur ins Auge fassen, wenn du eine
> hohe Genauigkeit deiner Zykluszeit benötigst.

Ja macht Sinn fand aber das das anschupsen deiner Nachricht relativ 
zackig geht! Ist dies nicht der Fall?

Entschuldige das ich Dumm frage aber bin kein Profi!
Was ich bis jetzt gesehen hae ist der CAN wirklich GEIL!!!
Lg

von Steffen R. (steffen_rose)


Lesenswert?

am grundsätzlichstem schrieb:
> Steffen R. schrieb:
>> am grundsätzlichstem schrieb:
>>> Wenn nun mein Empfangsinterrupt kommt sortiere ich in der ISR die daten
>>> ein und setzte mein Globales Empfangsbit.
>>
>> Denke über das Szenario nach, dass die Nachricht erneut eintrifft,
>> während du die alte im Hauptprogramm auswertest.
>
> Deine Bedenken kann ich bei viel Daten nachvollziehen. Aber das
> Hauptprogramm sollte aus meiner Sicht doch nie länger als 10ms brauchen
> oder?

Das kannst nur Du wissen und auch wie häufig die jeweiligen Nachrichten 
eintreffen. Dein Konzept scheint darauf zu beruhen, dass die Nachrichten 
einen bestimmten Mindestabstand haben. In diesem Punkt möchte ich dir 
nicht hineinreden.

> Würde das Problem dann nicht auch mit einer FIFO auftreten?
Wenn die Fifo noch Platz hat, würde die Nachricht hinten angehangen, 
während du die erste bearbeitest.

> Was würdest du anders machen?
Ich möchte dich nur darauf aufmerksam machen, damit du darüber 
nachdenken kannst, ob du das Problem bedacht hast und welche Maßnahmen 
du ergreifst.
Manchmal kann es ja wirklich sein, dass eine solche Analyse ergibt, das 
ein Problem akzeptabel ist.


> Steffen R. schrieb:
>> Ich würde im Timerinterrupt nur eine Info für das Hauptprogramm setzen
>> und dort senden. Deinen Weg würde ich nur ins Auge fassen, wenn du eine
>> hohe Genauigkeit deiner Zykluszeit benötigst.
>
> Ja macht Sinn fand aber das das anschupsen deiner Nachricht relativ
> zackig geht! Ist dies nicht der Fall?

Ja, du bist aber recht unflexibel. Vielleicht willst Du später auch 
zwischendurch senden oder du must auf das Problem reagieren, dass eine 
Nachricht verzögert gesendet wird.

von Guido (Gast)


Lesenswert?

Hallo,

zu den Fragen:

>Deine Bedenken kann ich bei viel Daten nachvollziehen. Aber das
>Hauptprogramm sollte aus meiner Sicht doch nie länger als 10ms brauchen
>oder?
Der Interrupt kommt asynchon. Wenn du das nicht berücksichtigst, kommt
dein Programm früher oder später durcheinander, weil es irgendwann, wenn
dein Programm lange läuft, dazu kommen wird, dass der Interrupt
gerade die Daten erneuert, während dein Hauptprogramm sie liest.
Wenn du bei dem Interrupt-Konzept bleibst, musst du:
- entweder einen Fifo nehmen
- oder kurz die Interrupts kurz(!) sperren während dein Hauptprogramm 
Daten liest. Der Fifo ist m.E. zu bevorzugen.


>Würde das Problem dann nicht auch mit einer FIFO auftreten?
>Was würdest du anders machen?
Das kommt auf die Fifo-Implementierung an. Ein ordentlicher Fifo hat 
einen
Schreibpointer (der wird vom Interrupt angefasst) und einen Lesepointer 
(der wird von deinem Hauptprogramm angefasst). Der Zugriff auf beide 
Pointer ist atomar, sofern sie nicht als double deklariert sind.
Somit wäre der  Fifo Interrupt-safe.

Du hattest ja geschrieben, dass du im 10ms Zyklus senden musst. Daher
(und weil du unerfahren bist) habe ich dir geraten, einen 5ms Timer zu 
nehmen und um jew. 5ms versetzt:
Auslesen
Bearbeiten, Senden
Auslesen
Bearbeiten, Senden
...

Damit hast du das Echtzeit-Thema (10ms Senderaster) und das 
Synchronisierungsproblem erschlagen. Wenn das dann läuft, kannst du
dich ja dran machen und das ganze auf Interrupt/Fifo umstellen.

@Steffen Rose:
>Per Interrupt und eine Softwarequeue [...]
Eine Queue ist hier m.E. nicht sinnvoll, da beim Anhängen und Lesen
die Zeiger auf das vorherige und das nächste Element manipuliert
werden müssen. Das ist nicht atomar und daher nicht Interrupt-safe.
Aus meiner Sicht müsste er schon einen Fifo nehmen.

von am grundsätzlichstem (Gast)


Lesenswert?

Guido schrieb:
> Ein ordentlicher Fifo hat
> einen
> Schreibpointer (der wird vom Interrupt angefasst) und einen Lesepointer
> (der wird von deinem Hauptprogramm angefasst). Der Zugriff auf beide
> Pointer ist atomar, sofern sie nicht als double deklariert sind.
> Somit wäre der  Fifo Interrupt-safe.

Gibt es so eine Fifo schon gekocht?

Danke LG

von am grundsätzlichstem (Gast)


Lesenswert?

War die Frage jetzt nicht ok?
Lg

von fifo (Gast)


Lesenswert?


von am grundsätzlichstem (Gast)


Lesenswert?

Hallo ich nochmal;-)
Sorry das ich schon wieder lästig bin!
Was ist von der Option "Automatic reply" zu halten?
Ist die Option Ressourcen sparend?
Ich habe nicht genau verstanden wie diese Option  arbeitet! Werden die 
Empfangenen Daten normal ausgelesen und die Antwort erfolgt dann über 
den selben Mob oder wird für das senden ein eigener Mob verwendet?
Lg
Und Danke

von Guido (Gast)


Lesenswert?

fifo schrieb:
> http://www.mikrocontroller.net/articles/FIFO#FIFO_als_Bibliothek

leider passt dieser Fifo nicht so recht auf sein Problem.
Das hier ist nämlich ein Byte-Fifo. Er wird aber einen Fifo
brauchen, der einen CAN-Frame + CANID + Längeninfo + RTR Flag
aufnehmen kann.

Er braucht einen Fifo, dem man eine Anzahl von Bytes am Stück
übergeben kann. Etwa so:


bool ringbufferWrite(RINGBUF_OBBJ pRingbuffer,
                     char*        pData,
                     int          writeLen);

bool ringbufferRead(RINGBUF_OBJ  pRingbuffer,
                    int         desiredReadLen,
              char*       pData);

pData müsste auf ein Object

struct _tData
{
  char data[8];
  uint32 canId;
  uint msgLen;
  bool rtr;
}tData;

zeigen. Somit kann er seine empfangenen CAN-Daten inkl. der relevanten
Zusatzinformationen am Stück in den Ringbuffer kopieren (im Interrupt) 
und wieder rausholen (Haupt-Programm).
...wäre zumindest meine Meinung.

von Guido (Gast)


Lesenswert?

am grundsätzlichstem schrieb:
> Ich habe nicht genau verstanden wie diese Option  arbeitet!

Ich will dir nicht zu nahe treten, aber das steht in der Spec.
Hast du diese denn nicht vorliegen?

von am grundsätzlichstem (Gast)


Lesenswert?

Guido schrieb:
> Ich will dir nicht zu nahe treten, aber das steht in der Spec.
> Hast du diese denn nicht vorliegen?

Ich habe Datenblatt hier vor mir liegen, habe daraus die Automatic reply 
Funktion raus gelesen aber nicht verstanden wie sie arbeitet:-\
Dachte es könnte mir jemand in klaren verständlichen Worten sagen:-)

Danke!

von Guido (Gast)


Lesenswert?

in 19.5.2.4 Automatic Reply steht in etwa folgendes:

Wenn du ein RTR empfängst, wird das dafür zuständige MOB
automatisch einen CAN Frame rausschicken.

RTR=1
RPLV=1
CAN-ID Maske
Tx-Mode

und dann sollte es gehen. Du bekommst einen Tx-Interrupt wenns 
funktioniert
hat und kannst das MOB wieder aufziehen (RPLV=1).

Falls du aber mit dem Gedanken spielst, deinen 10ms Sendetakt
durch die 10ms Empfangsbotschaft Triggern zu lassen, musst du genau
wissen, was du tust, weil du das Senden der von dir berechneten
Daten um 10ms verzögerst.

von am grundsätzlichstem (Gast)


Lesenswert?

Guido schrieb:
> Falls du aber mit dem Gedanken spielst, deinen 10ms Sendetakt
> durch die 10ms Empfangsbotschaft Triggern zu lassen, musst du genau
> wissen, was du tust, weil du das Senden der von dir berechneten
> Daten um 10ms verzögerst.

 Ja das war der Hintergedanke. Sorry da blicke ich nicht durch, warum 
verzögere ich damit die Daten?
Bitte erklär mir das?

Vielen herzlichen Dank!!

von Guido (Gast)


Lesenswert?

Du verzögerst nicht zwangsläufig (da muss ich meine Aussage 
korrigieren).
Es wäre aber möglich, je nachdem wie du dein Programm aufbaust. Die 
jeweils passende und einleuchtende Erklärung kann man nur geben, wenn 
man diesen Aufbau kennt.


Empfange im Interrupt in einen Ringbuffer. Lass dein Hauptprogramm in 
einer 10ms Schleife laufen und dort dann folgende
Abfolge:
1. empfangene Daten aus Ringbuffer lesen (älteste Daten verwerfen)
2. Aufbereiten, prüfen was auch immer...
3. Ausgabe berechnen
4. Senden

So stellst du sicher, dass du mit den aktuellsten Daten rechnest
und die daraus berechneten Ergebnisse auch schnellst möglich
raussendest und zwar im geforderten 10ms Raster.

Ausserdem war ja die Anforderung an dich, im 10ms Raster zu senden. Das 
was du vor hast, sendet nur dann im 10ms Raster, wenn auch die 
Gegenstelle
im 10ms Raster sendet. Wenn die ausfällt musst du ggf. Defaultwerte
oder anderweitig synthetisierte Werte senden - keine Ahnung...

Ggf musst du pro Rx-Frame auch noch einen Zeitstempel haben, um zu 
wissen, ob die empfangenen Daten älter als bspw. 20ms sind - dann hat 
die Gegenstelle ein Problem und du musst ggf. darauf reagieren?!?

von Steffen R. (steffen_rose)


Lesenswert?

am grundsätzlichstem schrieb:
> Ja das war der Hintergedanke.

Überlege Dir, ob du wirklich Remote Frames nutzen willst. Dass passt aus 
meiner Sicht nicht so ganz in dein Konzept des zyklischen Sendens.

am grundsätzlichstem schrieb:
> warum
> verzögere ich damit die Daten?

Du solltest nicht verschiedene Stellen zum Beschreiben des CAN 
Controllers haben. Da kann man ganz schnell Probleme bekommen, wenn man 
die Zugriffe nicht ordentlich verriegelt. Dein Ansatz is das Beschreiben 
im 10ms Interrupt. Somit kannst Du erst dort das MOB, welches auf das 
RTR reagiert, mit neuen Daten füllen oder, wenn nicht automatisch 
geantwortet werden soll, die Antwort auf den Remote Request (RTR) 
senden.

Im Worst case empfängst du die RTR Nachricht kurz nach dem Timer 
Interrupt. Bis zum nächsten vergehen dann 10ms.

zu der Fifo:
Die von mir gefundenen allgemeinen Implementierungen bieten so viel 
Funktionalität, dass man schon wieder aufpassen muss, dass man Interrupt 
safe bleibt. Ohne dem müßte man sonst einen Lock Mechanismus einführen. 
Guido hat das oben bereits beschrieben.

Soll heißen, ich lese mit. Auf manches hat man aber auch mal keine 
Antwort.

von Guido (Gast)


Lesenswert?

Steffen R. schrieb:
> zu der Fifo:
> Die von mir gefundenen allgemeinen Implementierungen bieten so viel
> Funktionalität, dass man schon wieder aufpassen muss, dass man Interrupt
> safe bleibt. Ohne dem müßte man sonst einen Lock Mechanismus einführen.

Auch allgemeine Fifo Implementierungen folgen dem Konzept, dass der
Schreiber den Lesepointer anfasst und der Leser den Lesepointer.
Du hast vermutl. tatsächlich eine Listenimplementierung o.ä. gefunden.

an den TO: Willst du einen 10ms RTR aufsetzen (quasi als Takt), dann 
andere CAN Daten einlesen und daraus Sendedaten berechnen?

Also ich rate, aber erklär doch mal, was du da genau vorhast und
welche Programmstruktur dir vorschwebt...

von Erwin D. (Gast)


Lesenswert?

Guido schrieb:
> Schreiber den Lesepointer anfasst und der Leser den Lesepointer.

Das meinst du bestimmt nicht so, oder? :-)

von fifo (Gast)


Lesenswert?

Guido schrieb:
> fifo schrieb:
>> http://www.mikrocontroller.net/articles/FIFO#FIFO_als_Bibliothek
>
> leider passt dieser Fifo nicht so recht auf sein Problem.
> Das hier ist nämlich ein Byte-Fifo. Er wird aber einen Fifo
> brauchen, der einen CAN-Frame + CANID + Längeninfo + RTR Flag
> aufnehmen kann.

Könnte er nicht je ein fifo für Längeninfo, CAN-Frame, CAN ID in 4x8Bit 
und ein RTR Flag anlegen... Dabei müsste man dann bei der  Längeninfo 
ein, bei den CAN-Frame die jeweilige Anzahl, bei der ID 4 Byte usw. 
abfragen...

von Guido (Gast)


Lesenswert?

Erwin D. schrieb:
> Guido schrieb:
>> Schreiber den Lesepointer anfasst und der Leser den Lesepointer.
>
> Das meinst du bestimmt nicht so, oder? :-)

Huch ;)

..der Schreiber den Schreibpointer anfasst und der Leser den Lesepointer

von Guido (Gast)


Lesenswert?

fifo schrieb:
> Könnte er nicht je ein fifo für Längeninfo, CAN-Frame, CAN ID in 4x8Bit
> und ein RTR Flag anlegen... Dabei müsste man dann bei der  Längeninfo
> ein, bei den CAN-Frame die jeweilige Anzahl, bei der ID 4 Byte usw.
> abfragen...

Nein. Das wird inkonstent, wenn die Fifos voll sind, der Leser aber 
bspw. den "Längenfifo" lesen konnte, dann ein Rx-Interrupt kommt, der 
Längenfifo einen Platz frei hat, aber die anderen Fifos noch nicht. Das 
wird doch inkonsistent, ausser man fragt im Interrupt ab, ob alle 4 
Fifos genug Platz haben. Das finde ich aber nicht schön.

Ausserdem ist die Lösung doch denkbar einfach und robust: Er macht sich 
einen Fifo, in dem er die CAN-Datenstruktur komplett reinschreiben kann
und fertig ist die Sache. Die von dir genannte Implementierung könnte
er auch umschreiben, sodass der Fifo generisch ist und beliebige Objekte
aufnehmen kann.

von fifo (Gast)


Lesenswert?

Mach mal ein Beispiel bei dem es zu Problemen führt. Ich denke es sollte 
ohne Probleme klappen

von Guido (Gast)


Lesenswert?

fifo schrieb:
> Mach mal ein Beispiel bei dem es zu Problemen führt. Ich denke es
> sollte
> ohne Probleme klappen

Ich hatte oben doch ein Beispiel mitgeliefert. Für meine Begriffe
stellt das den kritischen Fall dar.

Die Multi-Fifo-Lösung finde ich (ohne dir zu nahe treten zu wollen) 
nicht gut. Habe ich auch noch nirgendwo so gesehen. Zusammengehörende 
Informationen sollten zu einem Objekt zusammengefasst werden. Dieses 
Objekt sollte dann in den Fifo geschrieben werden ...meiner 
unbedeutenden Meinung nach.

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.