Other Parts Discussed in Thread: C2000WARE, TMDSCNCD28379D
Hi,
I need to use CAN to communicate with other product.
I start with the example "can_loopback_cpu01" to analyze registers settings. In this example, we use 2 functions, " CANMessageSet" and " CANMessageGet".
For more flexibility, I don't want to use these functions; but writing directly in the registers.
I've tried to convert the code, but it doesn't works.
I can see signals on the oscilloscope for Tx and Rx, but "NewDat" bit on a receipt is always '0'.
I've configured all the registers (CAN_IF1CMD, CAN_IF2CMD, CAN_IF1MSK, CAN_IF2MSK, CAN_IF1ARB, CAN_IF2ARB, CAN_IF1MCTL and CAN_IF2MCTL) to have the same settings than the original program.
//########################################################################### // // FILE: can_loopback.c // // TITLE: Example to demonstrate basic CAN setup and use. // //! \addtogroup cpu01_example_list //! <h1>CAN External Loopback Using Driverlib (can_loopback)</h1> //! //! This example, using driverlib, shows the basic setup of CAN in order to //! transmit and receive messages on the CAN bus. The CAN peripheral is //! configured to transmit messages with a specific CAN ID. A message is then //! transmitted once per second, using a simple delay loop for timing. The //! message that is sent is a 4 byte message that contains an incrementing //! pattern. //! //! This example sets up the CAN controller in External Loopback test mode. //! Data transmitted is visible on the CAN0TX pin and can be received with //! an appropriate mailbox configuration. //! //! \b Watch \b Variables \n //! - g_ulMsgCount - A counter for the number of successful messages received //! - g_bErrFlag - Indicates the data received didn't match the //! transmitted data //! // //########################################################################### // $TI Release: F2837xD Support Library v3.05.00.00 $ // $Release Date: Thu Oct 18 15:48:42 CDT 2018 $ // $Copyright: // Copyright (C) 2013-2018 Texas Instruments Incorporated - http://www.ti.com/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // $ //########################################################################### // // Included Files // #include "F28x_Project.h" #include <stdint.h> #include <stdbool.h> #include "inc/hw_types.h" #include "inc/hw_memmap.h" #include "inc/hw_can.h" #include "driverlib/can.h" // // Globals // volatile unsigned long g_ulMsgCount = 0; // A counter that keeps track of the // number of times the transmit was // successful. volatile unsigned long g_bErrFlag = 0; // A flag to indicate that some // transmission error occurred. // // Main // int main(void) { tCANMsgObject sTXCANMessage; tCANMsgObject sRXCANMessage; unsigned int ucTXMsgData[2], ucRXMsgData[2]; uint32_t ui32CmdMaskReg; uint32_t ui32MaskReg; uint32_t ui32ArbReg; uint32_t ui32MsgCtrl; int16_t iMsg; // // Step 1. Initialize System Control: // PLL, WatchDog, enable Peripheral Clocks // This example function is found in the F2837xD_SysCtrl.c file. // InitSysCtrl(); // // Step 2. Initialize GPIO: // This example function is found in the F2837xD_Gpio.c file and // illustrates how to set the GPIO to its default state. // InitGpio(); /*GPIO_SetupPinMux(30, GPIO_MUX_CPU1, 1); //GPIO30 - CANRXA GPIO_SetupPinMux(31, GPIO_MUX_CPU1, 1); //GPIO31 - CANTXA GPIO_SetupPinOptions(30, GPIO_INPUT, GPIO_ASYNC); GPIO_SetupPinOptions(31, GPIO_OUTPUT, GPIO_PUSHPULL);*/ /*GPIO_SetupPinMux(21, GPIO_MUX_CPU1, 3); //GPIO30 - CANRXA GPIO_SetupPinMux(20, GPIO_MUX_CPU1, 3); //GPIO31 - CANTXA GPIO_SetupPinOptions(21, GPIO_INPUT, GPIO_ASYNC); GPIO_SetupPinOptions(20, GPIO_OUTPUT, GPIO_PUSHPULL);*/ EALLOW; GpioCtrlRegs.GPAPUD.bit.GPIO20 = 0; // Enable pullup on GPIO20 GpioCtrlRegs.GPAPUD.bit.GPIO21 = 0; // Enable pullup on GPIO21 GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 3; // GPIO20 = CANTXB GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 3; // GPIO21 = CANRXB GpioCtrlRegs.GPAQSEL2.bit.GPIO21 = 3; // asynch input EDIS; // // Initialize the CAN controller // //CANInit(CANB_BASE); // // Place CAN controller in init state, regardless of previous state. This // will put controller in idle, and allow the message object RAM to be // programmed. // CanbRegs.CAN_CTL.bit.Init = 1; // CAN module ignores bus activity EALLOW; CanbRegs.CAN_CTL.bit.SWR = 1; // Module is forced to reset state. This bit will get cleared automatically one clock cycle after execution of software reset. EDIS; CanbRegs.CAN_CTL.bit.CCE = 1; // The CPU has write access to the configuration registers (when Init bit is set). // // Setup CAN to be clocked off the M3/Master subsystem clock // //CANClkSourceSelect(CANB_BASE, 0); EALLOW; // Configure the eCAN timing // CANB Bit-Clock Source Select Bit: ClkCfgRegs.CLKSRCCTL2.bit.CANBBCLKSEL = 0; // 00 = PERx.SYSCLK (default on reset) EDIS; // // Set up the bit rate for the CAN bus. This function sets up the CAN // bus timing for a nominal configuration. You can achieve more control // over the CAN bus timing by using the function CANBitTimingSet() instead // of this one, if needed. // In this example, the CAN bus is set to 500 kHz. In the function below, // the call to SysCtlClockGet() is used to determine the clock rate that // is used for clocking the CAN peripheral. This can be replaced with a // fixed value if you know the value of the system clock, saving the extra // function call. For some parts, the CAN peripheral is clocked by a fixed // 8 MHz regardless of the system clock in which case the call to // SysCtlClockGet() should be replaced with 8000000. Consult the data // sheet for more information about CAN peripheral clocking. // // CANBitRateSet(CANB_BASE, 200000000, 125000); CanbRegs.CAN_BTR.bit.BRPE = 1; // Baud Rate Prescaler Extension - Valid programmed values are 0 to 15. CanbRegs.CAN_BTR.bit.BRP = 58; // Baud Rate Prescaler - Value by which the CAN_CLK frequency is divided for generating the bit time quanta. The bit time is built up from a multiple of this quanta. // ////////////////////////////////////////////// Maximum : 64 (6 bits) // Prescaler calculation : BRPE - BRP bits : XXXX XXXXXX = 0001 100011 = 0110 0011 = 99 Scaled_Clock (tq) = SYSCLK / PRESCAL = 200Mhz / (Prescale + 1) = 2Mhz CanbRegs.CAN_BTR.bit.TSEG1 = 6; CanbRegs.CAN_BTR.bit.TSEG2 = 4; CanbRegs.CAN_BTR.bit.SJW = 3; // // Step 3. Clear all interrupts and initialize PIE vector table: // Disable CPU interrupts // DINT; // // Initialize the PIE control registers to their default state. // The default state is all PIE interrupts disabled and flags // are cleared. // This function is found in the F2837xD_PieCtrl.c file. // InitPieCtrl(); // // Disable CPU interrupts and clear all CPU interrupt flags: // IER = 0x0000; IFR = 0x0000; // // Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR). // This will populate the entire table, even if the interrupt // is not used in this example. This is useful for debug purposes. // The shell ISR routines are found in F2837xD_DefaultIsr.c. // This function is found in F2837xD_PieVect.c. // InitPieVectTable(); // // Enable test mode and select external loopback // HWREG(CANB_BASE + CAN_O_CTL) |= CAN_CTL_TEST; HWREG(CANB_BASE + CAN_O_TEST) = CAN_TEST_EXL; // // Enable the CAN for operation. // CanbRegs.CAN_CTL.bit.Init = 0; // Enable CAN - CAN module processes messages normally // // Initialize the message object that will be used for sending CAN // messages. The message will be 4 bytes that will contain an incrementing // value. Initially it will be set to 0. // /* sTXCANMessage.ui32MsgID = 1; // CAN message ID - use 1 sTXCANMessage.ui32MsgIDMask = 0; // no mask needed for TX sTXCANMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE; // enable interrupt on TX sTXCANMessage.ui32MsgLen = sizeof(ucTXMsgData); // size of message is 4 sTXCANMessage.pucMsgData = ucTXMsgData; // ptr to message content */ CanbRegs.CAN_IF1ARB.bit.ID = 0x0040000; // CAN message ID - use 1 CanbRegs.CAN_IF1ARB.bit.Dir = 1; // Direction = transmit. On TxRqst, the respective message object is transmitted as a data frame. CanbRegs.CAN_IF1ARB.bit.MsgVal = 1; // The mailbox is enabled. CanbRegs.CAN_IF1ARB.bit.Xtd = 0; // The 11-bit ("standard") Identifier is used for this message object. CanbRegs.CAN_IF1MCTL.bit.UMask = 0; // Mask ignored CanbRegs.CAN_IF1MCTL.bit.DLC = 2; // size of message is 2 CanbRegs.CAN_IF1MCTL.bit.TxIE = 1; // IntPnd will be triggered after the successful transmission of a frame. CanbRegs.CAN_IF1MCTL.bit.EoB = 1; // The message object is a single message object or the last message object in a FIFO Buffer Block. CanbRegs.CAN_IF1MSK.all = 0x20000000; // The corresponding bit in the identifier of the message object is not used for acceptance filtering // // Initialize the message object that will be used for receiving CAN // messages. // /* sRXCANMessage.ui32MsgID = 1; // CAN message ID - use 1 sRXCANMessage.ui32MsgIDMask = 0; // no mask needed for TX sRXCANMessage.ui32Flags = MSG_OBJ_NO_FLAGS; sRXCANMessage.ui32MsgLen = sizeof(ucRXMsgData); // size of message is 4 sRXCANMessage.pucMsgData = ucRXMsgData; // ptr to message content */ CanbRegs.CAN_IF2ARB.bit.ID = 0x0040000; // CAN message ID - use 1 CanbRegs.CAN_IF2ARB.bit.Dir = 0; // Direction = receive CanbRegs.CAN_IF2ARB.bit.MsgVal = 1; // The mailbox is enabled. CanbRegs.CAN_IF2ARB.bit.Xtd = 0; // The 11-bit ("standard") Identifier is used for this message object. CanbRegs.CAN_IF2MCTL.bit.UMask = 0; // Mask ignored CanbRegs.CAN_IF2MCTL.bit.TxIE = 0; // IntPnd will not be triggered after the successful transmission of a frame. CanbRegs.CAN_IF2MCTL.bit.RxIE = 0; // IntPnd will not be triggered after the successful reception of a frame. CanbRegs.CAN_IF2MCTL.bit.RmtEn = 0; // At the reception of a remote frame, TxRqst is not changed. CanbRegs.CAN_IF2MCTL.bit.EoB = 1; // The message object is a single message object or the last message object in a FIFO Buffer Block. CanbRegs.CAN_IF2MCTL.bit.IntPnd = 0; // This message object is not the source of an interrupt. CanbRegs.CAN_IF2MCTL.bit.DLC = 2; // Size of message is 2 CanbRegs.CAN_IF2MSK.all = 0xB19E0C8C; // The corresponding bit in the identifier of the message object is not used for acceptance filtering // // Setup send and receive buffers // ucTXMsgData[0] = 0x01; ucTXMsgData[1] = 0x02; *(unsigned long *)ucRXMsgData = 0; // // Setup the message object being used to receive messages // //CANMessageSet(CANB_BASE, 2, &sRXCANMessage, MSG_OBJ_TYPE_RX); while(CanbRegs.CAN_IF2CMD.bit.Busy) // 1 Transfer between IF2 Register Set and Message RAM is in progress. { } CanbRegs.CAN_IF2CMD.bit.DIR = 0; // Direction = Read: Transfer direction is from the message object addressed by Message Number (Bits [7:0]) to the IF1/IF2 Register CanbRegs.CAN_IF2DATA.bit.Data_0 = *ucRXMsgData; // ptr to message content CanbRegs.CAN_IF2CMD.bit.MSG_NUM = 2; // Transfer the message object // // Enter loop to send messages. A new message will be sent once per // second. The 4 bytes of message content will be treated as an unsigned // long and incremented by one each time. // while(1) { // // Send the CAN message using object number 1 (not the same thing as // CAN ID, which is also 1 in this example). This function will cause // the message to be transmitted right away. // //CANMessageSet(CANB_BASE, 1, &sTXCANMessage, MSG_OBJ_TYPE_TX); while(CanbRegs.CAN_IF1CMD.bit.Busy) // 1 Transfer between IF1 Register Set and Message RAM is in progress. { } CanbRegs.CAN_IF1CMD.bit.DIR = 1; // Transfer direction is from the IF1 Register set to the message object CanbRegs.CAN_IF1DATA.bit.Data_0 = ucTXMsgData[0]; // ptr to message content CanbRegs.CAN_IF1DATA.bit.Data_1 = ucTXMsgData[1]; // ptr to message content CanbRegs.CAN_IF1MCTL.bit.TxRqst = 1; // The transmission of this message object is requested and is not yet done. CanbRegs.CAN_IF1CMD.bit.Arb = 1; // The Arbitration bits (Identifier + Dir + Xtd + MsgVal) will be transferred CanbRegs.CAN_IF1CMD.bit.Control = 1; // The message control bits will be transferred CanbRegs.CAN_IF1CMD.bit.DATA_A = 1; // The Data Bytes 0-3 will be transferred CanbRegs.CAN_IF1CMD.bit.DATA_B = 1; // The Data Bytes 0-3 will be transferred CanbRegs.CAN_IF1CMD.bit.MSG_NUM = 1; // Transfer the message object CanbRegs.CAN_IF1DATA.bit.Data_0 = ucTXMsgData[0]; // ptr to message content CanbRegs.CAN_IF1DATA.bit.Data_1 = ucTXMsgData[1]; // ptr to message content CanbRegs.CAN_IF1MCTL.bit.TxRqst = 1; // The transmission of this message object is requested and is not yet done. // // Now wait 1 second before continuing // DELAY_US(10*1000); // // Get the receive message // //CANMessageGet(CANB_BASE, 2, &sRXCANMessage, true); CanbRegs.CAN_IF2CMD.bit.TxRqst = 1; // Clears NewDat bit in the message object. CanbRegs.CAN_IF2CMD.bit.MSG_NUM = 2; // Transfer the message object while (CanbRegs.CAN_IF2CMD.bit.Busy) // Transfer between IF1/IF2 Register Set and Message RAM is in progress. { } if (CanbRegs.CAN_IF2MCTL.bit.NewDat == 1) // The message handler or the CPU has written new data into the data portion of this message object. { CanbRegs.CAN_IF2CMD.bit.TxRqst = 1; // Clears NewDat bit in the message object. CanbRegs.CAN_IF2CMD.bit.MSG_NUM = 2; // Transfer the message object while(CanbRegs.CAN_IF2CMD.bit.Busy) // 1 Transfer between IF1/IF2 Register Set and Message RAM is in progress. { } } // // Ensure the received data matches the transmitted data // if((ucTXMsgData[0] != ucRXMsgData[0]) || (ucTXMsgData[1] != ucRXMsgData[1])) { g_bErrFlag++; //asm(" ESTOP0"); } else { // // Increment message received counter // g_ulMsgCount++; } // Increment the value in the transmitted message data. // // ucTXMsgData[0] += 0x01; ucTXMsgData[1] += 0x02; // // Reset data if exceeds a byte // if(ucTXMsgData[0] > 0xFF) { ucTXMsgData[0] = 0; } if(ucTXMsgData[1] > 0xFF) { ucTXMsgData[1] = 0; } } } // // End of file //
Where're the mistakes?
Thank you.
Regards