I am using the NXP UCANS32K146 development board with the SDK example 'can_pal_s32k146'.
I had to modify the code slightly to get it working with this development board, including additional digital outputs to pull the STB (standby) pin on the CAN transceivers low.
I can get CAN0 or CAN1 to work, but not both at the same time. If I try to use both CAN channels at the same time, CAN1 works but CAN0 stops working and the CAN0 ECR and ESR1 registers shows there are faults...
I have fitted 60R terminating resistors (x2) for each CAN transceiver and both CAN0 and CAN1 are connected together (I measured the total bus impedance to be 60R).
I use a PeakCAN USB with Busmaster to read the CAN messages (PeakCAN has no terminating resistor fitted).
I'm not entirely sure how to configure the CAN peripheral on these processors, so I hoping its just something simple I've missed or done wrong.
The changes I made to the code are shown below - the original code is on the left pane and the modified code is on the right pane.
Below are the Processor Expert settings for both CAN0 and CAN1...
Below is the Tx/Rx pins for CAN1...
Below is the GPIO for the digital outputs (for the CAN transceiver STB pin)...
The project (zip) is attached for reference.
Hi Robin
Interesting to hear it works for you.
I have both CAN0 and CAN1 buses connected together with the PEAK CAN USB spliced into the bus - see picture below...
I have also fitted 60R terminating resistors on the board for both CAN channels i.e. R23 & R24 for CAN1 and R3 & R4 for CAN0...
As both CAN0 and CAN1 buses are connected together, I checked that the bus impedance is 60R.
The root cause is PINS_DRV_SetPinsDirection(STB_PORT, (1 << CAN0_STB)); and PINS_DRV_SetPinsDirection(STB_PORT, (1 << CAN1_STB)); . The default pin setting already configure the direction of CAN0_STB and CAN1_STB as output. But PINS_DRV_SetPinsDirection reconfigure one of pin as input.
The project is able to work on S32K146EVB is due to there is no STB pin on my external CAN transceiver.
Hi
CAN frame can be sent when CAN0_ENABLE or CAN1_ENABLE is defined, but cannot be sent if both are defined at the same time?
Have you try to move the CAN_Send to main function and configure interrupt priority(INT_SYS_SetPriority) for CAN0 and CAN1 and PORTE?
Sorry, only CAN0 connected to the CAN transceiver on S32K146EVB, so it is not convenient for me to test.
Best Regards,
Robin
Thanks Robin
Yes that is correct, CAN frame can be sent when CAN0_ENABLE or CAN1_ENABLE is defined, but cannot be sent if both are defined at the same time.
I added a toggle to the switch ISR, so that each time the button is pressed it will toggle between sending either the CAN0 message or the CAN1 message (but not both).
I did this to avoid any possible conflicts of trying to send a message on CAN0 and CAN1 at the same time.
However, the result is the same i.e.CAN1 works but CAN0 doesn't.
The end goal is to send messages at the same time on both CAN0 and CAN1, because I am trying to emulate a redundant CAN bus.
The code is shown below (where canToggle is used to toggle between message sending)..
void buttonISR(void)
{
/* Check if one of the buttons was pressed */
uint32_t buttonsPressed = PINS_DRV_GetPortIntFlag(BTN_PORT) &
((1 << BTN1_PIN) | (1 << BTN2_PIN));
bool sendFrame = false;
static bool canToggle;
if(buttonsPressed != 0)
{
/* Set FlexCAN TX value according to the button pressed */
switch (buttonsPressed)
{
case (1 << BTN1_PIN):
ledRequested = LED0_CHANGE_REQUESTED;
sendFrame = true;
/* Clear interrupt flag */
PINS_DRV_ClearPinIntFlagCmd(BTN_PORT, BTN1_PIN);
break;
case (1 << BTN2_PIN):
ledRequested = LED1_CHANGE_REQUESTED;
sendFrame = true;
/* Clear interrupt flag */
PINS_DRV_ClearPinIntFlagCmd(BTN_PORT, BTN2_PIN);
break;
default:
PINS_DRV_ClearPortIntFlagCmd(BTN_PORT);
break;
}
if (sendFrame)
{
/* Set information about the data to be sent
* - Standard message ID
* - Bit rate switch enabled to use a different bitrate for the data segment
* - Flexible data rate enabled
* - Use zeros for FD padding
*/
if (canToggle)
{
#ifdef CAN1_ENABLE
can_buff_config_t buffCfg1 = {
.enableFD = false,
.enableBRS = true,
.fdPadding = 0U,
.idType = CAN_MSG_ID_STD,
.isRemote = false
};
/* Configure TX buffer with index TX_MAILBOX*/
CAN_ConfigTxBuff(&can_1_instance, 2, &buffCfg1);
/* Prepare message to be sent */
can_message_t message1 = {
.cs = 0U,
.id = 0x0C1,
.data[0] = 0x01,
.data[1] = 0x23,
.data[2] = 0x45,
.data[3] = 0x67,
.data[4] = 0x89,
.data[5] = 0xAB,
.data[6] = 0xCD,
.data[7] = 0xEF,
.length = 8U
};
/* Send the information via CAN */
CAN_Send(&can_1_instance, 2, &message1);
#endif
}
else
{
#ifdef CAN0_ENABLE
can_buff_config_t buffCfg = {
.enableFD = false,
.enableBRS = true,
.fdPadding = 0U,
.idType = CAN_MSG_ID_STD,
.isRemote = false
};
/* Configure TX buffer with index TX_MAILBOX*/
CAN_ConfigTxBuff(&can_0_instance, 1, &buffCfg);
/* Prepare message to be sent */
can_message_t message = {
.cs = 0U,
.id = TX_MSG_ID,
.data[0] = 0x01,
.data[1] = 0x23,
.data[2] = 0x45,
.data[3] = 0x67,
.data[4] = 0x89,
.data[5] = 0xAB,
.data[6] = 0xCD,
.data[7] = 0xEF,
.length = 8U
};
/* Send the information via CAN */
CAN_Send(&can_0_instance, 1, &message);
#endif
}
canToggle ^= 1;
}
}
}
I programed your project on S32K146EVB and connect external CAN transceiver on CAN1_TX(PTA13) CAN1_RX(PTA12). I am able to receive CAN frame from CAN0 and CAN1 at the same time. Did you connect the two CAN signals of UCANS32K146 to the two channels of PEAK_CAN as shown in the figure below? I am using PEAK-USB Pro.