This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TCAN4550EVM: Problem sending CAN-messages

Part Number: TCAN4550EVM
Other Parts Discussed in Thread: TCAN4550, TCAN4550-Q1,

Hello,

I use an Infineon TLE9869QXA20 to write via SPI to the registers of a TCAN4550. I have configured the TCAN4550 and wanted to send a message, but I get no measurable signal on CANH or CANL.
If I read the register 0x10C4 before sending I get the value 0x0000000A and if I give a write command via the register 0x10D0 I read 0x00010009 in the register 0x10C4 afterwards. So the sending of a CAN message should have been successful, but I can't see any signal on the oscilloscope.
Below is my initialization code and the commands I use to send a CAN message.

I hope for a quick answer and thank you.
With regards
Timo Blessing

//Initialisierung first two hex-values are the address and than it writes the bytes

    spi_write_1reg(0x10, 0x18, 0x00, 0x00, 0x00, 0x0B);
    spi_write_1reg(0x10, 0x84, 0x00, 0x02, 0x00, 0x00);
    spi_write_1reg(0x10, 0x88, 0x00, 0x01, 0x00, 0x08);
    spi_write_1reg(0x10, 0xA0, 0x02, 0x04, 0x00, 0x10);
    spi_write_1reg(0x10, 0xB0, 0x03, 0x05, 0x00, 0xF0);
    spi_write_1reg(0x10, 0xAC, 0x00, 0x00, 0x00, 0x00);
    spi_write_1reg(0x10, 0xBC, 0x00, 0x00, 0x00, 0x76);
    spi_write_1reg(0x10, 0xF0, 0x02, 0x03, 0x02, 0x58);
    spi_write_1reg(0x10, 0xC0, 0x0A, 0x00, 0x02, 0x70);
    spi_write_1reg(0x10, 0xC8, 0x00, 0x00, 0x00, 0x07);   
    spi_write_1reg(0x10, 0x1C, 0x02, 0x03, 0x06, 0x01);
    spi_write_1reg(0x10, 0x18, 0x00, 0x00, 0x00, 0x19);
    spi_write_1reg(0x80, 0x00, 0x48, 0xAA, 0x78, 0xBB);
    spi_write_2reg(0x80, 0x08, 0x20, 0x00, 0x11, 0x11, 0x40, 0x00, 0x22, 0x22);
    spi_write_1reg(0x08, 0x00, 0xC8, 0x00, 0x04, 0xA8);

//Sending Code

    spi_send_receive(0x41, 0x10, 0xC4, 0x01);
    spi_write_1reg(0x82, 0x70, 0x02, 0xA8, 0x00, 0x00);
    spi_write_1reg(0x82, 0x74, 0x01, 0x04, 0x00, 0x00);
    spi_write_1reg(0x82, 0x78, 0x44, 0x33, 0x22, 0x11);  

spi_write_1reg(0x10, 0xD0, 0x00, 0x00, 0x00, 0x01);

  • Timo,

    An applications engineer has been notified of this post and will respond accordingly. Thank you for your patience.

    Regards,

    Eric Hackett 

  • Hello Eric,

    Thank you for the reply. I wanted to ask what is the current status?

  • Hi Timo,

    It's a bit difficult to analyze what the intention is of each of these function calls. Have you been able to test your setup using the drivers from the TCAN4550 DEMO software? The c drivers in this demo contain readable functions and structures for each device register making configurations and other features much more readable in code. The main.c file also provides an example configuration that can be used to test your hardware setup.

    I'm not certain how the spi_write_nreg() function operates, but it appears that the first two fields are the write address. I also assume that the following four fields contain the data of the write in descending order (most significant byte first). Based on this layout, I don't see anything wrong with the shared code, though I cannot check all of the configuration values in this format. I would recommend commenting each of these calls to make the configuration more readable and so the intention of each register write is clear. 

    Please ensure that all of the following are in order for proper configuration of the device:

    • Read the device ID registers ('h0000 - 'h0004) to ensure SPI communication is working properly.
    • Check and clear interrupt status flags, service interrupts as needed.
    • Read mode control register to confirm device is in proper mode before attempting to send data.
    • Verify that all supply rails (Vsup, Vio) are adequately supplied. 

    Regards,
    Eric Schott

  • Hey Eric,

    the way you interpreted my code was correct.
    I checked and I have the correct voltage everywhere on Vsup, Vio etc..
    Also my SPI communication is working. I can read registers and when I write to registers and then read them, it says the right thing.
    But when I write or read something via SPI, I get the status of register 0x0820[7:0] on the SDO line and I think something is wrong there. When I read a register before initialization I get there the value 0x89 and when I read a register after initialization I always get the value 0xA9. This would mean I have an SPI error and a CAN error, but I don't know where these errors should be or what they are related to. I have attached an example of a register read command.


    Do you know maybe an answer and is this the reason why my CAN communication is not working?


    Thanks for your feedback.


    With regards
    Timo Blessing

  • Also when I read the register 0x000C i get the Value 0x0020000A

  • Hi Timo,

    Thanks for the extra information and scope shot. 

    It does indeed sound like a SPI issue could be preventing proper configuration and use of CAN. The values from the interrupt register and status register suggest that the device has recognized a SPI_end_error. This is caused when a SPI transaction ends without completing the current byte. Once this interrupt is recognized, it should be cleared (writing 1s to corresponding registers) so that any future occurrence can also be recognized. 

    The scope shot you shared of the SPI interface doesn't appear to have any issues and should not cause a SPI_end_error. However, it's possible that a previous transaction contained such an error and the status flag was not since cleared. Would you be able to capture the the first SPI transaction to this device after startup? I've seen stray clock pulses from the MCU in some systems during the first transaction that can cause such errors. 

    The interrupt status is always sent as the first byte when a SPI transaction is initiated. This is intended and described in the datasheet. Figure 8-17 (TCAN4550-Q1 datasheet) shows a good representation of this. The scope shot appears consistent with this. 

    Regards,
    Eric Schott

  • Hi Eric,

    In this first image you can see the oscilloscope image of the first SPI read request after the voltage was started on both boards. For the register 0x0820 I get the value 0x81, that means VTWD interrupt got, which I would get away with a reset. But when I send the second SPI read request, I get the value 0x89 there again, which means an SPI error.

    In this second image you can see the oscilloscope capture of the first SPI read request, after a reset of the TCAN4550. For the register 0x0820 I get the value 0x00, which means everything would be perfect or? But when I send the second SPI read request, I get there the value 0x88, so a SPI error.

    Can you see whre the Error is coming from?

    As you said, I used the AHB_WRITE_32(0x000C, 0x00200000) command to clear the interrupt flags. Afterwards I get also on the register 0x0820 the value 0x00 back, so it works. But when I reflash the Infineon board to load a new read or write command, I get the error neither with the value 0x88. That means always the first SPI transfer is not executed correctly, so the interrupt flag is set. But I don't know what exactly is wrong with the first transfer or how to fix it.

    With regards

    Timo Blessing

  • I think the error comes from the fact that CS is set directly to LOW after the reset of the Infineon until the initialization of the Infineon is finished. And the TCAN4550 sees this already as the first send attempt via SPI can this be?
    If so is there a possibility to ignore this "first send"? 

  • Hi Timo,

    I'm reviewing your reply and will get back to you tomorrow. 

    Regards,
    Eric Schott

  • Hi Timo,

    I agree with your second analysis here. The initial assertion of nCS when the MCU starts up would be considered a SPI end error (frame does not end on a byte boundary because no data was sent). We see this status in both scope shots here (bit 21 from status register 000Ch). I suspect the difference in interrupt status (81h vs 00h) is due to the different reset cases - one being done by power supply (UV flag set) the other done using the reset. 

    Because we can't configure the device to ignore this initial occurrence of nCS assertion, I would suggest that after startup, all interrupts be cleared first (write 1s to Status register 000Ch). Once these are confirmed to be cleared, the configuration of the device can begin once again. 

    Once again I'd like to encourage you to consider use of the TCAN4550 driver library to increase readability of this program. It will still make use of the SPI read and write functions you already implement, but will organize the TCAN4550 registers and features to named variables and structures for ease of use, modification, and debug. Let me know if you have any questions about this library.

    Regards,
    Eric Schott

  • Hi Eric,

    I have now used the TCAN4550 Libaray as you said. I rewrote the SPI function to work with the TLE9869 and copied the rest of the files (TCAN4550.h, TCAN4550.c, TCAN4x5x_Data_Struct.h and TCAN4x5x_Reg.h). This has also worked so far I get over the SPI also no more errors.
    In addition I have taken out of the main.c of the demo code so far everything what I needed, mainly the CAN_Init. But I still get no message on the CAN line. And when I measure with the oscilloscope to CANH or CANL both are on 0 Volt.
    Below is my main.c attached. Do you see any other error or know what it could be?

    Thanks
    Timo

    #include "tle_device.h"
    #include "port.h"
    #include "spi.h"
    #include "eigene_uart.h"
    #include <string.h>
    #include <stdio.h>
    #include "tcan4550.h"
    
    //Variablen
    extern uint16 receive_Array[12];
    char string[8];
    
    volatile uint8_t TCAN_Int_Cnt = 0;
    
    //Funktionen
    //void Init_GPIO(void);
    //void Init_Clock(void);
    //void Init_SPI(void);
    void Init_CAN(void);
    
    int main(void)
    {
    	//PORT_ChangePin(0x00U, PORT_ACTION_SET);
    	
      /*****************************************************************************
      ** Initialization of the hardware modules based on the configuration set    **
      ** in Config Wizard                                                         **
      *****************************************************************************/
      TLE_Init();
    	ADC1_Init();
    	
    	PORT_ChangePin(0x00U, PORT_ACTION_SET);
    	
    	Init_CAN();
    	
    	/*Define the CAN message we want to send*/
    	TCAN4x5x_MCAN_TX_Header header = {0};							//Remember to initialize to 0, or you´ll get random garbage!
    	uint8_t data[4] = {0x55, 0x66, 0x77, 0x88};				//Define the data payload
    	header.DLC = MCAN_DLC_4B;													//Set the DLC to be equal to or less than the data payload (it is ok to pass a64 byte array into the WriteTXFIFO function if your DLC is 8 bytes, only the first 8 bytes will be read)
    	header.ID = 0x144;																//Set the ID
    	header.FDF = 1;																		//CAN FD frame enabled
    	header.BRS = 1;																		//BIT10 rate switch enabled
    	header.EFC = 0;
    	header.MM  = 0;
    	header.RTR = 0;
    	header.XTD = 0;																		//We are not using an extended ID in this example
    	header.ESI = 0;																		//Error state indicator
    	
    	TCAN4x5x_MCAN_WriteTXBuffer(0, &header, data);		// This function actually writes the header and data payload to the TCAN's MRAM in the specified TX queue number. It returns the bit necessary to write to TXBAR,
    																										// but does not necessarily require you to use it. In this example, we won't, so that we can send the data queued up at a later point.
    
    	/* Let's make a different CAN message */
    	data[0] = 0x11;
    	data[1] = 0x22;
    	data[2] = 0x33;
    	data[3] = 0x44;											//define data payload
    	
    	header.DLC = MCAN_DLC_4B;						// Set the DLC to be equal to or less than the data payload (it is ok to pass a 64 byte data array into the WriteTXFIFO function if your DLC is 8 bytes, only the first 8 bytes will be read)
    	header.ID = 0x123;									// Set the ID
    	header.FDF = 1;											// CAN FD frame enabled
    	header.BRS = 1;											// Bit rate switch enabled
    	header.EFC = 0;
    	header.MM  = 0;
    	header.RTR = 0;
    	header.XTD = 0;											// We are not using an extended ID in this example
    	header.ESI = 0;											// Error state indicator
    
    	TCAN4x5x_MCAN_WriteTXBuffer(1, &header, data);	//This line writes the data and header to TX FIFO1
    	TCAN4x5x_MCAN_TransmitBufferContents(1);				//Request that TX Buffer 1 be transmitted
    	
    	TCAN4x5x_MCAN_TransmitBufferContents(0);				//now we can send the TX FIFO element 0 data that we had queued up earliere but didn't send.
    	
    	
      for (;;)
      {
    		
        (void)WDT1_Service();
    
    		if (TCAN_Int_Cnt > 0 )
    		{
    			TCAN_Int_Cnt--;
    			TCAN4x5x_Device_Interrupts dev_ir = {0};           // Define a new Device IR object for device (non-CAN) interrupt checking
    			TCAN4x5x_MCAN_Interrupts mcan_ir = {0};						 // Setup a new MCAN IR object for easy interrupt checking
    			TCAN4x5x_Device_ReadInterrupts(&dev_ir);           // Read the device interrupt register
    			TCAN4x5x_MCAN_ReadInterrupts(&mcan_ir);		       	 // Read the interrupt register
    
    			if (dev_ir.SPIERR)                                  // If the SPIERR flag is set
    			    TCAN4x5x_Device_ClearSPIERR();                  // Clear the SPIERR flag
    
    			if (mcan_ir.RF0N)																		// If a new message in RX FIFO 0
    			{
    				TCAN4x5x_MCAN_RX_Header MsgHeader = {0};					// Initialize to 0 or you'll get garbage
    				uint8_t numBytes = 0;                           	// Used since the ReadNextFIFO function will return how many bytes of data were read
    				uint8_t dataPayload[64] = {0};                  	// Used to store the received data
    
    				TCAN4x5x_MCAN_ClearInterrupts(&mcan_ir);	    		// Clear any of the interrupt bits that are set.
    
    				numBytes = TCAN4x5x_MCAN_ReadNextFIFO( RXFIFO0, &MsgHeader, dataPayload);	// This will read the next element in the RX FIFO 0
    
    				// numBytes will have the number of bytes it transfered in it. Or you can decode the DLC value in MsgHeader.DLC
    				// The data is now in dataPayload[], and message specific information is in the MsgHeader struct.
    				if (MsgHeader.ID == 0x0AA)		// Example of how you can do an action based off a received address
    				{
    					// Do something
    				}
    			}
    		
    		}
    		
      }
    	
    }
    
    /*
    * Configure the TCAN4550
    */
    void Init_CAN(void)
    {
    	TCAN4x5x_Device_ClearSPIERR();									//Clear any SPI ERR flags that might be set as a result of our pin mux changing during MCU startup
    	
    	/*Step one attempt to clear all interrupts*/
    	TCAN4x5x_Device_Interrupt_Enable dev_ie = {0};			//Initialize to 0 to all bits are set to 0
    	TCAN4x5x_Device_ConfigureInterruptEnable(&dev_ie);	//Disable all non-MCAN related interrupts for simplicity
    	
    	TCAN4x5x_Device_Interrupts dev_ir = {0};						//Setup a new MCAN IR objekt for easy interrupt checking
    	TCAN4x5x_Device_ReadInterrupts(&dev_ir);						//Requsetthat the struct be updated with current DEVICE (not MCAN) interrupt values
    	
    	if(dev_ir.PWRON)																		//if the Power On interrupt flag is set
    	{
    		TCAN4x5x_Device_ClearInterrupts(&dev_ir);					//clearerr it because if it's not cleared within ca. 4 minutes, it goes sleep
    	}
    	
    	/* Configure the CAN bus speeds */
    	TCAN4x5x_MCAN_Nominal_Timing_Simple TCANNomTiming = {0};	//500k arbitration with a 40 MHz cystal ((40E6 / 2) / (32 + 8) = 500E3)
    	TCANNomTiming.NominalBitRatePrescaler = 2;
    	TCANNomTiming.NominalTqBeforeSamplePoint = 32;
    	TCANNomTiming.NominalTqAfterSamplePoint = 8;
    	
    	TCAN4x5x_MCAN_Data_Timing_Simple TCANDataTiming = {0};		// 2 Mbps CAN FD with a 40 MHz crystal (40E6 / (15 + 5) = 2E6)
    	TCANDataTiming.DataBitRatePrescaler = 1;
    	TCANDataTiming.DataTqBeforeSamplePoint = 15;
    	TCANDataTiming.DataTqAfterSamplePoint = 5;
    	
    	/* Configure the MCAN core settings */
    	TCAN4x5x_MCAN_CCCR_Config cccrConfig = {0};								//Remember to initialize to 0, or you´ll get random garbage!
    	cccrConfig.FDOE = 1;																			//CAN FD mode enable
    	cccrConfig.BRSE = 1;																			//CAN FD Bit rate switch enable
    	
    	/*Configure the default CAN packet filtering settings*/
    	TCAN4x5x_MCAN_Global_Filter_Configuration gfc = {0};
    	gfc.RRFE = 1;																							//Reject remote frames (TCAN4x5x doesn't support this)
    	gfc.RRFS = 1;																							//Rejects remote frames (TCAN4x5x doesn't support this)
    	gfc.ANFE = TCAN4x5x_GFC_ACCEPT_INTO_RXFIFO0;							//Default behaviour if incoming message doesn't match filter is to accept into RXFIO0 for extended ID message (29 bit IDs)
    	gfc.ANFS = TCAN4x5x_GFC_ACCEPT_INTO_RXFIFO0;              // Default behavior if incoming message doesn't match a filter is to accept into RXFIO0 for standard ID messages (11 bit IDs)
    	
    	/* ***********************************************************
    	* In the next configuration block, we will set the MCAN core up to have :
    	*   - 1 SID filter element
      *   - 1 XID Filter element
      *   - 5 RX FIFO 0 elements
      *   - RX FIFO 0 supports data payloads up to 64 bytes
      *   - RX FIFO 1 and RX Buffer will not have any elements, but we still set their data payload sizes, even though it's not required
      *   - No TX Event FIFOs
      *   - 2 Transmit buffers supporting up to 64 bytes of data payload
      */
    	TCAN4x5x_MRAM_Config MRAMConfiguration = {0};
    	MRAMConfiguration.SIDNumElements = 1;												// Standard ID number of elements, you MUST have a filter written to MRAM for each element defined
    	MRAMConfiguration.XIDNumElements = 1;												// Extended ID number of elements, you MUST have a filter written to MRAM for each element defined
    	MRAMConfiguration.Rx0NumElements = 5;												// RX0 Number of elements
    	MRAMConfiguration.Rx0ElementSize = MRAM_64_Byte_Data;				// RX0 data payload size
    	MRAMConfiguration.Rx1NumElements = 0;												// RX1 number of elements
    	MRAMConfiguration.Rx1ElementSize = MRAM_64_Byte_Data;				// RX1 data payload size
    	MRAMConfiguration.RxBufNumElements = 0;											// RX buffer number of elements
    	MRAMConfiguration.RxBufElementSize = MRAM_64_Byte_Data;			// RX buffer data payload size
    	MRAMConfiguration.TxEventFIFONumElements = 0;								// TX Event FIFO number of elements
    	MRAMConfiguration.TxBufferNumElements = 2;									// TX buffer number of elements
    	MRAMConfiguration.TxBufferElementSize = MRAM_64_Byte_Data;	// TX buffer data payload size
    	
    	/* Configure the MCAN core with the settings above, the changes in this block are write protected registers,      *
    	 * so it makes the most sense to do them all at once, so we only unlock and lock once                             */
    
    	TCAN4x5x_MCAN_EnableProtectedRegisters();											// Start by making protected registers accessible
    	TCAN4x5x_MCAN_ConfigureCCCRRegister(&cccrConfig);							// Enable FD mode and Bit rate switching
    	TCAN4x5x_MCAN_ConfigureGlobalFilter(&gfc);                 	  // Configure the global filter configuration (Default CAN message behavior)
    	TCAN4x5x_MCAN_ConfigureNominalTiming_Simple(&TCANNomTiming);	// Setup nominal/arbitration bit timing
    	TCAN4x5x_MCAN_ConfigureDataTiming_Simple(&TCANDataTiming);		// Setup CAN FD timing
    	TCAN4x5x_MRAM_Clear();																				// Clear all of MRAM (Writes 0's to all of it)
    	TCAN4x5x_MRAM_Configure(&MRAMConfiguration);									// Set up the applicable registers related to MRAM configuration
    	TCAN4x5x_MCAN_DisableProtectedRegisters();										// Disable protected write and take device out of INIT mode
    	
    	/* Set the interrupts we want to enable for MCAN */
    	TCAN4x5x_MCAN_Interrupt_Enable mcan_ie = {0};					// Remember to initialize to 0, or you'll get random garbage!
    	mcan_ie.RF0NE = 1;																		// RX FIFO 0 new message interrupt enable
    
    	TCAN4x5x_MCAN_ConfigureInterruptEnable(&mcan_ie);			// Enable the appropriate registers
    
    	/* Setup filters, this filter will mark any message with ID 0x055 as a priority message */
    	TCAN4x5x_MCAN_SID_Filter SID_ID = {0};
    	SID_ID.SFT = TCAN4x5x_SID_SFT_CLASSIC;								// SFT: Standard filter type. Configured as a classic filter
    	SID_ID.SFEC = TCAN4x5x_SID_SFEC_PRIORITYSTORERX0;			// Standard filter element configuration, store it in RX fifo 0 as a priority message
    	SID_ID.SFID1 = 0x055;																	// SFID1 (Classic mode Filter)
    	SID_ID.SFID2 = 0x7FF;																	// SFID2 (Classic mode Mask)
    	TCAN4x5x_MCAN_WriteSIDFilter(0, &SID_ID);							// Write to the MRAM
    	
    	/* Store ID 0x12345678 as a priority message */
    	TCAN4x5x_MCAN_XID_Filter XID_ID = {0};
    	XID_ID.EFT = TCAN4x5x_XID_EFT_CLASSIC;                      // EFT
    	XID_ID.EFEC = TCAN4x5x_XID_EFEC_PRIORITYSTORERX0;           // EFEC
    	XID_ID.EFID1 = 0x12345678;                                  // EFID1 (Classic mode filter)
    	XID_ID.EFID2 = 0x1FFFFFFF;                                  // EFID2 (Classic mode mask)
    	TCAN4x5x_MCAN_WriteXIDFilter(0, &XID_ID);                   // Write to the MRAM
    	
    	/* Configure the TCAN4550 Non-CAN-related functions */
    	TCAN4x5x_DEV_CONFIG devConfig = {0};                        		 // Remember to initialize to 0, or you'll get random garbage!
    	devConfig.SWE_DIS = 0;                                		       // Keep Sleep Wake Error Enabled (it's a disable bit, not an enable)
    	devConfig.DEVICE_RESET = 0;                                 		 // Not requesting a software reset
    	devConfig.WD_EN = 0;                                		         // Watchdog disabled
    	devConfig.nWKRQ_CONFIG = 0;                            			     // Mirror INH function (default)
    	devConfig.INH_DIS = 0;                                      		 // INH enabled (default)
    	devConfig.GPIO1_GPO_CONFIG = TCAN4x5x_DEV_CONFIG_GPO1_MCAN_INT1; // MCAN nINT 1 (default)
    	devConfig.FAIL_SAFE_EN = 0;                                 		 // Failsafe disabled (default)
    	devConfig.GPIO1_CONFIG = TCAN4x5x_DEV_CONFIG_GPIO1_CONFIG_GPO;   // GPIO set as GPO (Default)
    	devConfig.WD_ACTION = TCAN4x5x_DEV_CONFIG_WDT_ACTION_nINT;  		 // Watchdog set an interrupt (default)
    	devConfig.WD_BIT_RESET = 0;                                 		 // Don't reset the watchdog
    	devConfig.nWKRQ_VOLTAGE = 0;                                		 // Set nWKRQ to internal voltage rail (default)
    	devConfig.GPO2_CONFIG = TCAN4x5x_DEV_CONFIG_GPO2_NO_ACTION; 		 // GPO2 has no behavior (default)
    	devConfig.CLK_REF = 1;                                      		 // Input crystal is a 40 MHz crystal (default)
    	devConfig.WAKE_CONFIG = TCAN4x5x_DEV_CONFIG_WAKE_BOTH_EDGES;		 // Wake pin can be triggered by either edge (default)
    	TCAN4x5x_Device_Configure(&devConfig);                      		 // Configure the device with the above configuration
    
    	TCAN4x5x_Device_SetMode(TCAN4x5x_DEVICE_MODE_NORMAL);       		 // Set to normal mode, since configuration is done. This line turns on the transceiver
    
    	TCAN4x5x_MCAN_ClearInterruptsAll();                         		// Resets all MCAN interrupts (does NOT include any SPIERR interrupts)
    	
    }
    

  • And I don't any voltage at Vio and VCCOUT after flashing the code. But the INH-LED and the GPIO1 LED is on.

  • Hi Timo,

    Welcome back to the project! I'm glad to hear the conversion to the new code went well. The code here looks good! It looks like this will properly configure TCAN4550 and have it transmit the first two messages to the CAN bus. 

    Based on the observed state of the CAN bus and the supply pins, it sounds like TCAN4550 is not in normal mode. Vio needs to be supplied from an external source for the device to interface correctly through any logic-level pins, including SPI. If Vio is not supplied, the device will automatically go to sleep after the UVio timer expires, which also shuts off Vccout. Once in sleep mode, INH will be inactive (floating) and the CAN bus will be weakly biased to 0V. 

    Another reason that the device may enter sleep mode automatically is if the inactive timer expires after initial power-up. This can occur if power is supplied to TCAN4550 and then left idle for a couple of minutes. This will also deactivate Vccout, INH, and CAN bus. Once asleep, the device will wake up from bus activity or a transition on the WAKE pin. Once awake, it will be able to be interfaced with through SPI.

    In both of these cases where the device is in sleep mode, the SPI interface will not be accessible. To consider this in the software, the MCU can read a register with a known value from TCAN4550 (such as the device ID or scratchpad registers) to confirm that the interface is working. If there is no response (all 0s or all 1s) a wake event needs to occur before SPI communication can be successfully initiated. If there is no Vio available for TCAN4550, this supply will need to be returned before normal mode can be achieved (typically this source is shared with the MCU, so if unavailable, there would be no need for SPI). 

    I'm not sure what the polarities of the LEDs are on the board you're using. Could you probe the votlages at the device pins for best clarity of device state? 

    Let me know how the follow-up debug efforts go. It looks like you have a good handle on the software now, so it's just resolving some hardware before things are in working order. 

    Regards,
    Eric Schott

  • Hi Eric,

    since I am using the TCAN4550EVM board, my Vio pin is powered by the LDO or not? Then I would not need an external power supply for Vio.
    I tried to flash my program and comment out Init_CAN(). Then I had all levels on the pins, but as soon as I tried the Init_CAN() function, the levels went straight down.

    By debugging I found out that it is because of the TCAN4x5x_Device_Configure(&devConfig); function. As soon as I want to execute this function the voltage goes down, with all other functions in Init_CAN() the voltage stays up. I think that writing to the register 0x0800 does not work properly and the program hangs when it tries to compare if the writing worked. Therefore I wrote the register with the function "AHB_WRITE_32(0x0800, 0xC8000460);". This seems to have worked so far.

    But I still did not get a CAN message out also CANH and CANL. Then I noticed that after the second time flashing the program on the register 0x0820[7:0] I get the value 0xA0, so a CANSLNT error. This I have then replaced by


    AHB_WRITE_32(0x000C, 0xFFFFFF);       //delete all interrupt flags
    AHB_WRITE_32(0x0830, 0xFFFFFBFF);   //disable CANSLNT interrupt
    AHB_WRITE_32(0x0820, 0x00100400);     //delete CANSLNT interrupt flag


    cleared. If I now write to registers or execute Init_CAN() and want to send something via CAN, I get no more errors in register 0x0820 and the board has all levels everywhere. Also CANH and CANL are on the correct levels, but still no message comes out.

    I also tried the test mode "SPI and M_CAN Core Test Mode". For this I wrote the value "0xC8100469" directly after INIT_CAN() into the register 0x0800. But also here I see nothing when I measure with the oscilloscope at GPO2. There should be also the CAN message readable or?

    Where could be the error now?

    With regards

    Timo

  • /* Configure the TCAN4550 Non-CAN-related functions */
    /*	TCAN4x5x_DEV_CONFIG devConfig = {0};                        		 // Remember to initialize to 0, or you'll get random garbage!
    	devConfig.SWE_DIS = 0;                                		       // Keep Sleep Wake Error Enabled (it's a disable bit, not an enable)
    	devConfig.DEVICE_RESET = 0;                                 		 // Not requesting a software reset
    	devConfig.WD_EN = 0;                                		         // Watchdog disabled
    	devConfig.nWKRQ_CONFIG = 0;                            			     // Mirror INH function (default)
    	devConfig.INH_DIS = 0;                                      		 // INH enabled (default)
    	devConfig.GPIO1_GPO_CONFIG = TCAN4x5x_DEV_CONFIG_GPO1_MCAN_INT1; // MCAN nINT 1 (default)
    	devConfig.FAIL_SAFE_EN = 0;                                 		 // Failsafe disabled (default)
    	devConfig.GPIO1_CONFIG = TCAN4x5x_DEV_CONFIG_GPIO1_CONFIG_GPO;   // GPIO set as GPO (Default)
    	devConfig.WD_ACTION = TCAN4x5x_DEV_CONFIG_WDT_ACTION_nINT;  		 // Watchdog set an interrupt (default)
    	devConfig.WD_BIT_RESET = 0;                                 		 // Don't reset the watchdog
    	devConfig.nWKRQ_VOLTAGE = 0;                                		 // Set nWKRQ to internal voltage rail (default)
    	devConfig.GPO2_CONFIG = TCAN4x5x_DEV_CONFIG_GPO2_NO_ACTION; 		 // GPO2 has no behavior (default)
    	devConfig.CLK_REF = 1;                                      		 // Input crystal is a 40 MHz crystal (default)
    	devConfig.WAKE_CONFIG = TCAN4x5x_DEV_CONFIG_WAKE_BOTH_EDGES;		 // Wake pin can be triggered by either edge (default)
      //TCAN4x5x_Device_Configure(&devConfig);                      		 // Configure the device with the above configuration
    */
    	//Takes the function the block above
    	AHB_WRITE_32(0x0800, 0xC8000460);

  • Hi Timo,

    Yes, Vio is supplied by the LDO on the EVM (U2) which is enabled by the INH output of TCAN4550. This means that when TCAN4550 goes to sleep and disables the INH output, the LDO will stop supplying 3.3V. The INIT_CAN() function ends by putting the device into normal mode and clearing all of the interrupts. 

    It's unlikely that the TCAN4x5x_Device_Configure() method is causing the device to go to sleep. This method reads the current mode of the device and writes it back with the new data so the device mode does not change. It's possible that while debugging to find where this occurs, the INACTIVE timer timed out and the device automatically went into sleep mode. That said, it is strange to hear that the device still goes to sleep when the Init_CAN() is called normally. If the device was placed into normal mode by this function, it should not go to sleep again (disabled INH) until explicitly told to do so via SPI or some other fault condition occurs (such as undervoltage). 

    Please check that the device is in normal mode after the Init_CAN() function by verifying that both INH is active and by reading back the mode control register to confirm that bits [7:6] read 2'b10. It it appears the device is in sleep mode, try manually waking it with the WAKE pushbutton and restarting the configuration. 

    If possible, I would encourage you to try this configuration using an MSP430FR6989 launchpad to verify the hardware setup of this test. This tool will be able to run the demo software without any modifications, so few variables will be dissimilar to setups I have used many times internally. 

    Regards,
    Eric Schott

  • Hi Eric,

    I have found my mistake. My AHB_READ_32() function returned a wrong value, therefore the configuration could not be correct. Now I get something out on the CANL lines, but unfortunately not yet the correct or full message.

    In the two pictures you see the CAN messages as they go out. The complete frame is not transmitted, but aborted after CRC and there is no data field. In addition, the value 0 is in DLC although 4byte are set in the code.

    I have to say that I switched off CAN-FD in the code and increased the baud rate to 1Mbit/s. I send you the new code in addition. It would be great if you could tell me if my changes are correct. But the Can messages went out exactly the same before these changes, so I don't think it's because of that.

    Then regarding this error I read the registers 0x0820, 0x0824, 0x1020 and 0x1024 and got the following values:

    0x0820 = 0x00000000

    0x0824 = 0x08010000

    0x1020 = 0x00000002

    0x1024 = 0x00000E32 / but here the value changes everytime I try

    According to the value in 0x0824, I have a PEA interrupt or a protocoll error in the arbitration phase and a timestamp error or interrupt. But I don't know where this comes from or how to get rid of it. Could it also come from the fact that the value 0 is in DLC? Or maybe you know another possibility where it could be?

    Thanks for your good support.

    With regards

    Timo

  • #include "tle_device.h"
    #include "port.h"
    #include "spi.h"
    #include "eigene_uart.h"
    #include <string.h>
    #include <stdio.h>
    #include "tcan4550.h"
    
    //Variablen
    extern uint16 receive_Array[12];
    char string[8];
    
    volatile uint8_t TCAN_Int_Cnt = 0;
    uint32_t readData;
    
    //Funktionen
    void Init_CAN(void);
    
    int main(void)
    {
    	//PORT_ChangePin(0x00U, PORT_ACTION_SET);
    	
      /*****************************************************************************
      ** Initialization of the hardware modules based on the configuration set    **
      ** in Config Wizard                                                         **
      *****************************************************************************/
      TLE_Init();
    	ADC1_Init();
    	
    	PORT_ChangePin(0x00U, PORT_ACTION_SET);
    	
    	AHB_WRITE_32(0x000C, 0xFFFFFFFF);	//delete all Interrupt-Flags
    	AHB_WRITE_32(0x0830, 0xFFFFFBFF);	//disable CANSLNT-Interrupt
    	AHB_WRITE_32(0x0820, 0x00100400);	//delete CANSLNT Interrupt-Flag
    	
    		
    	Init_CAN();
    	
    	TCAN4x5x_MCAN_EnableProtectedRegisters();
    	AHB_WRITE_32(0x1018, 0x00000340);		//set DAR bit
    	AHB_WRITE_32(0x1020, 0x00000000);		//setbuf Timestep to always 0
    //	AHB_READ_32(0x1018);
    	TCAN4x5x_MCAN_DisableProtectedRegisters();
    	
    	/*Define the CAN message we want to send*/
    	TCAN4x5x_MCAN_TX_Header header = {0};							//Remember to initialize to 0, or you´ll get random garbage!
    	uint8_t data[4] = {0x55, 0x66, 0x77, 0x88};				//Define the data payload
    	header.DLC = MCAN_DLC_4B;													//Set the DLC to be equal to or less than the data payload (it is ok to pass a64 byte array into the WriteTXFIFO function if your DLC is 8 bytes, only the first 8 bytes will be read)
    	header.ID = 0x144;																//Set the ID
    	header.FDF = 0;																		//CAN FD frame disabled
    	header.BRS = 0;																		//BIT10 rate switch disabled
    	header.EFC = 0;
    	header.MM  = 0;
    	header.RTR = 0;
    	header.XTD = 0;																		//We are not using an extended ID in this example
    	header.ESI = 0;																		//Error state indicator
    	
     	TCAN4x5x_MCAN_WriteTXBuffer(0, &header, data);		// This function actually writes the header and data payload to the TCAN's MRAM in the specified TX queue number. It returns the bit necessary to write to TXBAR,
    																										// but does not necessarily require you to use it. In this example, we won't, so that we can send the data queued up at a later point.
    
    	/* Let's make a different CAN message */
    	data[0] = 0x11;
    	data[1] = 0x22;
    	data[2] = 0x33;
    	data[3] = 0x44;											//define data payload
    	
    	header.DLC = MCAN_DLC_4B;						// Set the DLC to be equal to or less than the data payload (it is ok to pass a 64 byte data array into the WriteTXFIFO function if your DLC is 8 bytes, only the first 8 bytes will be read)
    	header.ID = 0x123;									// Set the ID
    	header.FDF = 0;											// CAN FD frame disabled
    	header.BRS = 0;											// Bit rate switch disabled
    	header.EFC = 0;
    	header.MM  = 0;
    	header.RTR = 0;
    	header.XTD = 0;											// We are not using an extended ID in this example
    	header.ESI = 0;											// Error state indicator
    
    	TCAN4x5x_MCAN_WriteTXBuffer(1, &header, data);	//This line writes the data and header to TX FIFO1
    	TCAN4x5x_MCAN_TransmitBufferContents(1);				//Request that TX Buffer 1 be transmitted
    	
    	TCAN4x5x_MCAN_TransmitBufferContents(0);				//now we can send the TX FIFO element 0 data that we had queued up earliere but didn't send.
    	/*
    		AHB_READ_32(0x0820);
    		AHB_READ_32(0x0824);
    		AHB_READ_32(0x1020);
    		AHB_READ_32(0x1024);
    	*/
      for (;;)
      {
    		
        (void)WDT1_Service();
    
    		if (TCAN_Int_Cnt > 0 )
    		{
    			TCAN_Int_Cnt--;
    			TCAN4x5x_Device_Interrupts dev_ir = {0};           // Define a new Device IR object for device (non-CAN) interrupt checking
    			TCAN4x5x_MCAN_Interrupts mcan_ir = {0};						 // Setup a new MCAN IR object for easy interrupt checking
    			TCAN4x5x_Device_ReadInterrupts(&dev_ir);           // Read the device interrupt register
    			TCAN4x5x_MCAN_ReadInterrupts(&mcan_ir);		       	 // Read the interrupt register
    
    			if (dev_ir.SPIERR)                                  // If the SPIERR flag is set
    			    TCAN4x5x_Device_ClearSPIERR();                  // Clear the SPIERR flag
    
    			if (mcan_ir.RF0N)																		// If a new message in RX FIFO 0
    			{
    				TCAN4x5x_MCAN_RX_Header MsgHeader = {0};					// Initialize to 0 or you'll get garbage
    				uint8_t numBytes = 0;                           	// Used since the ReadNextFIFO function will return how many bytes of data were read
    				uint8_t dataPayload[64] = {0};                  	// Used to store the received data
    
    				TCAN4x5x_MCAN_ClearInterrupts(&mcan_ir);	    		// Clear any of the interrupt bits that are set.
    
    				numBytes = TCAN4x5x_MCAN_ReadNextFIFO( RXFIFO0, &MsgHeader, dataPayload);	// This will read the next element in the RX FIFO 0
    
    				// numBytes will have the number of bytes it transfered in it. Or you can decode the DLC value in MsgHeader.DLC
    				// The data is now in dataPayload[], and message specific information is in the MsgHeader struct.
    				if (MsgHeader.ID == 0x0AA)		// Example of how you can do an action based off a received address
    				{
    					// Do something
    				}
    			}
    		
    		}
    		
      }
    	
    }
    
    /*
    * Configure the TCAN4550
    */
    void Init_CAN(void)
    {
    	TCAN4x5x_Device_ClearSPIERR();									//Clear any SPI ERR flags that might be set as a result of our pin mux changing during MCU startup
    
    	/*Step one attempt to clear all interrupts*/
    	TCAN4x5x_Device_Interrupt_Enable dev_ie = {0};			//Initialize to 0 to all bits are set to 0
    	TCAN4x5x_Device_ConfigureInterruptEnable(&dev_ie);	//Disable all non-MCAN related interrupts for simplicity
    	
    	TCAN4x5x_Device_Interrupts dev_ir = {0};						//Setup a new MCAN IR objekt for easy interrupt checking
    	TCAN4x5x_Device_ReadInterrupts(&dev_ir);						//Requsetthat the struct be updated with current DEVICE (not MCAN) interrupt values
    	
    	if(dev_ir.PWRON)																		//if the Power On interrupt flag is set
    	{
    		TCAN4x5x_Device_ClearInterrupts(&dev_ir);					//clearerr it because if it's not cleared within ca. 4 minutes, it goes sleep
    	}
    	
    	/* Configure the CAN bus speeds */
    	TCAN4x5x_MCAN_Nominal_Timing_Simple TCANNomTiming = {0};	//500k arbitration with a 40 MHz cystal ((40E6 / 4) / (8 + 2) = 1E6)
    	TCANNomTiming.NominalBitRatePrescaler = 4;
    	TCANNomTiming.NominalTqBeforeSamplePoint = 8;
    	TCANNomTiming.NominalTqAfterSamplePoint = 2;
    	
    	TCAN4x5x_MCAN_Data_Timing_Simple TCANDataTiming = {0};		// 2 Mbps CAN FD with a 40 MHz crystal (40E6 / (15 + 5) = 2E6)
    	TCANDataTiming.DataBitRatePrescaler = 1;
    	TCANDataTiming.DataTqBeforeSamplePoint = 15;
    	TCANDataTiming.DataTqAfterSamplePoint = 5;
    	
    	/* Configure the MCAN core settings */
    	TCAN4x5x_MCAN_CCCR_Config cccrConfig = {0};								//Remember to initialize to 0, or you´ll get random garbage!
    	cccrConfig.FDOE = 0;																			//CAN FD mode disable
    	cccrConfig.BRSE = 0;																			//CAN FD Bit rate switch disable
    	
    	/*Configure the default CAN packet filtering settings*/
    	TCAN4x5x_MCAN_Global_Filter_Configuration gfc = {0};
    	gfc.RRFE = 1;																							//Reject remote frames (TCAN4x5x doesn't support this)
    	gfc.RRFS = 1;																							//Rejects remote frames (TCAN4x5x doesn't support this)
    	gfc.ANFE = TCAN4x5x_GFC_ACCEPT_INTO_RXFIFO0;							//Default behaviour if incoming message doesn't match filter is to accept into RXFIO0 for extended ID message (29 bit IDs)
    	gfc.ANFS = TCAN4x5x_GFC_ACCEPT_INTO_RXFIFO0;              // Default behavior if incoming message doesn't match a filter is to accept into RXFIO0 for standard ID messages (11 bit IDs)
    	
    	/* ***********************************************************
    	* In the next configuration block, we will set the MCAN core up to have :
    	*   - 1 SID filter element
      *   - 1 XID Filter element
      *   - 5 RX FIFO 0 elements
      *   - RX FIFO 0 supports data payloads up to 64 bytes
      *   - RX FIFO 1 and RX Buffer will not have any elements, but we still set their data payload sizes, even though it's not required
      *   - No TX Event FIFOs
      *   - 2 Transmit buffers supporting up to 64 bytes of data payload
      */
    	TCAN4x5x_MRAM_Config MRAMConfiguration = {0};
    	MRAMConfiguration.SIDNumElements = 1;												// Standard ID number of elements, you MUST have a filter written to MRAM for each element defined
    	MRAMConfiguration.XIDNumElements = 1;												// Extended ID number of elements, you MUST have a filter written to MRAM for each element defined
    	MRAMConfiguration.Rx0NumElements = 5;												// RX0 Number of elements
    	MRAMConfiguration.Rx0ElementSize = MRAM_64_Byte_Data;				// RX0 data payload size
    	MRAMConfiguration.Rx1NumElements = 0;												// RX1 number of elements
    	MRAMConfiguration.Rx1ElementSize = MRAM_64_Byte_Data;				// RX1 data payload size
    	MRAMConfiguration.RxBufNumElements = 0;											// RX buffer number of elements
    	MRAMConfiguration.RxBufElementSize = MRAM_64_Byte_Data;			// RX buffer data payload size
    	MRAMConfiguration.TxEventFIFONumElements = 0;								// TX Event FIFO number of elements
    	MRAMConfiguration.TxBufferNumElements = 2;									// TX buffer number of elements
    	MRAMConfiguration.TxBufferElementSize = MRAM_64_Byte_Data;	// TX buffer data payload size
    	
    	/* Configure the MCAN core with the settings above, the changes in this block are write protected registers,      *
    	 * so it makes the most sense to do them all at once, so we only unlock and lock once                             */
    
    	TCAN4x5x_MCAN_EnableProtectedRegisters();											// Start by making protected registers accessible
    	TCAN4x5x_MCAN_ConfigureCCCRRegister(&cccrConfig);							// Disable FD mode and Bit rate switching
    	TCAN4x5x_MCAN_ConfigureGlobalFilter(&gfc);                 	  // Configure the global filter configuration (Default CAN message behavior)
    	TCAN4x5x_MCAN_ConfigureNominalTiming_Simple(&TCANNomTiming);	// Setup nominal/arbitration bit timing
    	TCAN4x5x_MCAN_ConfigureDataTiming_Simple(&TCANDataTiming);		// Setup CAN FD timing
    	TCAN4x5x_MRAM_Clear();																				// Clear all of MRAM (Writes 0's to all of it)
    	TCAN4x5x_MRAM_Configure(&MRAMConfiguration);									// Set up the applicable registers related to MRAM configuration
    	TCAN4x5x_MCAN_DisableProtectedRegisters();										// Disable protected write and take device out of INIT mode
    	
    	/* Set the interrupts we want to enable for MCAN */
    	TCAN4x5x_MCAN_Interrupt_Enable mcan_ie = {0};					// Remember to initialize to 0, or you'll get random garbage!
    	mcan_ie.RF0NE = 1;																		// RX FIFO 0 new message interrupt enable
    
    	TCAN4x5x_MCAN_ConfigureInterruptEnable(&mcan_ie);			// Enable the appropriate registers
    
    	/* Setup filters, this filter will mark any message with ID 0x055 as a priority message */
    	TCAN4x5x_MCAN_SID_Filter SID_ID = {0};	
    	SID_ID.SFT = TCAN4x5x_SID_SFT_CLASSIC;								// SFT: Standard filter type. Configured as a classic filter
    	SID_ID.SFEC = TCAN4x5x_SID_SFEC_PRIORITYSTORERX0;			// Standard filter element configuration, store it in RX fifo 0 as a priority message
    	SID_ID.SFID1 = 0x055;																	// SFID1 (Classic mode Filter)
    	SID_ID.SFID2 = 0x7FF;																	// SFID2 (Classic mode Mask)
    	TCAN4x5x_MCAN_WriteSIDFilter(0, &SID_ID);							// Write to the MRAM
    	
    	/* Store ID 0x12345678 as a priority message */
    	TCAN4x5x_MCAN_XID_Filter XID_ID = {0};
    	XID_ID.EFT = TCAN4x5x_XID_EFT_CLASSIC;                      // EFT
    	XID_ID.EFEC = TCAN4x5x_XID_EFEC_PRIORITYSTORERX0;           // EFEC
    	XID_ID.EFID1 = 0x12345678;                                  // EFID1 (Classic mode filter)
    	XID_ID.EFID2 = 0x1FFFFFFF;                                  // EFID2 (Classic mode mask)
    	TCAN4x5x_MCAN_WriteXIDFilter(0, &XID_ID);                   // Write to the MRAM
    	
    	/* Configure the TCAN4550 Non-CAN-related functions */
    	TCAN4x5x_DEV_CONFIG devConfig = {0};                        		 // Remember to initialize to 0, or you'll get random garbage!
    	devConfig.SWE_DIS = 0;                                		       // Keep Sleep Wake Error Enabled (it's a disable bit, not an enable)
    	devConfig.DEVICE_RESET = 0;                                 		 // Not requesting a software reset
    	devConfig.WD_EN = 0;                                		         // Watchdog disabled
    	devConfig.nWKRQ_CONFIG = 0;                            			     // Mirror INH function (default)
    	devConfig.INH_DIS = 0;                                      		 // INH enabled (default)
    	devConfig.GPIO1_GPO_CONFIG = TCAN4x5x_DEV_CONFIG_GPO1_MCAN_INT1; // MCAN nINT 1 (default)
    	devConfig.FAIL_SAFE_EN = 0;                                 		 // Failsafe disabled (default)
    	devConfig.GPIO1_CONFIG = TCAN4x5x_DEV_CONFIG_GPIO1_CONFIG_GPO;   // GPIO set as GPO (Default)
    	devConfig.WD_ACTION = TCAN4x5x_DEV_CONFIG_WDT_ACTION_nINT;  		 // Watchdog set an interrupt (default)
    	devConfig.WD_BIT_RESET = 0;                                 		 // Don't reset the watchdog
    	devConfig.nWKRQ_VOLTAGE = 0;                                		 // Set nWKRQ to internal voltage rail (default)
    	devConfig.GPO2_CONFIG = TCAN4x5x_DEV_CONFIG_GPO2_NO_ACTION; 		 // GPO2 has no behavior (default)
    	devConfig.CLK_REF = 1;                                      		 // Input crystal is a 40 MHz crystal (default)
    	devConfig.WAKE_CONFIG = TCAN4x5x_DEV_CONFIG_WAKE_BOTH_EDGES;		 // Wake pin can be triggered by either edge (default)
      TCAN4x5x_Device_Configure(&devConfig);                      		 // Configure the device with the above configuration
    
    	TCAN4x5x_Device_SetMode(TCAN4x5x_DEVICE_MODE_NORMAL);       		 // Set to normal mode, since configuration is done. This line turns on the transceiver
    
    	TCAN4x5x_MCAN_ClearInterruptsAll();                         		// Resets all MCAN interrupts (does NOT include any SPIERR interrupts)
    }
    
    

  • Hi Timo,

    Glad to hear you could resolve the previous issue.

    I agree that is sounds like the current error frame is being generated in response to the DLC of 0 being used in a data frame. It doesn't align with the code you shared, but the RTR bit in the waveform you shared (directly following the ID field) is dominant, indicating that this is a data frame and the data length code appears to be zero in the frame (despite the stuff bit). As it would not make sense to transmit a data frame with a length of zero, this may be what's causing the error, though I am not certain. Additionally, it sounds like you receive the same error even when the frame is configured as a remote frame.  

    • When this error is generated, is the TCA4550 board connected to a bus with another active controller? Can you tell which node is generating the error frame?
      • If there is a receiving node, be sure it is configured for the same data rate (1Mbps) as the TCAN4550. 
    • Is an error frame generated when you try to send a data frame? (DLC > 0 and RTR set for data frame)

    Regards,
    Eric Schott

  • Hi Eric,

    I have no other devices on a CAN bus. I have only connected the oscilloscope to the CANH and CANL line of the TCAN4550 and try to send out a message.

    The error frame and DLC=0 always come no matter what settings I try. But if I change in the code e.g. the RTR bit or XTD bit, then I see on the oscilloscope that it worked. If I send the message as a remot frame and write 0 at DLC, then I get the error too. It doesn't matter what or how I write the value into DLC.

    with regards

    Timo

  • Hi Timo,

    This does indeed sound strange. I have used the demo code configuration many times and never encountered this issue with inconsistent DLC in the code vs the waveform. I couldn't see any modifications that would change this behavior, but were there any other parts of the configuration that you changed from the demo that could impact the behavior of the arbitration portion of the frame?

    Please specify in which conditions this setup appears to function correctly. What are the working values of the RTR bit? XTD bit? Which configurations make the DLC in the waveform reflect what is shown in the software? 

    Regards,
    Eric Schott

  • Hi Eric,

    I did not change anything in the demo that could affect the behavior of the arbitration part of the frame. I only included a .h file in TCAN4x5x_Data_Structs.h so that the program recognizes the data type "uint8_t". Additionally I renamed in this file in the struct of the bit fieds of the cccr register the variable "uint8_t MON" (line 264)  in "uint_8 MONI", because the variable "MON" is already stored zw. created for the Infineon. But all this should have no impact on the DLC, right?

    I think you misunderstood me. The DLC always has the value 0 no matter which configurations I try. I just meant that if I change the RTR bit, for example, then the oscilloscope also shows me that I send a remote frame, but the DLC is then also automatically 0 no matter what I enter and an error frame also comes. The same with XID, if I set there a 1, then I get on the Oszilosskop a longer ID, however remains there also DLC = 0 no matter what I enter.
    So the DLC is never displayed in the waveform as it is set in the software, it always remains 0.

    To get to the bottom of it, I tried the TestMode "SPI and M_CAN Core Test Mode". At first I wanted to use the functions from the library, but I didn't find anywhere a description which of them would be the appropriate mode. With the command "AHB_WRITE_32(0x0800, 0xC82004A1);" I activated the TestMode (Watchdog off, otherwise I got no signal on GPO2). With activated TestMode I tried to send a CAN message with the same structure as in the example. I got the picture below on the Oszilosskop. I get a clock, but only that the CAN message is set to be sent continuously. If the message should be sent only once, then I get only the first edge and nothing else.

    Why is it that I don't even get a proper signal in this TestMode and is it possible that this is why I get DLC = 0? Or do you have another idea?

    Thank you very much.

    Regards

    Timo

  • Hi Timo,

    The functional call TCAN4x5x_Device_EnableTestMode(TCAN4x5x_DEVICE_TEST_MODE_CONTROLLER); will configure the device to SPI and MCAN test mode, breaking out the TXD and RXD signals GPO2 and GPIO1 respectfully. In this state, the CAN controller will still expect to see its own data reflected from the CAN bus (RXD should be dominant whenever TXD is dominant). If the RXD signal is ever sampled high while TXD is driven low, the device will recognize it as an error. Make sure that there is some loopback occurring from the TXD (GPO2) to RXD (GPIO1) signal, weather from digital connection or through a CAN transceiver (to simulate loop delay). 

    I don't see a shared scope shot. Did you mean to post it separately?

    Regards,
    Eric Schott

  • Hi Eric,

    I am sorry, I forgot to send the scope shot. But I have found the error. When writing to the TX buffer, only 1 word was written. All other values that were in the second or third word were not written to the buffer. Now I get the whole CAN message sent and can set and change DLC and everything else.

    The only problem I have now (and hopefully the last) is that I still get the error frame at the end of each message. No matter if remote or data frame. What could be the reason for this? I have attached the image of the message below.

    Regards

    Timo

  • Hi Timo,

    Sorry I haven't had time to look into this further. Tomorrow I'll run some tests to see if I can recreate what you're seeing here.

    Remind me again, this setup consists only of the TCAN4550 correct? No other nodes on the CAN bus?

    Regards,
    Eric Schott

  • Hi eric,

    Yes exactly this setup consists only of the TCAN4550 sending out a message. The oscilloscope records this message, but there is no other node.

    Regards

    Timo

  • Hi Eric,

    I noticed that the Error Frame disappears, when I conncet the TCAN4550EVM to another CAN node.

    Thank you for all your support.

    Regards

    Timo