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.
Argh, finalmente encontré lo que estaba mal. La inicialización del DMA para el módulo CAN (o de otro modo) incluye:
Apuntando al Registro de Periféricos --> Lo había hecho correctamente
Señalando los búferes en uso ---> También lo había hecho correctamente
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 = 71
CAN2 solucionó todo!
olin lathrop
mamá
mamá
olin lathrop
mamá