Hallo,
ich hab ein Problem wenn ich mehrere CAN Nachrichten gleich nacheinander
senden will, werden manche verschluckt.
Es kommen nur Nachricht 1 und 4 an. Es ist egal, ob die in dem selben
mob sind oder nicht.
Anscheinend mache ich beim warten bis alles gesendet ist was falsch.
Ohne den delays geht es nicht, mit den delays kein Problem.
Bemerkung:
Die main.c ist so geschrieben, dass sie bei jedem sofort mit Atmel
Studio kompilieren sollte.
Momentan nur 2 AT90CAN128 am CAN.
Bus ist terminiert.
Der Andere liest nur. (Nicht im spy/silent mode)
Baudrate 500kB/s.
Normalerweise werden die Nachrichten in nem Timer gesendet und da ist
das delay ein Problem.
Mir ist klar, dass endlos whiles doof sind.
Danke,
Michi
liefert der integrierte CAN Controller nichts das man weiß ob die
Übertragung ok oder fehlerhaft war, der ATM16M1 spuckt z.B einige
Interrupts aus, diese muss man eben auch auswerten.
Interrupt on receive completed OK
Interrupt on transmit completed OK
Interrupt on error (bit error, stuff error, CRC error, form error,
acknowledge error)
Interrupt on frame buffer full
Interrupt on “Bus Off” setting
Interrupt on overrun of CAN timer
warte ich eigentlich auf das Interrupt auslösende Bit.
So wie ich das gesehen hab, muss der Interrupt dafür aber nicht extra
Aktiviert werden.
TXOK: Transmit OK
This flag can generate an interrupt. It must be cleared using a
read-modify-write software routine on the whole CANSTMOB register.
The communication enabled by transmission is completed.
TxOK rises at the end of EOF field and then, the MOb is disabled (the
corresponding ENMOB-bit of CANEN registers is cleared). When the
controller is ready to send a frame, if two or more message objects are
enabled as producers, the lower MOb index is supplied >first.
stimmt die Interruptroutine muss man nicht anspringen lassen, aber du
musst das Bit nach jeder Übertragung löschen damit du es wieder neu
auswerten kannst.
Mach ich davor, um sicher zu gehen, dass zwischen den Aufrufen nichts
darin passiert. (z.B. Nachrichten empfangen)
Aber auch wenn ich es davor und danach mache bleibt das Problem
bestehen.
Danke für deinen Code, aber auch damit funktioniert es bei mir nicht.
Hast du damit schon erfolgreich mehrere Nachrichten gleich nacheinander
gesendet?
Ich habe gerade mal kurz ausprobiert den Bus voll zu machen und das
funktioniert so nicht, es gehen nicht alle Botschaften durch.
Von vier Botschaften hintereinander weg kommen nur die ersten zwei auf
dem Bus an.
Macht aber auch Sinn, durch die Priorisierung der Botschaften sollte
eigentlich nur die Botschaft mit der niedrigsten ID durch gehen,
wenn man versucht in einer engen Schleife zu senden.
Die zweite Botschaft geht mit durch, weil genug Zeit ist zwischen dem
Abschluss des Sendens der niedrigsten ID und dem neu befüllen des MOB.
Okay, also mal anders:
1
while(1)
2
{
3
counter++;
4
5
CANPAGE = (3<<4); // select MOB3
6
if(CANSTMOB & (1<<TXOK)) // fertig mit Senden?
7
{
8
9
CANPAGE = (0<<4); // select MOB0
10
if(CANSTMOB & (1<<TXOK)) // fertig mit Senden?
11
{
12
CANSTMOB &= ~(1<<TXOK); // reset flag
13
CANCDMOB = (1<<DLC1); // 2 Byte
14
CANMSG = counter;
15
CANMSG = 0xaa;
16
CANCDMOB |= (1<<CONMOB0); // Transfer einleiten
17
}
18
19
CANPAGE = (1<<4); // select MOB1
20
if(CANSTMOB & (1<<TXOK)) // fertig mit Senden?
21
{
22
CANSTMOB &= ~(1<<TXOK); // reset flag
23
CANCDMOB = (1<<DLC1); // 2 Byte
24
CANMSG = counter;
25
CANMSG = 0xaa;
26
CANCDMOB |= (1<<CONMOB0); // Transfer einleiten
27
}
28
29
CANPAGE = (2<<4); // select MOB2
30
if(CANSTMOB & (1<<TXOK)) // fertig mit Senden?
31
{
32
CANSTMOB &= ~(1<<TXOK); // reset flag
33
CANCDMOB = (1<<DLC1); // 2 Byte
34
CANMSG = counter;
35
CANMSG = 0xaa;
36
CANCDMOB |= (1<<CONMOB0); // Transfer einleiten
37
}
38
39
CANPAGE = (3<<4); // select MOB3
40
if(CANSTMOB & (1<<TXOK)) // fertig mit Senden?
41
{
42
CANSTMOB &= ~(1<<TXOK); // reset flag
43
CANCDMOB = (1<<DLC1); // 2 Byte
44
CANMSG = counter;
45
CANMSG = 0xaa;
46
CANCDMOB |= (1<<CONMOB0); // Transfer einleiten
47
}
48
}
49
}
Erst wieder neu die MOBs füllen wenn die letze Botschaft auch durch ist.
Damit sehe ich dann auch alle vier Botschaften auf dem Bus
hintereinander weg mit dem jeweils aktuellen Zählerstand, da fehlt
nichts mehr.
Das sind dann auch alle 130µs eine Botschaft, das passt zur Länge einer
2-Byte Botschaft mit 500kBit.
Time Chn ID Name Dir DLC Data
0.000132 CAN 1 200 Rx 2 C4 AA
0.000130 CAN 1 201 Rx 2 C4 AA
0.000130 CAN 1 202 Rx 2 C4 AA
0.000130 CAN 1 203 Rx 2 C4 AA
0.000130 CAN 1 200 Rx 2 CD AA
0.000130 CAN 1 201 Rx 2 CD AA
0.000130 CAN 1 202 Rx 2 CD AA
0.000130 CAN 1 203 Rx 2 CD AA
0.000130 CAN 1 200 Rx 2 D3 AA
Ich probiere auch gerade ein Programm mit dem AT90CAN zu schreiben, im
speziellen geht es darum, dass ich 2 Nachrichten zeitgleich übertrage,
oder zumindest den Payload zeitgleich übertrage. Das hat denn Sinn, dass
man dadurch einen Schlüsselausstausch erreichen kann (Plug-and-Secure
Verfahren von Bosch).
Jedoch frage ich mich jetzt langsam, ob es überhaupt mit dem AT90CAN
funktionieren kann? Bisher habe ich es mit einem Trigger durch einen
zusätzlichen Interrupt probiert, sodass beide Seiten zeitgleich eine
CAN-Nachricht verschicken, anscheinend passiert das aber nicht
zeitgleich. Die ID ist auch die selbe.
Hat da jemand von euch Erfahrung mit?
Zwei MOBs direkt hintereinander zu füllen damit zwei Botschaften direkt
hintereinander raus gehen ist doch gar kein Problem, wenn man das zum
Beispiel nur alle 10ms versucht.
Das Problem hier war nur den Bus maximal voll zu bekommen ohne
Botschaften an die Priorisierung zu verlieren.
Danke schon mal für deine Antwort. Ich meinte aber vielmehr, dass ich
zwei AT90CANs auf dem CAN Bus habe. Diesen sollen nun zeitgleich jeweils
eine Nachricht senden und lesen. Es geht vorallem darum, dass der
Payload zeitgleich auf den Bus geschrieben und gelesen wird. Dadurch
bekommt man in diesem Schlüsselaustausch das Geheimnis.
Peter schrieb:> zwei AT90CANs auf dem CAN Bus habe. Diesen sollen nun zeitgleich jeweils> eine Nachricht senden und lesen. Es geht vorallem darum, dass der
Das geht natürlich nicht, wenn es gleichzeitig gehen soll.
Falls beide dasselbe Format haben:
Die niedrigere ID geht durch.
Falls nicht:
CAN Standard geht durch, CAN Extended nicht.
Wenn du mit zeitgleich die zeitlichen Abstände meinst, dann wird es
mit der Genauigkeit nicht sehr wit her sein...
Was würde denn theorethisch passieren, wenn beide die selbe ID haben?
Dann könnte es doch passieren, dass beide anfangen zu senden, weil sie
denken, sie haben die niedrigste ID?
Ich meinte schon, dass zeitgleiche Versenden und nicht das Senden von
Nachrichten mit gleichem Abstand hintereinander.
Nur mit einem Transceiver habe ich es bisher schon implementiert. Das
kann man aber ja leider nicht so direkt auf den Controller übertragen.
Dort habe ich jeweils die beiden Parteien, die Bits senden lassen und
dann wenig später den Bus von Beiden lesen lassen.
Peter schrieb:> Was würde denn theorethisch passieren, wenn beide die selbe ID haben?
Dann sendet ganz praktisch erst der eine Controller auf der ID, dann der
andere.
Du wirst es niemals hinbekommen, dass beide gleichzeitig anfangen zu
senden, auch nicht mit einer gemeinsamen Trigger-Leitung und ansonsten
Bus-Ruhe.
Zwei Controller laufen niemals exakt synchron, selbst bei zwei direkt
nebeneinander die mit einem gemeinsamen Oszillator laufen wird das eher
nichts.
Und selbst wenn das zufällig doch mal klappen sollte, dann wird es
CRC-Fehler geben.
Ich habe das ja schon mal auf einem Transceiver gemacht. Da ist mir ja
schon aufgefallen, dass es niemals komplett synchron war. Es gab immer
einen Zeitunterschied. Durch den Interrupt und eine Anpassung, wo der
Sender eine Zeit lang nichts tut (da er schneller ist/war), konnte die
Übertragung der Bits dann aber doch stattfinden.
Beim Controller kann ich aber aber ja nicht so direkt auf alles
zugreifen, da er mir ja auch Arbeit abnehmen soll.
Peter schrieb:> Was würde denn theorethisch passieren, wenn beide die selbe ID haben?> Dann könnte es doch passieren, dass beide anfangen zu senden, weil sie> denken, sie haben die niedrigste ID?
Die Arbitrierung ist nur während der ID erlaubt. Sollte der Unterschied
beider Frames während der Datenphase auffallen, ist dies ein Fehler.
Um eine korrekte Operation sicherzustellen, muss sichergestellt sein,
dass eine ID nur von einem Knoten gesendet wird.
Bei CAN-FD ist das ganze durch den möglichen Bitratenwechsel sowieso so.
Eine Arbitrierung im schnellen Datenfeld ist durch Laufzeiten auf dem
Bus sowieso ausgeschlossen.
M. H. schrieb:> Was würde denn theorethisch passieren, wenn beide die selbe ID haben?>> Dann könnte es doch passieren, dass beide anfangen zu senden, weil sie>> denken, sie haben die niedrigste ID?
die dominanten Bits würden die rezesiven Bits eben unterdrücken und die
Checksumme wird dann nicht mehr passen.