Hallo,
Ich arbeite nun schon ein halbes Jahr mit dem at90 und dem CAN-Bus,
jetzt stellt sich aber ein größeres Problem:
Ich möchte dem Mikrocontroller zwei unterschiedliche Nachrichten mit
verschiedenen IDs senden, dieser soll per Interrupt reagieren und je
nach ID die Daten in die richtigen Variablen übernehmen.
Wie kann ich herausfinden welche ID den Interrupt ausgelöst hat?
Das Beispiel von Atmel arbeitet mit dem Prioritätsregister, wenn ich das
auch mache, kommt eine Nachricht (mit der niedrigeren Priorität) nicht
mehr durch.
Die Nachrichten werden extrem schnell hintereinander geschickt (max 10
ms Abstand, dann 50 ms, dann wieder 10...), kann das Probleme machen?
Gruß
David
hallo,
>Wie kann ich herausfinden welche ID den Interrupt ausgelöst hat?
naja. zunächst einmal gar nicht. lösen zwei message-objekte (mobs)
gleichzeitig einen irq aus, ist das pech.
dann hast du die möglichkeit, das highest priority-register zu checken
und entsprechend das mob zu behandeln. wenn du damit fertig bist, das
entsprechende rx-flag löschen (und den ganzen restlichen kram, siehe
doku) und fertig. das nächste mob wird sich alsbald wieder melden, da es
ja noch nicht behandelt wurde.
eine andere möglichkeit ist das cansit-register abzuklappern. ich mache
das so, da ich mir merke, welches mob zuletzt behandelt wurde, um dann
in ring-buffer-manier vorzugehen. zweck: keine nachricht soll eine
andere überholen (stichwort: re-ordering durch den can-controller)
bye kosmo
Das mit dem cansit Register habe ich glaub ich schon ausprobiert, im
Prinzip braucht man doch nur gucken wo überall eine 1 steht und dann
entsprechend reagieren, hat aber nicht viel gebracht.
Ich werd mich da morgen noch mal dransetzen...
Danke für die schnelle Antwort
David
Ich weiß jetzt nicht mehr weiter, es passiert immer noch das gleiche,
egal wie ich die Abfrage mache, ich habe sogar schon eine Variante
probiert, in der nur eine ID verwendet wird und die Zuordnung über
höhere, unbenutzte Bits in der Nachricht selbst geschieht. Das ganze
macht aber auch keinen Unterschied...
Hier mal meine ISR, vielleicht fällt jemandem ja ein grober Schnitzer
auf.
hallo.
erste frage: was funktioniert wie nicht?
und nun die kritikpunkte :)
>SIGNAL (SIG_CAN_INTERRUPT1)
das heißt doch jetzt ISR(CANIT_vect)
>{> unsigned char temp = CANPAGE; //CANPAGE sichern>> unsigned char nummer = (CANHPMOB >> 4); //MOb finden> CANPAGE = (nummer << MOBNB0);>> unsigned char i; //Zähler
soweit so gut.
> CANPAGE = (nummer << MOBNB0); //Flags zurücksetzen
warum wieder ein anderes mob? CANHPMOB gibt dir doch schon die id, und
du hast doch richtig geshiftet, die 4 entspricht MOBNB0
> CANSTMOB &= ~(1 << RXOK);
zu früh.
> CANSIT2 &= ~(1 << nummer);
brauchst nicht. ist ein nur-lese-register.
> CANCDMOB = 0;
ok, aber würde ich zusammen mit dem re-enablen hintereinander weg
schreiben.
> CANGIT = 0xff;
brauchst nicht.
> for (i=0; i<8; i++) //Daten auslesen> msg[0].data[i] = CANMSG;
sehr fein.
> CANCDMOB = (1<<CONMOB1); //MOb wieder auf Empfang
zu früh, wenn du mich fragst. funktioniert aber.
> posidaten[nummer][0] = msg[0].data[0]; //Daten speichern> posidaten[nummer][1] = msg[0].data[1];> posidaten[nummer][2] = msg[0].data[2];> posidaten[nummer][3] = msg[0].data[3];> posidaten[nummer][4] = msg[0].data[4];> posidaten[nummer][5] = msg[0].data[5];> posidaten[nummer][6] = msg[0].data[6];> posidaten[nummer][7] = msg[0].data[7];> CANPAGE = temp; //CANPAGE zurück>}
ok.
ich würde das mob erst wieder freigeben,
wenn die isr fertig ist, aber das ist geschmackssache. viele register
musst du gar nicht setzen (read-only oder implizit). größter schnitzer
ist aber das CANHPMOB, wenn ich das richtig erkannt habe.
hth,
bye kosmo
Hallo,
Das mit dem zweiten CANPAGE ist da wohl beim reinkopieren reingeraten,
der Code sieht in echt ein bißchen wüster aus, mit vielen
auskommentierten Varianten...
Was nicht geht ist, wenn ich eine Nachricht sende, auf die MOb 1
reagiert und dann eine, auf die MOb 2 reagieren soll (von den Message
IDs her), dann passiert da nichts,
andersherum geht, aber wenn ich dann wieder versuche MOb 2 anzusprechen
geht das auch wieder nicht, das finde ich seltsam.
Das mit der erneuten Freigabe des MObs ist doch eigentlich egal, die ISR
wird doch nicht durch einen erneuten Interrupt unterbrochen, oder?
Danke für´s auseinanderfleddern :-)
David
hallo,
>Das mit der erneuten Freigabe des MObs ist doch eigentlich egal, die ISR>wird doch nicht durch einen erneuten Interrupt unterbrochen, oder?
nein, das nicht. daher ist es egal, ja.
ich rate einfach mal: vielleicht siehst du da ein problem, wo gar keines
ist.
wenn du kein (!) masking benutzt, ist es doch egal, welches mob
reagiert. die nummerierung der mobs hat in diesem falle rein gar nichst
mit den CAN.identifyern (message-id's nennst du diese) zu tun.
oder maskiertst du einzelne mobs für den empfang von speziellen
identifiern?
bye kosmo
Ja tue ich,
Es müssen 8 Werte a 10 Bit übetragen werden (Positionen für 8 Servos),
ich habe mir gedacht ich bastel die in 8 unsigned int um und splitte
diese auf 16 unsigned char auf, somit brauche ich ja 2 Pakete um alles
zu übertragen. Es ist nun ziemlich wichtig, dass die Nachrichten
unterschieden werden, sonst werden nicht die richtigen Servos
angesteuert.
Wie gesagt hatte ich es auch schon damit probiert in den oberen 6 Bit
die Zugehörigkeit zu kennzeichnen und alles mit der gleichen ID zu
übertragen, aber das hat überhaupt keinen Unterschied gemacht, was ich
ziemlich seltsam finde.
Gruß
David
das klingt alles für mich so, als wenn du das mob nicht wieder auf
empfang stellst. dann sind die beiden voll, der controller findet kein
freies mob und wirft es in die tonne.
um das zu evaluieren: erst einmal masking aus. dann solltest du jede
nachricht kriegen. wenn das funktioniert, lasse dir ausgeben, welches
mob die isr behandelt. vielleicht hilft das weiter.
ich selber mache das CANCDMOB niemals komplett platt. sondern schreibe
nur die conf mit nem ODER neu rein (wie es die doku so schön verlangt).
weiterhin benutze ich das dlc beim einlesen der daten, gut, wenn du
immer 8 erhältst, ist das schnuppe. ansonsten sind mir keine großen
unterschiede aufgefallen. zur not musst' halt noch n bischen code
posten.
bye kosmo
Ja, dann werd ich noch ein bißchen testen, vielen Dank für die Tipps,
es ist allerdings so, dass MOb 1 (also nach meinem Verständnis der mit
der höheren Priorität) immer die Nachrichten empfängt, nur die für
Nummer 2 kommen nicht richtig an, aber das werd ich mir gleich noch mal
ansehen.
Gruß
David
Also die Maskierung funktioniert, wenn ich nur eine ID benutze reagieren
beide MObs so wie sie das sollen, ohne das ein anderer da mitredet...
Ich bin jetzt soweit, dass ich einfach nen zweiten at90 einbaue, so dass
jeder nur mit einer Nachricht arbeiten muss. Das funktioniert wenigstens
und die Uni hat ja genug Geld :-)
Inzwischen glaube ich auch immer mehr, dass die Interrupts einfach zu
schnell hintereinander kommen.
Naja,
morgen gehts weiter, jetzt reicht das erst mal
Gruß
David
hallo,
was du machst, ist fragmentierung von daten. du hast mehr daten, als in
eine mtu passt. hab ich auch vor kurzem gemacht, um mehr als 8 byte über
CAN zu übertragen. nettes thema bei mehreren puffern.
problem ist doch, das ein höher priorisiertes mob für nachrichten
benutzt wird, die zeitlich hinter anderen nachrichten angesiedelt sind.
wobei letztere bereits in niedriger priorisierten mobs stecken. der
controller nimmt somit ein re-ordering vor.
da die abarbeitung eines mobs schlicht zeit in anspruch nimmt (register
puschen, isr selber, register wieder poppen), sind manchmal mehrere mobs
mit einem irq signalisiert. bei dir also mob 1 und 2 , obwohl du gerade
auf eine nachricht im 2. mob wartest. was ist jetzt richtig?
meiner meinung nach gibt es zwei möglichkeiten:
1. nimm nur ein mob, und unterscheide anhand des CAN-identifiers. also
kein hardware-masking. ist zwar nicht sehr clever, aber einfach und
sollte leicht gehen.
2. einfach merken, welches das letzte aktive mob war. wäre dies also mob
2, denn wäre also mob 1 das nächste erwartete (bei dir). oder
entsprechend umgekehrt. kann man schön mit 15 mobs hochtreiben.
funtkioniert, wie schon mal erwähnt.
na viel spass (das macht es tatsächlich .. wenn es mal funktioniert)
bye kosmo
Hallo,
Nach langem, intensivem Testen bin ich jetzt auf den Kern des Problems
gestoßen.
Der liegt überhaupt nicht bei CAN (die Sache ging die ganze Zeit
wunderbar), sondern an der Ansteuerung der Servos durch die PWM.
Die Sache ist jetzt zwar auch nicht einfach, aber wenigstens bin ich
nicht mehr Schuld :-)
Gruß
David