Hello, I am using the CAN interface of the MCF51AC256 microcontroller. I have managed to make it transmit and receive messages, but when I try transmitting 3 messages one after another, it transmits more than I want.
More precisely, I want to transmit TX0, then TX1 and then TX2. But it transmits TX0, TX1, then TX0, TX1, TX2, and then TX0, TX1, TX2.
It seems that the TXE flag is not set after each transmission, as it should be... I have gone through the reference manual several times to see whether I have missed something in the register functioning system, but I can't find anything wrong. Can someone help?
Here is the code I'm using:
/* transmit (buffer TX0) */
while (!CANTFLG_TXE0) // wait till buffer TX0 is empty
{
;
}
CANTBSEL_TX0 = 1; // select buffer TX0
CANTDLR = 8; // 8-byte message length
CANTIDR0 = 0x0C; // ID = 100
CANTIDR1 = 0x80; // bit 4 = 0 : data frame
// bit 3 = 0 : standard identifier
CANTDSR0 = pot[0]; // copier valeurs à transmettre
CANTDSR1 = pot[1];
CANTDSR2 = pot[2];
CANTDSR3 = pot[3];
CANTDSR4 = pot[4];
CANTDSR5 = pot[5];
CANTDSR6 = pot[6];
CANTDSR7 = pot[7];
CANTBSEL_TX0 = 0; // deselect buffer TX0
CANTFLG_TXE0 = 1; // buffer full, clear flag to transmit
// (writing 1 clears flag)
/* transmit (buffer TX1) */
while (!CANTFLG_TXE1) // wait till buffer TX1 is empty
{
;
}
CANTBSEL_TX1 = 1; // select buffer TX1
CANTDLR = 8; // 8-byte message length
CANTIDR0 = 0x0C; // ID = 101
CANTIDR1 = 0xA0; // bit 4 = 0 : data frame
// bit 3 = 0 : standard identifier
CANTDSR0 = pot[8]; // copier valeurs à transmettre
CANTDSR1 = pot[9];
CANTDSR2 = pot[10];
CANTDSR3 = pot[11];
CANTDSR4 = pot[12];
CANTDSR5 = pot[13];
CANTDSR6 = pot[14];
CANTDSR7 = pot[15];
CANTBSEL_TX1 = 0; // deselect buffer TX1
CANTFLG_TXE1 = 1; // buffer full, clear flag to transmit
// (writing 1 clears flag)
/* transmit (buffer TX2) */
while (!CANTFLG_TXE2) // wait till buffer TX2 is empty
{
;
}
CANTBSEL_TX2 = 1; // select buffer TX2
CANTDLR = 8; // 8-byte message length
CANTIDR0 = 0x0C; // ID = 102
CANTIDR1 = 0xC0; // bit 4 = 0 : data frame
// bit 3 = 0 : standard identifier
CANTDSR0 = pot[16]; // copier valeurs à transmettre
CANTDSR1 = pot[17];
CANTDSR2 = pot[18];
CANTDSR3 = pot[19];
CANTDSR4 = pot[20];
CANTDSR5 = pot[21];
CANTDSR6 = pot[22];
CANTDSR7 = pot[23];
CANTBSEL_TX2 = 0; // deselect buffer TX2
CANTFLG_TXE2 = 1; // buffer full, clear flag to transmit
// (writing 1 clears flag)
I would really appreciate any help. Thank you!
Solved! Go to Solution.
CANTFLG_TXE0 = 1; // buffer full, clear flag to transmit
Since 1) flags are cleard writing '1' to them, and 2) CANTFLG register has more flags, red line above will clear all set CANTFLG flags! That's why you send more messages than you really want. Red line can schedule for transmission messages from all 3 Tx buffers. Proper code to send just Tx0 buffer is this:
CANTFLG = CANTFLG_TXE0_MASK;
---------------------
CANTBSEL_TX0 = 0; // deselect buffer TX0
It is absolutely not necessary to clear CANTBSEL bits. If you you would remove ^^ such lines, then you may use another correct code to send single, CANTBSEL-selected buffer:
CANTFLG = CANTBSEL;
This is valid because hardware restricts setting more than just one CANTBSEL bits.
CANTFLG_TXE0 = 1; // buffer full, clear flag to transmit
Since 1) flags are cleard writing '1' to them, and 2) CANTFLG register has more flags, red line above will clear all set CANTFLG flags! That's why you send more messages than you really want. Red line can schedule for transmission messages from all 3 Tx buffers. Proper code to send just Tx0 buffer is this:
CANTFLG = CANTFLG_TXE0_MASK;
---------------------
CANTBSEL_TX0 = 0; // deselect buffer TX0
It is absolutely not necessary to clear CANTBSEL bits. If you you would remove ^^ such lines, then you may use another correct code to send single, CANTBSEL-selected buffer:
CANTFLG = CANTBSEL;
This is valid because hardware restricts setting more than just one CANTBSEL bits.
Thank you so much, it works fine now!!
(though it would have been a lot more logical if CANTFLG_TXE0 allowed us to clear only one buffer...)