Forum: Mikrocontroller und Digitale Elektronik CAN / mcp2515: rtr bit immer gesetzt


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Philipp H. (atmega-bastler)


Bewertung
0 lesenswert
nicht lesenswert
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

von Bastian W. (jackfrost)


Bewertung
0 lesenswert
nicht lesenswert
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

von H.Joachim S. (crazyhorse)


Bewertung
0 lesenswert
nicht lesenswert
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.

von Bastian W. (jackfrost)


Bewertung
0 lesenswert
nicht lesenswert
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

von H.Joachim S. (crazyhorse)


Bewertung
0 lesenswert
nicht lesenswert
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.

von Philipp H. (atmega-bastler)


Bewertung
0 lesenswert
nicht lesenswert
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
von H.Joachim S. (crazyhorse)


Bewertung
0 lesenswert
nicht lesenswert
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.

von Philipp H. (atmega-bastler)


Bewertung
0 lesenswert
nicht lesenswert
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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.