Así que estoy en medio de mi primer PIC proyecto, y ha sido cuanto menos interesante. El problema que estoy teniendo es la configuración de los módulos CAN. El PIC que estoy usando tiene dos módulos ECAN. Usando los ejemplos de código proporcionados, he configurado 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 intento usar el mismo código con CAN2 (el segundo módulo del PIC). Transmite algunos datos, pero no el que he configurado en el búfer; todo lo que veo es 0x0000 en todo el paquete.
Mi código procede en su mayor parte de las notas de aplicación de ECAN, con algunos retoques de configuración. CAN1 funciona bien, pero CAN2 no. Cuando pido a ambos módulos que transmitan (CAN1 primero y luego CAN2), sólo CAN1 funciona, pero CAN2 no se mueve en absoluto (no tengo ni idea de por qué). Cuando apago CAN1 y sólo pido CAN2 para transmitir, como se mencionó anteriormente, funciona, pero sólo transmite 0 (parece que no está hablando con el DMA correctamente, a pesar de que estoy usando el mismo código probado y comprobado que he utilizado para CAN1).
Configurar 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
Ajustar la velocidad del bus CAN (Esta es una función de la biblioteca de periféricos):
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 utilizando el mismo código para ambos módulos. Sólo cambio los 1's por los 2's para los nombres de las direcciones. Por ejemplo, C1TR01CON para CAN1 se convierte en C2TR01CON para CAN2, etc.
0 votos
Estás utilizando dos motores DMA separados para los dos módulos CAN, ¿verdad?
0 votos
Sí, un DMA diferente para cada módulo.
1 votos
Después de horas y horas de prueba y error parece que he reducido a un fallo de dirección DMA (?). Cualquier DMA, cuando se configura para CAN2 parece generar una gran cantidad de basura mediante la lectura de la memoria intermedia especificada desde una extraña ubicación desplazada. No tengo ni idea de lo que está pasando: Por ejemplo, si cambio los bytes en el búfer en relación con los paquetes de datos, en lugar de la parte CAN ID del mensaje se ve afectada. Completamente perdido.
0 votos
Asegúrese de que los búferes están en la memoria DMA. En algunas partes, el motor DMA sólo puede acceder a una parte limitada de la RAM.
0 votos
¿Cómo puedo asegurarme de ello? Bueno, he seguido religiosamente la hoja de datos y me estoy volviendo loco. CAN2 se comporta de manera extraña, estoy completamente perdido.