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.
Argh, ich habe endlich herausgefunden, was falsch war. Das Initialisieren des DMA für das CAN-Modul (oder anderweitig) umfasst:
Auf das Peripherals Register zeigen --> Das hatte ich richtig gemacht
Hinweis auf die verwendeten Puffer ---> Das hatte ich auch richtig gemacht
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 = 71
für CAN2 ändern, wurde alles behoben!
Olin Lathrop
MAM
MAM
Olin Lathrop
MAM