CAN-Interface

Das CAN-Interface des SpartanMC besitzt 15 Ein-/Ausgaberegister zur Funktionsauswahl und Funktionssteuerung sowie einen DMA Speicherbereich für die zu sendenden und für die empfangenen CAN-Nachrichten. Im DMA-Speicher können 1 ... 18 Empfangspuffer und 1 ... 18 Sendepuffer installiert werden. Zusäzlich können auch 1 ... 18 Nachrichten Filter Installiert werden die bei ihrer Aktivierung dafür sorgen das nur noch Nachrichten einen Empfangsinterrupt auslösen die mit den eingestellten Filterwerten übereinstimmen. Das CAN-Interface kann Nachrichten mit dem Standard 11 Bit ID und auch mit dem Erweiterten 29 Bit ID empfangen und versenden. Beide ID Formen können gemicht auftreten. Die Datenrate ist von 5 KB/s bis 1000KB/s in den üblichen Stufen varierbar. Die DMA Puffer können beim Systemstart vorinitialisiert werden. Zum Anschluß an einen CAN-Bus muss nur noch der Treiber Schaltkreis MCP2551-I/P mit dem FPGA-Board verbunden werden. Die Schaltung dazu ist am Ende dieser Seite zu finden.

Die 18 Rx und Tx Puffer werden entsprechend der Priorität gesendet, oder für den Empfang genutzt. Die Puffer Rx 0 und Tx 0 haben die höchste Priorität. Werden alle Tx Puffer im Regiter tx_request_buffer als belegt gekennzeichnet, dann wird mit dem Senden von Tx 0 (Bit 17 im Register) begonnen und erst nach dem Senden von Tx 17 (Bit 0 im Register) aufgehört. Nach dem senden eines der Puffer wird das zugehörige Bit im tx_request_buffer sofort gelöscht. Achtung, solange noch nicht alle Bits im Register gelöscht sind sollte kein Bit erneut gesetzt werden, da dann dieser Puffer eine höhere Priorität hat als die noch nicht gesendeten Puffer und damit vor den noch nicht gesendeten Puffern gesendet würde. Die Daten aller bereits gesendeten Puffer können aber schon mit neuen Daten belegt werden. Sie müssen dann nur noch freigegeben werden sobald alle Puffer des letzten Starts gesendet sind.

Beim Empfang wird immer nach dem höchsten nicht gesetzten Bit im Register rx_used_buffer gesucht und dort werden dann die Daten der empfangen Nachricht abgelegt. In den ersten 4 Worten stehen die maximal 8 Datenbyte der Nachricht. Danach stehen die unteren 18 Bit eines Extended ID, wenn die letzte Nachricht in diesem Format gesendet wurde. Daran folgt ein Wort mit einer Reihe von Statusbits, der Nachrichten Länge und den 11 Bit des Standard ID oder der oberen 11 Bit eines Extendet ID. Im Wort 7 werden die Ausgangssignale aller 18 Filter angezeigt. Hat ein Filter einen Treffer, so wird das Bit auf 1 gesetzt. Nicht initialisierte Filter (alle Bits in den Filterregistern sind 0) liefern immer eine 1. Die Bits sind aber nicht wirksam, wenn keines der Bits im Register acf_enable gesetzt ist. Sobald Bits in diesem Register gesetzt sind, werden auch nur noch diese Bits im 7. Wort angezeigt. Man kann daran erkennen welcher Filter beim Empfang der Nachricht aktiv war. Sobald ein oder mehrere Filter aktiv sind, können auch nur noch dies Nachrichten empfangen werden. Gefilter werden kann nach einem ID oder nach ID-Gruppen im Extendet oder Standard ID, auf Remoteframe und auf die oberen 4 Bit des 1. Bytes einer Nachricht. Dazu sind im Filter 2*36 Bit Register installiert. In den ersten 36 Bit muss der Wert eingetragen werden, nachdem gesucht werden soll in dem 2. Register werden die Bits maskiert, die vom Vergleich ausgeschlossern werden sollen. Damit kann man auch Teile des ID maskieren, wodurch die Auswahl von ID Gruppen möglich wird. Im 8. Wort des Rx Puffers wird der CRC der empfangenen Nachricht abgelegt.
Die Tx Puffer sind ähnlich aufgebaut. In den ersten 4 Worten stehen auch die 8 Datenbyte der zu sendenden Nachricht. Auch die nächten beiden Worte sind wie beim Rx Puffer mit den unteren 18 Bit des Extendet ID und das Wort 6 mit dem RTR-Bit, dem IDE-Bit, der Länge und den 11 Bit des Standard ID oder den oberen 11 Bit des Extendet ID zu laden. Im 7. Wort ist die Anzahl der Sendewiederholungen abzulegen. Null bedeutet die Nachricht soll nur einmal gesendet werden. Das 8. Wort im Puffer wird nicht genutzt.

Das CAN-Interface kann auch im Listen Only Mode eingesetzt werden um alle Nachrichten auf einem CAN-Bus zu protokollieren. Dabei werden auch fehlerhafte und nicht beantwortete Nachrichten angezeigt. Bei Aktivierung der Filter werden nur noch die Nachrichten an ein bestimmtes Gerät oder eine Gerätegruppe angezeigt. Mit diesem Mode kann gut nach Fehlern auf dem CAN-Bus gesucht werden.

Register des Kontrollers

Offset Register-Name Bit Bez. in Verilog Beschreibung (Rechte) Initialwert
0 Arbeitsregister work Schreiben und Lesen immer möglich
17-10 (nur Lesen) nicht genutzt
9-8 can_mode setzt Arbeitsmodus des CAN-Controller h3
7 abort_tx bricht Telegrammsendung ab b0
6 en_exception_ir aktiviert/deaktiviert Exception Interrupt b0
5 en_tx_successful_ir aktiviert/deaktiviert TX Interrupt b0
4 en_rx_successful_ir aktiviert/deaktiviert RX Interrupt b0
3 overload_request fordert ein Overload Frame an b0
2 transmitting (nur Lesen) gesetzt wenn Gesendet wird b0
1 receiving (nur Lesen) gesetzt wenn Empfangen wird b0
0 bus_free (nur Lesen) gesetzt wenn der Bus frei ist b0
1 Konfigurations Register choose_config
17-2 (nur Lesen) nicht genutzt
1 sample_mode schaltet 3-fach Abtastung an b0
0 extended_mode Ermöglicht das Versenden von Extended Frames b1
2 Bus-Timing-Reg. bustiming Schreiben nur im Config_Mode
17-10 baudrate_presc BRP h0
9-8 sync_jump_width SJW h2
7-3 time_segment1 Länge des Prop_Seg & Phase_Seg1 in tq = tseg1 h15
2-0 time_segment2 Länge des Phase_Seg2 in tq-2 = tseg2 h4
3 Fehlerzähler-Reg. error_cnt Schreiben und Lesen immer möglich
17-9 rx_error_cnt setzen oder lesen Empfangsfehlerzähler h0
8-0 tx_error_cnt setzen oder lesen Sendefehlerzähler h0
4 Fehlerwarnungs-Reg. warn_state Schreiben nur im Config_Mode & Extended_Mode
17-8 (nur Lesen) nicht genutzt h0
7-0 error_warning_limit setzt Errorwarnungswert (96 = 0x60) h60
5 ACF Adress-Reg. acf_select Schreiben nur im Config_Mode
17-5 nicht genutzt
4-0 acf_adr ACF-Adresse setzen übernimmt die Filterregeln in Register 6-9 h0
5 ACF Freigabe acf_enable Schreiben und lesen, wenn kein Config_Mode
17-0 acf_en Jeder ACF-Filter wird mit einer 1 freigegeben. Sind alle Bits 0, werden alle Telegramme angenommen. h0
6 ACF Code-Reg.1 acf_ac1 Schreiben nur im Config_Mode
17 ac_rtr1 setzt ACF Code für RTR Bit (SSR bei Ext. Frames) b0
16 ac_rtr2 setzt ACF Code für RTR Bit für Ext. Frames b0
15-12 ac_data setzt ACF Code für ersten 4 Bit des Datenteils h0
11 ac_we ist 1 solange das Schreiben noch nicht beendet (read only) b0
10-0 ac_b_id setzt ACF Code für die ersten 11 Bit Identifier h0
7 ACF Masken-Reg. 1 acf_am1 Schreiben nur im Config_Mode (gesetzte Bits werden nicht Verglichen)
17 am_rtr1 setzt ACF Maske für RTR Bit (SSR bei Ext. Frames) b0
16 am_rtr2 setzt ACF Maske für RTR Bit für Ext. Frames b0
15-12 am_data setzt ACF Maske für ersten 4 Bit des Datenteils hF
11 frei b0
10-0 am_b_id setzt ACF Maske für die ersten 11 Bit Identifier h7FF
8 ACF Code-Reg. 2 acf_ac2 Schreiben nur im Config_Mode
17-0 ac_e_id setzt den ACF Code für den zweiten 18 Bit Identifier h0
9 ACF Masken-Reg. 2 acf_am2 Schreiben nur im Config_Mode (gesetzte Bits werden nicht Verglichen)
17-0 am_e_id setzt die ACF Maske für den zweiten 18 Bit Identifier h3FFFF
10 Fehler-Code-Reg. error_code (nur Lesen) Schreiben setzt Exception Interrupt zurück
17 error_warning gesetzt, wenn error_warning_limit überschritten b0
16 error_dirction 0 - CAN write / 1 - CAN read b0
15 frei b0
14-12 error_typ Bit-, Form-, Stuff-, CRC-, ACK-Error h0
11-9 frei h0
8-4 Zustand des Rx Automat h0
3 node_error_passive gesetzt, wenn der Controller nur noch passiv mithört (127 < Fehlerzähler <= 255) b0
2 node_bus_off gesetzt, wenn sich der Controller vom Bus getrennt hat (Fehlerzähler > 255) b0
1 rx_buffer_full_q gesetzt wenn RX Puffer voll b0
0 send_failed_q gesetzt wenn Senden endgültig fehlschlug b0
11 TX Success-Reg. tx_succ (nur Lesen) Schreiben setzt TX Interrupt zurück
9-0 tx_start_adr Adresse die als letztes aus TX Puffer gelesen wurde h0
12 RX Success-Reg. rx_succ (nur Lesen) Schreiben setzt RX Interrupt zurück
9-0 rx_start_adr Adresse die als letztes im RX Puffer geschrieben wurde h0
13 TX Puffer-Reg. tx_buffer Schreiben und Lesen immer möglich
17-0 tx_request_buffer Belegungsstatus des TX Puffer (1= voll, 0= leer) h0
14 RX Puffer-Reg. rx_buffer Schreiben und Lesen immer möglich
17-0 rx_used_buffer Belegungsstatus des RX Puffer (1= voll, 0= leer) h0

Berechnung der CAN-Bitfrequenz aus den Werten im Bus-Timing Register

f = can_clk / ( (BRP+2)*(1+tseg1+tseg2+2) ) = 28000 kHz / ( (6+2)*(1+21+4+2) ) = 28000 kHz / (8*28) = 125 kHz
  • Je größer die Summe von (1+tseg1+tseg2+2), desto besser kann synchronisiert werden.
  • Je größer SJW, desto mehr Bits kann der Synchronisationszeitpunkt automatisch verschoben werden.
  • Mit SJW wird entweder die Periodendauer vergrößert durch (tseg1 + SJW) oder verkleinert mit (tseg2 - SJW) um den Synchronisationszeitpunkt von Sender und Empfänger wieder anzugleichen.
  • Der Teilerwert, der sich aus 1+ tseg1 + tseg2 + 2 ergibt, ist die Anzahl der Zeitquanten (tq) der Nominal CAN Bit Time = 100%
  • tseg2+2 Minimum sollte > (100 - 87,5)% = 12,5% von der Nominal CAN Bit Time betragen.
  • tseg2+2 Maximum sollte < (100 - 75,0)% = 25,0% von der Nominal CAN Bit Time betragen.
Baudrate BRP SJW tseg1 tseg2 Bus-Timing Reg. tseg2+2 in % tseg2+2 in % bei +SJW tseg2+2 in % bei -SJW
8 Bit 2 Bit 5 Bit 3 Bit Summe = 18 Bit
1000 kBit/s 0 1 10 1 0x00151 21,4 (3/(1+11+3))*100=20,0 (2/(1+10+2))*100=15,4
500 kBit/s 0 2 21 4 0x002AC 21,4 (6/(1+23+6))*100=20,0 (4/(1+21+4))*100=15,4
250 kBit/s 2 2 21 4 0x00AAC 21,4 (6/(1+23+6))*100=20,0 (4/(1+21+4))*100=15,4
125 kBit/s 6 2 21 4 0x01AAC 21,4 (6/(1+23+6))*100=20,0 (4/(1+21+4))*100=15,4
100 kBit/s 6 3 26 6 0x01BD6 22,9 (8/(1+29+8))*100=21,1 (5/(1+26+5))*100=15,6
50 kBit/s 14 3 26 6 0x03BD6 22,9 (8/(1+29+8))*100=21,1 (5/(1+26+5))*100=15,6
20 kBit/s 38 3 26 6 0x09BD6 22,9 (8/(1+29+8))*100=21,1 (5/(1+26+5))*100=15,6
10 kBit/s 78 3 26 6 0x13BD6 22,9 (8/(1+29+8))*100=21,1 (5/(1+26+5))*100=15,6
5 kBit/s 158 3 26 6 0x27BD6 22,9 (8/(1+29+8))*100=21,1 (5/(1+26+5))*100=15,6

* BRP - Baud Rate Prescaler (0 ... 253)
* SJW - Synchronization Jump Width (1 ... 3)
* tseg1 - Time Segment 1 (= Prop_Segment + Phase_Segment_1) (4 ... 31)
* tseg2 - Time Segment 2 -2 (= Phase_Segment_2 -2) (0 ... 7)

Bits des Fehler-Code-Register

Bit Nummern              | cy - Feld (Fehlertype) | w  - Error Warning
11 .111 ...0 0000  0000  | 001  Form-Error        |
76 .432 ...8 7654  3210  | 010  Stuff-Error       | cd - Datenrichtung
Bit Felder und Signale   | 011  ACK-Error         |  0 - CAN write
wc .ccc ...c cccc  nnft  | 100  CRC-Error         |  1 - CAN read
 d .yyy ...s ssss  po x  | 101  Bit-Error         |
                         | 111  alle anderen      | np - node error passiv
--------------------------------------------------|
cs - Feld (Zustand des Automaten)                 | no - node bus off
0 0000 -                                          |
0 0001 -                                          | f  - rx Puffer alle belegt
0 0010 - id1                                      |
0 0011 - idle                                     | tx - senden engültig fehlgeschlagen 
0 0100 - rtr1
0 0101 - ide
0 0110 - id1 & (bit_cnt > 7)
0 0111 - id2 & (bit_cnt < 5)
0 1000 - crc
0 1001 - r0
0 1010 - data
0 1011 - dlc
0 1100 - rtr2
0 1101 - r1
0 1110 - id2 & (bit_cnt > 13)
0 1111 - id2 & (bit_cnt > 4) & (bit_cnt < 13)
1 0000 - error_lim
1 0001 - error & node_error_active
1 0010 - inter
1 0011 - 
1 0100 - overload_lim
1 0101 - 
1 0110 - error & node_error_passive
1 0111 - 
1 1000 - crc_lim
1 1001 - ack
1 1010 - eof
1 1011 - ack_lim
1 1100 - overload
1 1101 - 
1 1110 - data >0
1 1111 -

Offset im DMA Puffer für den TX Puffer mit der höchsten Priorität abgeleitet aus dem Inhalt vom TX Puffer-Register bei 18 Puffern.


Register Belegung von          BlockRam Word         Adresse
tx_buffer                      Adressen              in C

1x xxxx xxxx xxxx xxxx   -->   00 0000 0000 =  0*8 = data_tx00
01 xxxx xxxx xxxx xxxx   -->   00 0000 1000 =  1*8 = data_tx01
00 1xxx xxxx xxxx xxxx   -->   00 0001 0000 =  2*8 = data_tx02
00 01xx xxxx xxxx xxxx   -->   00 0001 1000 =  3*8 = data_tx03
00 001x xxxx xxxx xxxx   -->   00 0010 0000 =  4*8 = data_tx04
00 0001 xxxx xxxx xxxx   -->   00 0010 1000 =  5*8 = data_tx05
00 0000 1xxx xxxx xxxx   -->   00 0011 0000 =  6*8 = data_tx06
00 0000 01xx xxxx xxxx   -->   00 0011 1000 =  7*8 = data_tx07
00 0000 001x xxxx xxxx   -->   00 0100 0000 =  8*8 = data_tx08
00 0000 0001 xxxx xxxx   -->   00 0100 1000 =  9*8 = data_tx09
00 0000 0000 1xxx xxxx   -->   00 0101 0000 = 10*8 = data_tx10
00 0000 0000 01xx xxxx   -->   00 0101 1000 = 11*8 = data_tx11
00 0000 0000 001x xxxx   -->   00 0110 0000 = 12*8 = data_tx12
00 0000 0000 0001 xxxx   -->   00 0110 1000 = 13*8 = data_tx13
00 0000 0000 0000 1xxx   -->   00 0111 0000 = 14*8 = data_tx14
00 0000 0000 0000 01xx   -->   00 0111 1000 = 15*8 = data_tx15
00 0000 0000 0000 001x   -->   00 1000 0000 = 16*8 = data_tx16
00 0000 0000 0000 0001   -->   00 1000 1000 = 17*8 = data_tx17
00 0000 0000 0000 0000   -->   alle Puffer leer

In C werden die Puffer mit zB.: CAN_0_DMA->data_tx00 angesprochen.

Offset im DMA Puffer für den ersten freien RX Puffer abgeleitet aus dem Inhalt vom RX Puffer-Register bei 18 Puffern.


Register Belegung von          Nummer des                   BlockRam Word      Adresse
rx_buffer                      rx_block                     Adresse            in C

0x xxxx xxxx xxxx xxxx   --> ( 0 0000 + 18 ) * 8 =  00 1001 0000 = ( 0+18)*8 = data_rx00
10 xxxx xxxx xxxx xxxx   --> ( 0 0001 + 18 ) * 8 =  00 1001 1000 = ( 1+18)*8 = data_rx01
11 0xxx xxxx xxxx xxxx   --> ( 0 0010 + 18 ) * 8 =  00 1010 0000 = ( 2+18)*8 = data_rx02
11 10xx xxxx xxxx xxxx   --> ( 0 0011 + 18 ) * 8 =  00 1010 1000 = ( 3+18)*8 = data_rx03
11 110x xxxx xxxx xxxx   --> ( 0 0100 + 18 ) * 8 =  00 1011 0000 = ( 4+18)*8 = data_rx04
11 1110 xxxx xxxx xxxx   --> ( 0 0101 + 18 ) * 8 =  00 1011 1000 = ( 5+18)*8 = data_rx05
11 1111 0xxx xxxx xxxx   --> ( 0 0110 + 18 ) * 8 =  00 1100 0000 = ( 6+18)*8 = data_rx06
11 1111 10xx xxxx xxxx   --> ( 0 0111 + 18 ) * 8 =  00 1100 1000 = ( 7+18)*8 = data_rx07
11 1111 110x xxxx xxxx   --> ( 0 1000 + 18 ) * 8 =  00 1101 0000 = ( 8+18)*8 = data_rx08
11 1111 1110 xxxx xxxx   --> ( 0 1001 + 18 ) * 8 =  00 1101 1000 = ( 9+18)*8 = data_rx09
11 1111 1111 0xxx xxxx   --> ( 0 1010 + 18 ) * 8 =  00 1110 0000 = (10+18)*8 = data_rx10
11 1111 1111 10xx xxxx   --> ( 0 1011 + 18 ) * 8 =  00 1110 1000 = (11+18)*8 = data_rx11
11 1111 1111 110x xxxx   --> ( 0 1100 + 18 ) * 8 =  00 1111 0000 = (12+18)*8 = data_rx12
11 1111 1111 1110 xxxx   --> ( 0 1101 + 18 ) * 8 =  00 1111 1000 = (13+18)*8 = data_rx13
11 1111 1111 1111 0xxx   --> ( 0 1110 + 18 ) * 8 =  01 0000 0000 = (14+18)*8 = data_rx14
11 1111 1111 1111 10xx   --> ( 0 1111 + 18 ) * 8 =  01 0000 1000 = (15+18)*8 = data_rx15
11 1111 1111 1111 110x   --> ( 1 0000 + 18 ) * 8 =  01 0001 0000 = (16+18)*8 = data_rx16
11 1111 1111 1111 1110   --> ( 1 0001 + 18 ) * 8 =  01 0001 1000 = (17+18)*8 = data_rx17
11 1111 1111 1111 1111   --> alle Puffer voll

In C werden die Puffer mit z.B.: CAN_0_DMA->data_rx00 angesprochen.

Anordnung der Telegramme im DMA-Speicher

Durch die oben dargestellte Zuordnung der Bits in den Registern rx_buffer = 0x36000 und tx_buffer = 0x2c000 ergibt sich folgender Aufbau Rx Puffer nach dem 1. Aufruf des Selbsttest.
Word Adr. im Blockram Inhalt des 18 Bit Wort freie Inhalt initialisiert durch can_init.c Bemerkung
hexadezimal Telegrammnummer/Inhalt bits hexadezimal aus can_init.c
0x000 TX 1 / frei, Byte 0, Byte 1 2 0x0f0f0 0,0,data0,data1 (00 11110000 11110000)
0x001 TX 1 / frei, Byte 2, Byte 3 2 0x0aa55 0,0,data2,data3 (00 10101010 01010101)
0x002 TX 1 / frei, Byte 4, Byte 5 2 0x0f0f0 0,0,data4,data5 (00 11110000 11110000)
0x003 TX 1 / frei, Byte 6, Byte 7 2 0x0aa55 0,0,data6,data7 (00 10101010 01010101)
0x004 TX 1 / Extended ID 0 0x00000 extID (00 00000000 00000000)
0x005 TX 1 / RTR, IDE, DLC, frei, Standard ID 1 0x28555 stdID (10 1000 0 10101010101)Remoteframe 8 Byte
0x006 TX 1 / frei, Retry Zähler -1 12 0x00003 retry_tx -1 (00 0000 0000 00 000011)
0x007 TX 1 / frei 18 0x03000 leere Speicherstelle
0x008 TX 2 / frei, Byte 0, Byte 1 2 0x0cc33 0,0,data0,data1 (00 11001100 00110011)
0x009 TX 2 / frei, Byte 2, Byte 3 2 0x0f0f0 0,0,data2,data3 (00 11110000 11110000)
0x00A TX 2 / frei, Byte 4, Byte 5 2 0x0cc33 0,0,data4,data5 (00 11001100 00110011)
0x00B TX 2 / frei, Byte 6, Byte 7 2 0x0f0f0 0,0,data6,data7 (00 11110000 11110000)
0x00C TX 2 / Extended ID 0 0x00000 extID (00 00000000 00000000)
0x00D TX 2 / RTR, IDE, DLC, frei, Standard ID 1 0x0841f stdID (00 1000 0 10000011111) 8 Byte
0x00E TX 2 / frei, Retry Zähler -1 18 0x00000 retry_tx -1 (00 0000 0000 00 000000)
0x00F TX 2 / frei 18 0x00000 leere Speicherstelle
0x010 TX 3 / frei, Byte 0, Byte 1 2 0x0cc33 0,0,data0,data1 (00 11001100 00110011)
0x011 TX 3 / frei, Byte 2, Byte 3 2 0x0f0f0 0,0,data2,data3 (00 11110000 11110000)
0x012 TX 3 / frei, Byte 4, Byte 5 2 0x0cc33 0,0,data4,data5 (00 11001100 00110011)
0x013 TX 3 / frei, Byte 6, Byte 7 2 0x0f0f0 0,0,data6,data7 (00 11110000 11110000)
0x014 TX 3 / Extended ID 0 0x00000 extID (00 00000000 00000000)
0x015 TX 3 / RTR, IDE, DLC, frei, Standard ID 1 0x0841f stdID (00 1000 0 10000011111) 8 Byte
0x016 TX 3 / frei, Retry Zähler -1 18 0x00000 retry_tx -1 (00 0000 0000 00 000000)
0x017 TX 3 / frei 18 0x00000 leere Speicherstelle
0x018 TX 4 / frei, Byte 0, Byte 1 2 0x0f0f0 0,0,data0,data1 (00 11110000 11110000)
0x019 TX 4 / frei, Byte 2, Byte 3 2 0x10000 0,0,data2,data3 (01 00000000 00000000)
0x01A TX 4 / frei, Byte 4, Byte 5 2 0x00000 0,0,data4,data5 (00 00000000 00000000)
0x01B TX 4 / frei, Byte 6, Byte 7 2 0x00000 0,0,data6,data7 (00 00000000 00000000)
0x01C TX 4 / Extended ID 0 0x3C3C3 extID (11 11000011 11000011)
0x01D TX 4 / RTR, IDE, DLC, frei, Standard ID 1 0x12533 extID (01 0010 0 10100110011) Extended ID 2 Byte
0x01E TX 4 / frei, Retry Zähler -1 18 0x00000 retry_tx -1 (00 0000 0000 00 000000)
0x01F TX 4 / frei 18 0x00000 leere Speicherstelle
0x020 TX 5 / frei 18 0x00000 leere Speicherstelle
... ...
0x08F TX 18 / frei 18 0x00000 leere Speicherstelle
Rx Inhalte nach Ausführung des Tests
0x090 RX 1 / frei 18 0x00000 leere Speicherstelle
... ...
0x09F RX 2 / frei 18 0x00000 leere Speicherstelle
0x0A0 RX 3 / frei 18 0x00000 tx1 leere Speicherstelle
0x0A1 RX 3 / frei 18 0x00000 tx1 leere Speicherstelle
0x0A2 RX 3 / frei 18 0x00000 tx1 leere Speicherstelle
0x0A3 RX 3 / frei 18 0x00000 tx1 leere Speicherstelle
0x0A4 RX 3 / frei 18 0x00000 tx1 extID (00 00000000 00000000)
0x0A5 RX 3 / frei 18 0x28555 TX1 stdID (10 1000 0 10101010101) Remoteframe 8 Byte
0x0A6 RX 3 / frei 18 0x3FFF2 TX1 ACF match (11 11111111 11110010)
0x0A7 RX 3 / frei 18 0x0608E CRC des empfangen Telegramms
0x0A8 RX 4 / frei 18 0x00000 leere Speicherstelle
... ...
0x0B7 RX 5 / frei 18 0x00000 leere Speicherstelle
0x0B8 RX 6 / frei 18 0x0CC33 TX3 0,0,data0,data1 (00 11001100 00110011)
0x0B9 RX 6 / frei 18 0x0f0f0 TX3 0,0,data2,data3 (00 11110000 11110000)
0x0BA RX 6 / frei 18 0x0cc33 TX3 0,0,data4,data5 (00 11001100 00110011)
0x0BB RX 6 / frei 18 0x0f0f0 TX3 0,0,data6,data7 (00 11110000 11110000)
0x0BC RX 6 / frei 18 0x00000 TX3 extID (00 00000000 00000000)
0x0BD RX 6 / frei 18 0x0841f TX3 stdID (00 1000 0 10000011111) 8 Byte
0x0BE RX 6 / frei 18 0x3FFF1 TX3 ACF match (11 11111111 11110001)
0x0BF RX 6 / frei 18 0x06A52 CRC des empfangen Telegramms
0x0C0 RX 7 / frei 18 0x0f0f0 TX4 0,0,data0,data1 (00 11110000 11110000)
0x0C1 RX 7 / frei 18 0x00000 tx4 leere Speicherstelle
0x0C2 RX 7 / frei 18 0x00000 tx4 leere Speicherstelle
0x0C3 RX 7 / frei 18 0x00000 tx4 leere Speicherstelle
0x0C4 RX 7 / frei 18 0x3C3C3 TX4 extID (11 11000011 11000011)
0x0C5 RX 7 / frei 18 0x12533 TX4 extID (01 0010 0 10100110011) Extended ID 2 Byte
0x0C6 RX 7 / frei 18 0x3FFF8 TX4 ACF match (11 11111111 11111000)
0x0C7 RX 7 / frei 18 0x007AA CRC des empfangen Telegramms
... ...
0x11F RX 18 / frei 18 0x00000 leere Speicherstelle

Die Filter des CAN-Interface waren dabei wie folgt eingestellt:

Funktion zum setzen der Filter
/*
Setzen der Filter mit der Funktion:

void can_set_acf(struct can *can_p, unsigned int data1, unsigned int maske1, unsigned int data2, unsigned int maske2, unsigned int acf_sel);

aus der Datei can.h
*/

Belegung ACF 1 bis 4
#define ACF_DATA11	0x0041f	// 00,0000. 0, 100_0001_1111  rtr1,rtr2,data0, frei ,stdID
#define ACF_MASK11	0x3f800	// 11,1111, 1, 000_0000_0000  rtr1,rtr2,data0, frei ,stdID
#define ACF_DATA21	0x00000	// exID
#define ACF_MASK21	0x3ffff	// maskierte Bits werden nicht verglichen
#define ACF_SELECT_1	0x00001	// Filter Nummer

#define ACF_DATA12	0x00555	// 00,0000. 0, 101_0101_0101  rtr1,rtr2,data0, frei ,stdID
#define ACF_MASK12	0x3f800	// 11,1111, 1, 000_0000_0000  rtr1,rtr2,data0, frei ,stdID
#define ACF_DATA22	0x00000	// exID
#define ACF_MASK22	0x3ffff	// maskierte Bits werden nicht verglichen
#define ACF_SELECT_2	0x00002	// Filter Nummer

#define ACF_DATA13	0x00720	// 00,0000. 0, 111_0010_0000  rtr1,rtr2,data0, frei ,stdID
#define ACF_MASK13	0x3f800	// 11,1111, 1, 000_0000_0000  rtr1,rtr2,data0, frei ,stdID
#define ACF_DATA23	0x00000	// exID
#define ACF_MASK23	0x3ffff	// maskierte Bits werden nicht verglichen
#define ACF_SELECT_3	0x00003	// Filter Nummer

#define ACF_DATA14	0x00533	// 00,0000. 0, 101_0011_0011  rtr1,rtr2,data0, frei ,stdID
#define ACF_MASK14	0x3f800	// 11,1111, 1, 000_0000_0000  rtr1,rtr2,data0, frei ,stdID
#define ACF_DATA24	0x3c3c3	// exID
#define ACF_MASK24	0x00000	// nicht maskierte Bits werden verglichen
#define ACF_SELECT_4	0x00004	// Filter Nummer

can_set_acf(CAN_0, ACF_DATA11, ACF_MASK11, ACF_DATA21, ACF_MASK21, ACF_SELECT_1);	// = 1
can_set_acf(CAN_0, ACF_DATA12, ACF_MASK12, ACF_DATA22, ACF_MASK22, ACF_SELECT_2);	// = 2
can_set_acf(CAN_0, ACF_DATA13, ACF_MASK13, ACF_DATA23, ACF_MASK23, ACF_SELECT_3);	// = 3
can_set_acf(CAN_0, ACF_DATA14, ACF_MASK14, ACF_DATA24, ACF_MASK24, ACF_SELECT_4);	// = 4

CAN_0->acf_select	= 0;			// kein Filter freigegeben

can_init.c (external link) zur Vorinitialisierung der CAN-Telegramme im DMA-Speicher.

can.h (external link) mit der Register und Puffer Struktur des CAN-Interfaces.

Test (external link) der Funktion des SpartanMC CAN-Interface.

Dokumente zum CAN



SpartanMC