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 ?