Hallo zusammen,
ich habe eine Schaltung zusammen gebaut mit einem ATMEGA32 und einem CAN
Controller MCP2515. Schaltung und Code basieren auf den Daten von
Kreatives-Chaos.com. Da das dortige Tutorial sehr verbreitet ist, hoffe
ich das mir hier jemand helfen kann...
Ich hab versucht eine Nachricht zu senden. Dies schlägt allerdings fehl,
da die Abfrage, ob die Sendepuffer frei sind, immer ein false zurück
liefert.
In dem o.g. Tutorial ist auch ein Democode von dem Can Controller zu
finden. Auch bei diesem Code tritt der gleiche Fehler auf. Zusätzlich
wird in der Initialisierung des Controllers versucht, ein Register
auszulesen, welches zuvor beschrieben wurde. Dies schlägt bei mir auch
fehl (also das auslesen).
Ich habe die Schaltung bereits mehrfach gecheckt und konnte keinen
Fehler finden. Auch die SPI Kommunikation scheint zu funktionieren.
Aktuell weis ich absolut nicht mehr, wo ich noch suchen soll. Falls
jemand eine Idee hat wäre ich wirklich sehr dankbar...
Viele Grüße
Stefan
Ist der Controller allein im Netz? Wenn ja: Das geht bei CAN nicht,
führt zu Dauerfehler mangels Quittierung. In dem Fall solltest du deine
ersten Tests im Loopback-Testmodus machen.
Wär ohnehin kein Fehler, wenn du dir die Status/Error-Register
anschaust.
PS: Das setzt natürlich voraus, dass du den MCP überhaupt ansprechen
kannst. Dein Text erweckt aber etwas undeutlich den Eindruck, dass der
Treiber mit einem Stück Holz redet. Um das also zu klären: Funktioniert
der Zugriff auf die Register des MCP? Wenn nicht: Falsch angeschlossen,
falsche Pindefinitionen, kein Takt und hundert andere Möglichkeiten.
Hi A.K.
danke für deine Nachricht. Ehrlich gesagt bin ich auch etwas verwirrt,
weshalb ich in der mcp init ein Register nicht auslesen konnte (als
Test). Ich habe mittels Oszilloskop allerdings schonmal geschaut, ob die
Pins vom µC während der Datenübertragung mittels SPI richtig geschaltet
werden. Das sieht eigentlich ganz gut aus. Werd wohl nochmal versuchen
ein anderes Register auszulesen, um zu schauen ob das funktioniert.
Ja der Controller ist alleime am Netz. Müsste er nicht im ersten Moment
die Nachricht absenden und erst in den Fehlerzustand gehen, wenn er kein
Ack bekommen hat ? In dem Democode zum MCP2515 ist am Anfang der
Loopback gesetzt und ich hab das gleiche Problem, dass die Sendepuffer
nicht freigegeben sind.
Viele Grüße
Stefan
Stefan schrieb:> Ja der Controller ist alleime am Netz. Müsste er nicht im ersten Moment> die Nachricht absenden und erst in den Fehlerzustand gehen, wenn er kein> Ack bekommen hat ?
ja raussenden wird der controller den frame, also mit dem oszilloskop
zwischen CANH und CANL wirst du was sehen. der controller wird nur
irgendwann in den error modus gehen ohne ack
Welches Register konntest Du nicht verändern?
CNF1, CNT2, CNF3, TXRTSCTRL, Filter und Mask-Register lassen sich nur im
Konfigurationmodus verändern. Dazu CANTCTRL.REQOP auf 0b100 setzen. Bzw.
Bit7 im CANCTRL-Register setzen.
Mit Bit 3 (von 0 angefangen zu zählen) kann man den MCP2515 in den
One-Shot-Modus bringen. Dann sendet er nur einmal die Botschaft und
wartet nicht auf Acknowledge. Dadurch kann man verhindern, dass er zu
schnell in den Fehlermodus springt.
Wenn das alles nichts hilft. Dann einen Software-reset mit dem
SPI-Kommando 0xC0 senden.
Guten Abend zusammen,
vielen Dank für die rege Beteiligung.
Auf der Seite von kreatives-chaos gibt es ein Demo Package zum MCP2515.
Hier wird in der Init nach setzen des Configurationsmodus die Baudrate
eingestellt und anschließend versucht, diese zu lesen. Hier bekomme ich
aber lediglich ein false zurück
1
// reset MCP2515 by software reset.
2
// After this he is in configuration mode.
3
RESET(MCP2515_CS);
4
spi_putc(SPI_RESET);
5
SET(MCP2515_CS);
6
7
// wait a little bit until the MCP2515 has restarted
8
_delay_us(10);
9
10
// load CNF1..3 Register
11
RESET(MCP2515_CS);
12
spi_putc(SPI_WRITE);
13
spi_putc(CNF3);
14
15
spi_putc((1<<PHSEG21));// Bitrate 125 kbps at 16 MHz
16
spi_putc((1<<BTLMODE)|(1<<PHSEG11));
17
spi_putc((1<<BRP2)|(1<<BRP1)|(1<<BRP0));//CNF1
18
19
// activate interrupts
20
spi_putc((1<<RX1IE)|(1<<RX0IE));
21
SET(MCP2515_CS);
22
23
// test if we could read back the value => is the chip accessible?
Warum das nicht funktioniert, ist mir ein Rätsel. Habe auch gerade
versucht manuell ein Bit zu setzen und anschließend auszulesen. Ich kann
leider nicht debuggen, sondern habe nur eine LED zum An-/Ausschalten
1
//... Konfigurationsmodus aktiv...
2
mcp2515_write_register(CNF3,(1<<PHSEG21));//Bit 1
3
uint8_ttest;
4
test=mcp2515_read_register(CNF3);
5
6
if(test=2)
7
{
8
PORTA|=(1<<PA0);
9
}
Das komische ist, vergleiche ich "test" auf 2, leuchtet die LED. 2 ist
auch der erwarte Wert. Vergleiche ich auf 0, bleibt die LED aus. Passt
also auch. Vergleiche ich aber z.B. auf test=1, ist die LED wieder an,
was aber garnicht sein darf, da Bit0 = 0 ist. Versteh ich nicht... ?!
Der Vollständigkeit halber noch die Sende- und Empfangsroutinen:
Den CAN-Controller kann man auch im Loopback-Modus (oder so ähnlich)
betreiben.
Da kann man ihn dann für sich alleine testen, ohne einen weiteren Knoten
zu haben.
Wenn Du das selbst Programmiert hast, dann funktioniert das nicht, weil
Du das Tripel Komando, Register, Daten nicht einhälst.
Stefan schrieb:> // load CNF1..3 Register>> RESET(MCP2515_CS);>> spi_putc(SPI_WRITE);>> spi_putc(CNF3);>>>> spi_putc((1<<PHSEG21)); // Bitrate 125 kbps at 16 MHz>> spi_putc((1<<BTLMODE)|(1<<PHSEG11));>> spi_putc((1<<BRP2)|(1<<BRP1)|(1<<BRP0)); //CNF1>>>> // activate interrupts>> spi_putc((1<<RX1IE)|(1<<RX0IE));>> SET(MCP2515_CS);
Vielleicht funktioniert das hier:
RESET(MCP2515_CS);
/* Kommando 0x02*/
spi_putc(SPI_WRITE);
/* Registeradresse */
spi_putc(CNF3);
/* Daten für CNF3 */
spi_putc((1<<PHSEG21)); // Bitrate 125 kbps at 16 MHz
/* Chip-Select wieder auf 1 -> siehe dazu Fig 11-04*/
/* auf Seite 63 des Datenblattes MCP2515 */
SET(MCP2515_CS);
/*Warten ist hier nicht verkehrt*/
_delay_us(10);
RESET(MCP2515_CS);
/* Kommando 0x02*/
spi_putc(SPI_WRITE);
/* Registeradresse */
spi_putc(CNF2);
/* Daten für CNF2 */
spi_putc((1<<BTLMODE)|(1<<PHSEG11));
SET(MCP2515_CS);
/*Warten ist hier nicht verkehrt*/
_delay_us(10);
RESET(MCP2515_CS);
/* Kommando 0x02*/
spi_putc(SPI_WRITE);
/* Registeradresse */
spi_putc(CNF1);
/* Daten für CNF1 */
spi_putc((1<<BRP2)|(1<<BRP1)|(1<<BRP0)); //CNF1
SET(MCP2515_CS);
/*Warten ist hier nicht verkehrt*/
_delay_us(10);
RESET(MCP2515_CS);
/* Kommando 0x02*/
spi_putc(SPI_WRITE);
/* Registeradresse */
spi_putc(CANINTE);
/* Daten für CANINTE */
spi_putc((1<<RX1IE)|(1<<RX0IE)); //CANINTE1
SET(MCP2515_CS);
/*Warten ist hier nicht verkehrt*/
_delay_us(10);
HIER MUSST DU GENAUSO DEINE FILTER SETZEN FUER DIE MBX 0 und 1
/*ZUM SCHLUSS KONFIGURATIONMODUS AUF NORMALMODUS UMSCHALTEN !!!*/
RESET(MCP2515_CS);
/* Kommando 0x02*/
spi_putc(SPI_WRITE);
/* Registeradresse */
spi_putc(CANCTRL);
/* Daten für CANCTRL BIt 8 löschen -> Normalmodus
/* Bit4 -> OneShotModus */
spi_putc(0x04); //CANCTRL
SET(MCP2515_CS);
Ab hier dann fröhliches Senden und empfangenn
Stefan schrieb:> void mcp2515_write_register( uint8_t adress, uint8_t data )>> {>> // /CS des MCP2515 auf Low ziehen>> PORT_CS &= ~(1<<P_CS);>>>> spi_putc(SPI_WRITE);>> spi_putc(adress);>> spi_putc(data);>>>> // /CS Leitung wieder freigeben>> PORT_CS |= (1<<P_CS);>> }
Hier ist die Reihenfolge richtig. Aber in der Initialisierung wird der
Konfigurationmodus nie verlassen. Abgesehen davon, weiss der MCP beim
besten Willen nicht, was er mit den Informationen anfangen sollen, wenn
man die Reihenfolge Kommando, Register, Daten nicht einhält.
Viel Erfolg
Guten Abend,
Der erste Teil des Quellcodes stammt aus dem DemoCode.
Ich hab ein File angefügt, indem die Funktionen enthalten sind, wie ich
sie nutze (Redundants bereits entfernt).
Ich habe in der can_send_message Funktion auch einen Vermerkt gemacht,
wo bei mir das Problem liegt. Bis auf die Main Funktion stammt der Code
ebenfalls von kreatives Chaos. Bisher hab ich aber nur Beiträge im Netz
gefunden, dass das so funktioniert.
Ich weis nicht mehr weiter -.-
Viele Grüße
Stefan
Also, das sieht soweit o.k. aus.
In meiner Initialisierung habe ich das zuvor beschriebene Register
gelesen und mit der Vorgabe verglichen. Erst dann setzt die
Initialisierung fort.
Ich weiß nicht, ob Du weißt, wo Dein Programm stehen bleibt? Hast Du das
mal gescheckt? Wie wird der MCP getaktet? externer Quarz oder von
Mikrocontroler?
Eine Sache noch: Nach dem Reset (Software) 0xC0 mußt Du mal das CANSTAT
lesen und prüfen, ob 0x100x xxxx vorliegt. Erst dann ist der Controler
im Konfigurationsmodus. Wenn nicht, dann ist klar, warum er nicht
sendet. Er ist dann nicht konfiguriert.
Wenn Du keinen Debugger hast, würde ich zunächst auf einen freien Port
8LEDs anschließen und mit jedem Byte ein Zähler inkrementieren, dann
weißt Du, wo er hängen bleibt.