¿Cómo configuro ambos módulos CAN en el PIC DSPIC33EP128GM604?

Así que estoy en medio de mi primer proyecto PIC propiamente dicho , y ha sido interesante por decir lo menos. El problema que tengo es configurar los módulos CAN. El PIC que estoy usando tiene dos módulos ECAN. Usando los ejemplos de código proporcionados, configuré CAN1 (módulo 1) para transmitir un mensaje y funciona absolutamente bien. Puedo ver la señal en el pin de E/S designado.

El problema es cuando trato de usar el mismo código con CAN2 (el segundo módulo en el PIC). Transmite algunos datos, pero no los que configuré en el búfer; todo lo que veo es 0x0000 en todo el paquete.

Mi código proviene principalmente de las notas de la aplicación ECAN, con algunos ajustes de configuración. CAN1 funciona bien, pero CAN2 no. Cuando pido que ambos módulos transmitan (CAN1 primero y luego CAN2), solo funciona CAN1, pero CAN2 no se mueve en absoluto (no tengo idea de por qué). Cuando apago CAN1 y solo le pido a CAN2 que transmita, como se mencionó anteriormente, funciona, pero solo transmite 0 (parece que no está hablando correctamente con el DMA, aunque estoy usando el mismo código probado que Usé para CAN1).

Configure DMA1 para transmisión CAN:

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

Establezca la velocidad del bus CAN (esta es una función de biblioteca periférica):

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

Envía los datos:

    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. */

Estoy usando el mismo código para ambos módulos. Solo cambio los 1 por los 2 para los nombres de las direcciones. Por ejemplo, C1TR01CON para CAN1 se convierte en C2TR01CON para CAN2, etc.

Está utilizando dos motores DMA separados para los dos módulos CAN, ¿verdad?
Sí, un DMA diferente para cada módulo.
Después de horas y horas de prueba y error, parecía haberlo reducido a un error de dirección DMA (?). Cualquier DMA, cuando se configura para CAN2, parece generar mucha basura al leer el búfer especificado desde una ubicación compensada extraña. No tengo idea de lo que está pasando: por ejemplo, si cambio los bytes en el búfer relacionados con los paquetes de datos, en su lugar, se efectúa la parte CAN ID del mensaje. Completamente perdido.
Asegúrese de que los búferes estén en la memoria DMA. En algunas partes, el motor DMA solo puede acceder a una parte limitada de la RAM.
¿Cómo me aseguro de eso? Bueno, he seguido religiosamente la hoja de datos y me estoy volviendo loco. CAN2 se está comportando de manera tan extraña que estoy completamente perdido.

Respuestas (1)

Argh, finalmente encontré lo que estaba mal. La inicialización del DMA para el módulo CAN (o de otro modo) incluye:

  1. Apuntando al Registro de Periféricos --> Lo había hecho correctamente

  2. Señalando los búferes en uso ---> También lo había hecho correctamente

  3. Seleccionando el periférico requerido como la fuente de interrupción para el DMA --> Hice esto correctamente para CAN1 ( DMA1REQ = 70;), pero no cambié esto cuando copié el código para configurar el DMA para CAN2 que era IRQ 71 y no 70. ¡ Cambiar esto a DMA1REQ = 71CAN2 solucionó todo!

Hola adil, tengo dificultades para configurar mi periférico ecan para DSPIC33EP64GS804, ¿es posible que compartas el código ECAN?