Wie richte ich beide CAN-Module auf dem PIC DSPIC33EP128GM604 ein?

Ich bin also mitten in meinem ersten richtigen PIC- Projekt, und es war, gelinde gesagt, interessant. Mein Problem ist die Einrichtung der CAN-Module. Der PIC, den ich verwende, hat zwei ECAN-Module. Mit den bereitgestellten Codebeispielen habe ich CAN1 (Modul 1) eingerichtet, um eine Nachricht zu übertragen, und es funktioniert absolut gut. Ich kann das Signal auf dem bezeichneten I/O-Pin sehen.

Das Problem ist, wenn ich versuche, denselben Code mit CAN2 (das zweite Modul auf dem PIC) zu verwenden. Es überträgt einige Daten, aber nicht die, die ich im Puffer eingerichtet habe; Alles, was ich sehe, ist 0x0000 im gesamten Paket.

Mein Code stammt größtenteils aus den ECAN-Anwendungshinweisen, mit meinen wenigen Konfigurationswochen. CAN1 funktioniert einwandfrei, CAN2 jedoch nicht. Wenn ich beide Module zum Senden auffordere (zuerst CAN1, dann CAN2), funktioniert nur CAN1, aber CAN2 bewegt sich überhaupt nicht (ich habe keine Ahnung warum). Wenn ich CAN1 ausschalte und nur CAN2 zum Senden auffordere, wie oben erwähnt, funktioniert es, sendet aber nur Nullen (es scheint, als würde es nicht richtig mit dem DMA sprechen, obwohl ich denselben bewährten Code verwende, der Ich habe für CAN1) verwendet.

Richten Sie DMA1 für die CAN-Übertragung ein:

DMA1CONbits.SIZE = 0x0;
DMA1CONbits.DIR = 0x1; //From peripheral to DMA
DMA1CONbits.AMODE = 0x2;
DMA1CONbits.MODE = 0x0;
DMA1REQ = 70;
DMA1CNT = 7; //Data length
DMA1PAD = (volatile unsigned int) &C1TXD; //Point to peripheral register
DMA1STAL = (unsigned int) &CAN1MsgBuf; //Point to buffer
DMA1STAH = (unsigned int) &CAN1MsgBuf; //Point to buffer
DMA1CONbits.CHEN = 0x1; //Enable

CAN-Bus-Geschwindigkeit einstellen (Dies ist eine periphere Bibliotheksfunktion):

CAN1Initialize(CAN_SYNC_JUMP_WIDTH2 &
               CAN_BAUD_PRE_SCALE(4),
               CAN_WAKEUP_BY_FILTER_DIS &
               CAN_PHASE_SEG2_TQ(3) &
               CAN_PHASE_SEG1_TQ(3) &
               CAN_PROPAGATIONTIME_SEG_TQ(3) &
               CAN_SEG2_FREE_PROG &
               CAN_SAMPLE1TIME); //CAN-IN

Senden Sie die Daten:

    C1TR01CONbits.TXEN0 = 0x1;
    C1TR01CONbits.TX0PRI = 0x3;

    /* At this point the ECAN1 module is ready to transmit a message. Place the ECAN module in
       Normal mode. */
    C1CTRL1bits.REQOP = 0;
    while (C1CTRL1bits.OPMODE != 0)
        ;

    /* Write to message buffer 0. */
    /* CiTRBnSID = 0bxxx1 0010 0011 1100
       IDE = 0b0
       SRR = 0b0
       SID<10:0>= 0b100 1000 1111 */

    unsigned int ID = 0xB1;
    CAN1MsgBuf[0][0] = ID<<2;
    /* CiTRBnEID = 0bxxxx 0000 0000 0000
       EID<17:6> = 0b0000 0000 0000 */

    CAN1MsgBuf[0][1] = 0x0000;
    /* CiTRBnDLC = 0b0000 0000 xxx0 1111
       EID<17:6> = 0b000000
       RTR = 0b0
       RB1 = 0b0
       RB0 = 0b0
       DLC = 0b1111 */
    CAN1MsgBuf[0][2] = 0x0008;

    /* Write message data bytes */
    CAN1MsgBuf[0][3] = 0xabcd;
    CAN1MsgBuf[0][4] = 0xabcd;
    CAN1MsgBuf[0][5] = 0xabcd;
    CAN1MsgBuf[0][6] = 0xabcd;

    /* Request message buffer 0 transmission */
    C1TR01CONbits.TXREQ0 = 0x1;

    /* The following shows an example of how the TXREQ bit
       can be polled to check if transmission is complete. */
    while (C1TR01CONbits.TXREQ0 == 1)
        ;

    /* Message was placed successfully on the bus. */

Ich verwende den gleichen Code für beide Module. Ich tausche nur die 1er auf die 2er für die Adressnamen. Beispielsweise wird C1TR01CON für CAN1 zu C2TR01CON für CAN2 usw.

Sie verwenden zwei separate DMA-Engines für die beiden CAN-Module, richtig?
Yup, ein anderer DMA für jedes Modul.
Nach stundenlangem Versuch und Irrtum schien ich es auf einen DMA-Adressfehler (?) eingegrenzt zu haben. Jeder DMA, der für CAN2 konfiguriert ist, scheint eine Menge Müll zu erzeugen, indem er den angegebenen Puffer von einer seltsam versetzten Stelle ausliest. Ich habe keine Ahnung, was los ist: Wenn ich zum Beispiel die Bytes im Puffer in Bezug auf die Datenpakete ändere, wird stattdessen der CAN-ID-Teil der Nachricht beeinflusst. Vollständig verloren.
Stellen Sie sicher, dass sich die Puffer im DMA-Speicher befinden. Auf einigen Teilen kann die DMA-Engine nur auf einen begrenzten Teil des RAM zugreifen.
Wie stelle ich das sicher? Nun, ich habe das Datenblatt religiös befolgt und werde verrückt. CAN2 verhält sich so seltsam, ich bin völlig verloren.

Antworten (1)

Argh, ich habe endlich herausgefunden, was falsch war. Das Initialisieren des DMA für das CAN-Modul (oder anderweitig) umfasst:

  1. Auf das Peripherals Register zeigen --> Das hatte ich richtig gemacht

  2. Hinweis auf die verwendeten Puffer ---> Das hatte ich auch richtig gemacht

  3. Auswahl des erforderlichen Peripheriegeräts als Interruptquelle für den DMA --> Ich hatte dies für CAN1 ( DMA1REQ = 70;) richtig gemacht, aber ich habe dies nicht geändert, als ich den Code kopierte, um den DMA für CAN2 einzurichten, der IRQ 71 und nicht 70 war! Wenn Sie dies DMA1REQ = 71für CAN2 ändern, wurde alles behoben!

Hallo Adil, es fällt mir schwer, mein ECAN-Peripheriegerät für DSPIC33EP64GS804 zu konfigurieren. Ist es Ihnen möglich, den ECAN-Code zu teilen?