AnsweredAssumed Answered

CAN module re-transmits frame infinitely when not connected to bus

Question asked by AbdAlMoniem AlHifnawy on Jul 19, 2018

Hello, I'm writing a CAN driver for the S12ZVC using MSCAN, I modified the example code so that it transmits the frame inside the CAN_TX_ISR, it works fine if it is connected to a bus, but if it is not it receives a NACK. and re-transmits the frame again and again until it connects to the bus and receives an ACK.

 

NB. I've made a workaround using CAN_ERR_ISR to stop the TX ISR if an error occurs, but I'm unable to flush the tx buffer or restart the can module; however it works only if I call CAN_send() once, but when I call it inside the loop, it misbehaves as described.

 

here is my code:

int main(void) { 
CAN_init();
//construct frame
txBuffer.id = 0x5A;
txBuffer.data[0] = 0x23;
txBuffer.data[1] = 0x08;
txBuffer.data[2] = 0x93;txBuffer.length = 1;
txBuffer.priority = 0;
CAN_send(&txBuffer);
for(;;){}
}

//sends a CAN message
void CAN_send(transmitBuffer *txBuffer) {
bTxBuffer = txBuffer;

//prepare frame
CAN0TBSEL = CAN0TFLG; /* select lowest empty buffer */
bTxBuffer->bufferNumber = CAN0TBSEL;

//enable tx interrupt
CAN0TFLG_TXE = bTxBuffer->bufferNumber;
CAN0TIER_TXEIE = bTxBuffer->bufferNumber;

//enable can change status interrupt
CAN0RIER_CSCIE = 0x01;

//enable interrupts on TxErr or Bus-Off
CAN0RIER_TSTATE = 0x02;
}

//CAN message transmission interrupt
void interrupt VectorNumber_Vcan0tx CAN_TX_ISR() {
uint8 index;

//prepare frame
CAN0TBSEL = CAN0TFLG; /* select lowest empty buffer */
bTxBuffer->bufferNumber = CAN0TBSEL;

//load ID
CAN0TXIDR0 = (bTxBuffer->id & 0b11111111000) >> 3;
CAN0TXIDR1 = (bTxBuffer->id & 0b00000000111) << 5;

//load data for(index = 0; index < bTxBuffer->length; index++) {
*(&CAN0TXDSR0 + index) = bTxBuffer->data[index];
}

//send frame
CAN0TXDLR = bTxBuffer->length; /* set data length */
CAN0TXTBPR = bTxBuffer->priority; /* set priority */

//clear tx interrupt flag
CAN0TFLG_TXE = bTxBuffer->bufferNumber; /* start transmission */
}

void interrupt VectorNumber_Vcan0err CAN_ERR_ISR() {
CAN0TARQ = 0x07;
while (!(CAN0TAAK & 0x07)){}

//clear can change status flag
CAN0RFLG_CSCIF = 1;

//disable tx interrupt
CAN0TIER_TXEIE = 0;

//clear tx flag
//CAN0TFLG = 0x07;
}

Outcomes