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; }
Hi,
when Tx node does not receive ACK it goes to an error passive node and tries to send message in a loop.
The solution is ABORT (MSCAN Transmitter Message Abort Request Register (CANTARQ)
Best regards,
Ladislav
Hi @lama ,
I alse have this problem with my project.
How do I know the connecting status of CAN.
Here is the waveform without CAN connecting
Thank you for your answer
I do this in the CAN_ERR_ISR, but what happens is that it aborts the message, triggers a TX interrupt then goes to the CAN_TX_ISR which in turn resends the message again.
is there something I should do ?