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
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 !!!
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.
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...
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.
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.
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
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??
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
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.
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!
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?
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
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.
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.
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
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.
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
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.
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.
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
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
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.
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?
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!
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.
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!!
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?!?
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.
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...
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...
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
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.
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.