Hallo zusammen, ich beschäftige mich zurzeit ein wenig mit CAN Bus und dem mcp2515. Allerdings stehe ich derzeit vor einem kleinen Problem, dessen Lösung ich leider alleine nicht finde. Wenn ich eine Nachricht versende, egal ob normal oder loopBack Modus, ist immer das rtr bit gesetzt, obwohl ich dieses beim Senden nicht setze. Das einzige was im empfangenen Paket stimmt ist die ID, ansonsten ist nichts so wie es sein soll. Kann mir jemand erklären woher das kommt und wie ich das Problem lösen kann? Hier meine Sendefunktion: uint8_t can_send_message(CANMessage *p_message) { uint8_t status, address; // Status des MCP2515 auslesen PORT_CS &= ~(1<<P_CS); spi_putc(SPI_READ_STATUS); status = spi_putc(0xff); spi_putc(0xff); PORT_CS |= (1<<P_CS); if (!(status & (1<<2))) { address = 0x00; } else if (!(status & (1<<4))) { address = 0x02; } else if (!(status & (1<<6))) { address = 0x04; } else { return 0; } PORT_CS &= ~(1<<P_CS); // CS Low spi_putc(SPI_WRITE_TX | address); // Standard ID einstellen spi_putc((uint8_t) (p_message->id>>3)); spi_putc((uint8_t) (p_message->id<<5)); // Extended ID //spi_putc(0x00); //spi_putc(0x00); uint8_t length = p_message->length; if (length > 8) { length = 8; } // Ist die Nachricht ein "Remote Transmit Request" ? if (p_message->rtr) { // Nachrichten Laenge + RTR einstellen spi_putc((1<<RTR) | length); } else { // Nachrichten Laenge einstellen spi_putc(length); // Daten for (uint8_t i=0;i<length;i++) { spi_putc(p_message->data[i]); } } PORT_CS |= (1<<P_CS); // CS auf High asm volatile ("nop"); PORT_CS &= ~(1<<P_CS); // CS wieder Low if (address == 0x00) { spi_putc(SPI_RTS | 0x01); } else { spi_putc(SPI_RTS | address); } PORT_CS |= (1<<P_CS); // CS auf High return 1; } (stammt von http://www.kreatives-chaos.com, nur leicht modifiziert) das CANMessage struct sieht folgendermaßen aus: typedef struct { uint16_t id; uint8_t rtr; uint8_t length; uint8_t data[8]; } CANMessage; und wird so ausgefüllt: msg.id = 0x0123; msg.length = 1; msg.rtr = 0; msg.data[0] = 0xab; Danke schonmal im vorraus! mfg Philipp
Hi, Ich sende über CAN Statusmeldungen und Sensordaten. Mit dem MCP2515 läuft das ohne Probleme. Du kannst dir die Dateien unter https://github.com/JackFrost80/Wasserzaehler-CAN-Modul/blob/master/CAN.cpp ja mal anschauen. Das Projekt ist für einen Atxmega und in C++ geschrieben. Gruß JackFrost
Gerade mal den alten (funktionierenden) Kram herausgeholt, 2 Unterschiede sind mir aufgefallen: // Standard ID einstellen spi_putc((unsigned char) (p_message->id>>3)); spi_putc((unsigned char) (p_message->id<<5)); // Extended ID spi_putc(0x00); spi_putc(0x00); und: PORTB |= (1<<SPI_CS1); // CS high #asm ("nop"); #asm ("nop"); Ob es daran liegt, kann ich dir nicht sagen, schau ich jetzt nicht nach und probier ich auch nicht aus :-), der MCP2515 ist in der Mottenkiste.
Poste mal einen Frame vom Sende MCP und den gleichen dann vom Empfänger Die EID musst du setzen auch wenn du nur die ID verwendest , sonst ist alles um zwei Bytes verschoben wenn du den Adresspointer nicht neu setzt. Gruß JackFrost
Bastian W. schrieb: > Die EID musst du setzen auch wenn du nur die ID verwendest , sonst ist > alles um zwei Bytes verschoben Dann passt das ja mit den og. 2 Nullbytes, dem gesetzten RTR usw.
H.Joachim S. schrieb: > // Extended ID > spi_putc(0x00); > spi_putc(0x00); Bastian W. schrieb: > Die EID musst du setzen auch wenn du nur die ID verwendest vielen Dank für die Antworten. Daran hats gelegen, funktioniert jezt :)) mfg Philipp EDIT: Zumindest im Loopback betrieb. auf dem Bus sind die Nachrichten zu sehen, auch am rx pin des mcp2515 kommen die daten an. Aber ich bekomme leider keinen Interrupt am empfänger :( Der code zum initialisieren sieht folgendermaßen aus: // SPI Interface initialisieren spi_init(); // MCP2515 per Software Reset zuruecksetzten, // danach ist der MCP2515 im Configuration Mode PORT_CS &= ~(1<<P_CS); spi_putc( SPI_RESET ); _delay_ms(1); PORT_CS |= (1<<P_CS); // etwas warten bis sich der MCP2515 zurueckgesetzt hat _delay_ms(10); // BRP = 7 mcp2515_write_register( CNF1, (1<<BRP0)|(1<<BRP1)|(1<<BRP2) ); // Prop Seg und Phase Seg1 einstellen mcp2515_write_register( CNF2, (1<<BTLMODE)|(1<<PHSEG11) ); // Wake-up Filter deaktivieren, Phase Seg2 einstellen mcp2515_write_register( CNF3, (1<<PHSEG21) ); // Aktivieren der Rx Buffer Interrupts mcp2515_write_register( CANINTE, (1<<RX1IE)|(1<<RX0IE) ); /* * Einstellen der Filter */ // Buffer 0 : Empfangen aller Nachrichten mcp2515_write_register( RXB0CTRL, (1<<RXM1)|(1<<RXM0) ); // Buffer 1 : Empfangen aller Nachrichten mcp2515_write_register( RXB1CTRL, (1<<RXM1)|(1<<RXM0) ); // Alle Bits der Empfangsmaske loeschen, // damit werden alle Nachrichten empfangen mcp2515_write_register( RXM0SIDH, 0 ); mcp2515_write_register( RXM0SIDL, 0 ); mcp2515_write_register( RXM0EID8, 0 ); mcp2515_write_register( RXM0EID0, 0 ); mcp2515_write_register( RXM1SIDH, 0 ); mcp2515_write_register( RXM1SIDL, 0 ); mcp2515_write_register( RXM1EID8, 0 ); mcp2515_write_register( RXM1EID0, 0 ); /* * Einstellen der Pin Funktionen */ // Deaktivieren der Pins RXnBF Pins (High Impedance State) mcp2515_write_register( BFPCTRL, 0 ); // TXnRTS Bits als Inputs schalten mcp2515_write_register( TXRTSCTRL, 0 ); // Device zurueck in den normalen Modus versetzten mcp2515_bit_modify( CANCTRL, 0xE0, 0); mfg Philipp
:
Bearbeitet durch User
Hast du denn eigentlich schon irgendetwas selbst gemacht zur Fehlersuche? Du setzt hier den 1:1 kopierten Code (?, sieht zumindest so aus) rein und die einzige Info: Keinen RX-Int. Finde ich persönlich ein bisschen dünne... Die Routinen von kreatives Chaos funktionieren jedenfalls allesamt. D.h. der Fehler wird entweder an der Platine/Verdrahtung liegen oder am Interruptprogramm/Initialisierung des MC.
H.Joachim S. schrieb: > Hast du denn eigentlich schon irgendetwas selbst gemacht zur > Fehlersuche? > Du setzt hier den 1:1 kopierten Code (?, sieht zumindest so aus) rein > und die einzige Info: Keinen RX-Int. Finde ich persönlich ein bisschen > dünne... > Die Routinen von kreatives Chaos funktionieren jedenfalls allesamt. D.h. > der Fehler wird entweder an der Platine/Verdrahtung liegen oder am > Interruptprogramm/Initialisierung des MC. Sorry Hierfür, war ziemlich verzweifelt nachdem ich zwei tage fehler gesucht habe. ABER: Es funktioniert, hatte einen Wackelkontakt auf meinem Steckbrett ;) Vielen Dank nochmal! mfg Philipp
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.