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.

TM4C1294 CAN

再請教一下
如果CAN的TX和RX腳位對接,可以以這樣測試發送和接收數據嗎?
還是一定要接CAN transceiver才有辦法測試呢?
謝謝
  • 您可以尝试使用下面的代码

    e2e.ti.com/.../1280698
  • Hi Susan
    目前我使用以下代碼測試CAN0與CAN1發送與接收測試
    但是好像無法正常工作,是不是還有哪裡沒設定正確呢?


    extern uint32_t g_ui32SysClock;
    volatile uint8_t CAN0ErrFlag = 0;
    volatile uint8_t CAN1ErrFlag = 0;
    tCANMsgObject CAN0RxMsgObject,CAN0TxMsgObject; //CAN0 have32 objects
    tCANMsgObject CAN1RxMsgObject,CAN1TxMsgObject; //CAN1 have32 objects
    uint8_t CAN0_Obj1RxData[8],CAN0_Obj2RxData[8],CAN0_Obj3RxData[8];
    uint8_t CAN1_Obj1RxData[8],CAN1_Obj2RxData[8],CAN1_Obj3RxData[8];

    uint8_t CAN0_Obj1TxData[8],CAN1_Obj1TxData[8];
    volatile bool CAN0TxMsgObj4Sent = 0;
    volatile bool CAN1TxMsgObj4Sent = 0;

    void
    CAN0IntHandler(void)
    {
    uint32_t ui32Status;

    //
    // Read the CAN interrupt status to find the cause of the interrupt
    //
    ui32Status = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE);

    //
    // If the cause is a controller status interrupt, then get the status
    //
    if(ui32Status == CAN_INT_INTID_STATUS)
    {
    //
    // Read the controller status. This will return a field of status
    // error bits that can indicate various errors. Error processing
    // is not done in this example for simplicity. Refer to the
    // API documentation for details about the error status bits.
    // The act of reading this status will clear the interrupt.
    //
    ui32Status = CANStatusGet(CAN0_BASE, CAN_STS_CONTROL);

    CAN0ErrFlag++;
    }

    //
    // Check if the cause is message object 1.
    //
    else if(ui32Status == 1)
    {
    CANIntClear(CAN0_BASE, ui32Status);

    CAN0RxMsgObject.pui8MsgData = CAN0_Obj1RxData;

    CANMessageGet(CAN0_BASE, ui32Status, &CAN0RxMsgObject, 0);

    CAN0ErrFlag = 0;
    }

    //
    // Check if the cause is message object 2.
    //
    else if(ui32Status == 2)
    {
    CANIntClear(CAN0_BASE, ui32Status);

    CAN0RxMsgObject.pui8MsgData = CAN0_Obj2RxData;

    CANMessageGet(CAN0_BASE, ui32Status, &CAN0RxMsgObject, 0);

    CAN0ErrFlag = 0;
    }

    //
    // Check if the cause is message object 3.
    //
    else if(ui32Status == 3)
    {
    CANIntClear(CAN0_BASE, ui32Status);

    CAN0RxMsgObject.pui8MsgData = CAN0_Obj3RxData;

    CANMessageGet(CAN0_BASE, ui32Status, &CAN0RxMsgObject, 0);

    CAN0ErrFlag = 0;
    }

    // Check if the cause is message object 4, which is used for sending messages.

    else if(ui32Status == 4)
    {

    CANIntClear(CAN0_BASE, ui32Status);

    CAN0TxMsgObj4Sent = 1;

    CAN0ErrFlag = 0;
    }
    }

    void
    CAN1IntHandler(void)
    {
    uint32_t ui32Status;

    //
    // Read the CAN interrupt status to find the cause of the interrupt
    //
    ui32Status = CANIntStatus(CAN1_BASE, CAN_INT_STS_CAUSE);

    //
    // If the cause is a controller status interrupt, then get the status
    //
    if(ui32Status == CAN_INT_INTID_STATUS)
    {
    //
    // Read the controller status. This will return a field of status
    // error bits that can indicate various errors. Error processing
    // is not done in this example for simplicity. Refer to the
    // API documentation for details about the error status bits.
    // The act of reading this status will clear the interrupt.
    //
    ui32Status = CANStatusGet(CAN1_BASE, CAN_STS_CONTROL);

    CAN1ErrFlag++;
    }

    //
    // Check if the cause is message object 1.
    //
    else if(ui32Status == 1)
    {
    CANIntClear(CAN1_BASE, 1);

    CAN1RxMsgObject.pui8MsgData = CAN1_Obj1RxData;

    CANMessageGet(CAN0_BASE, ui32Status, &CAN1RxMsgObject, 0);

    CAN1ErrFlag = 0;

    }

    //
    // Check if the cause is message object 2.
    //
    else if(ui32Status == 2)
    {
    CANIntClear(CAN1_BASE, 2);

    CAN1RxMsgObject.pui8MsgData = CAN1_Obj2RxData;

    CANMessageGet(CAN0_BASE, ui32Status, &CAN1RxMsgObject, 0);

    CAN1ErrFlag = 0;
    }

    //
    // Check if the cause is message object 3.
    //
    else if(ui32Status == 3)
    {
    CANIntClear(CAN1_BASE, 3);

    CAN1RxMsgObject.pui8MsgData = CAN1_Obj3RxData;

    CANMessageGet(CAN0_BASE, ui32Status, &CAN1RxMsgObject, 0);

    CAN1ErrFlag = 0;
    }

    // Check if the cause is message object 4, which is used for sending messages.

    else if(ui32Status == 4)
    {

    CANIntClear(CAN1_BASE, ui32Status);

    CAN1TxMsgObj4Sent = 1;

    CAN1ErrFlag = 0;
    }
    }

    void CAN0RXConfig(uint8_t ObjNum,uint32_t MsgID)
    {
    // Initialize a message object to receive CAN messages with ID 0x1001.
    // The expected ID must be set along with the mask to indicate that all
    // bits in the ID must match.
    //
    CAN0RxMsgObject.ui32MsgID = MsgID;
    CAN0RxMsgObject.ui32MsgIDMask = 0xfffff;
    CAN0RxMsgObject.ui32Flags = (MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER |
    MSG_OBJ_EXTENDED_ID);
    CAN0RxMsgObject.ui32MsgLen = 8;

    // Now load the message object into the CAN peripheral message object 1.
    // Once loaded the CAN will receive any messages with this CAN ID into
    // this message object, and an interrupt will occur.
    //
    CANMessageSet(CAN0_BASE, ObjNum, &CAN0RxMsgObject, MSG_OBJ_TYPE_RX);
    }

    void CAN1RXConfig(uint8_t ObjNum,uint32_t MsgID)
    {
    // Initialize a message object to receive CAN messages with ID 0x1001.
    // The expected ID must be set along with the mask to indicate that all
    // bits in the ID must match.
    //
    CAN1RxMsgObject.ui32MsgID = MsgID;
    CAN1RxMsgObject.ui32MsgIDMask = 0xfffff;
    CAN1RxMsgObject.ui32Flags = (MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER |
    MSG_OBJ_EXTENDED_ID);
    CAN1RxMsgObject.ui32MsgLen = 8;

    // Now load the message object into the CAN peripheral message object 1.
    // Once loaded the CAN will receive any messages with this CAN ID into
    // this message object, and an interrupt will occur.
    //
    CANMessageSet(CAN0_BASE, ObjNum, &CAN1RxMsgObject, MSG_OBJ_TYPE_RX);
    }

    void CANMultiRXConfig()
    {
    CAN0RXConfig(1,0x1001);
    CAN0RXConfig(2,0x1002);
    CAN0RXConfig(3,0x1003);

    CAN1RXConfig(1,0x2001);
    CAN1RXConfig(2,0x2002);
    CAN1RXConfig(3,0x2003);
    }

    void CAN0TXSend(uint8_t ObjNum,uint32_t MsgID)
    {
    CAN0TxMsgObject.ui32MsgID = MsgID;
    CAN0TxMsgObject.ui32MsgIDMask = 0;
    CAN0TxMsgObject.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
    CAN0TxMsgObject.ui32MsgLen = sizeof(CAN0_Obj1TxData);

    CAN0_Obj1TxData[0]++;
    CAN0TxMsgObject.pui8MsgData = CAN0_Obj1TxData;

    CAN0TxMsgObj4Sent=0;
    CANMessageSet(CAN0_BASE, ObjNum, &CAN0TxMsgObject, MSG_OBJ_TYPE_TX);
    }

    void CAN1TXSend(uint8_t ObjNum,uint32_t MsgID)
    {
    CAN1TxMsgObject.ui32MsgID = MsgID;
    CAN1TxMsgObject.ui32MsgIDMask = 0;
    CAN1TxMsgObject.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
    CAN1TxMsgObject.ui32MsgLen = sizeof(CAN1_Obj1TxData);

    CAN1_Obj1TxData[0]++;
    CAN1TxMsgObject.pui8MsgData = CAN1_Obj1TxData;

    CAN1TxMsgObj4Sent=0;
    CANMessageSet(CAN1_BASE, ObjNum, &CAN1TxMsgObject, MSG_OBJ_TYPE_TX);
    }


    void CANInitial(void)
    {
    SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0); // The GPIO port and pins have been set up for CAN. The CAN peripheral must be enabled.

    CANInit(CAN0_BASE); // Initialize the CAN controller

    CANBitRateSet(CAN0_BASE, g_ui32SysClock, 1000000u); // Set up the 1M bit rate for the CAN bus.

    //HWREG(CAN0_BASE+CAN_O_CTL) |= CAN_CTL_TEST;
    //HWREG(CAN0_BASE+CAN_O_TST) |= CAN_TST_LBACK;

    //CANIntRegister(CAN0_BASE, CAN0IntHandler); // if using dynamic vectors

    CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);

    IntEnable(INT_CAN0);// Enable the CAN interrupt on the processor (NVIC).

    CANEnable(CAN0_BASE);// Enable the CAN for operation.


    SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN1); // The GPIO port and pins have been set up for CAN. The CAN peripheral must be enabled.

    CANInit(CAN1_BASE); // Initialize the CAN controller

    CANBitRateSet(CAN1_BASE, g_ui32SysClock, 1000000u); // Set up the 1M bit rate for the CAN bus.

    //CANIntRegister(CAN1_BASE, CAN1IntHandler); // if using dynamic vectors

    CANIntEnable(CAN1_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);

    IntEnable(INT_CAN1);// Enable the CAN interrupt on the processor (NVIC).

    CANEnable(CAN1_BASE);// Enable the CAN for operation.

    CANMultiRXConfig();
    }



    每100ms調用TX function
    CAN0TXSend(4,0x2001);
    CAN1TXSend(4,0x1001);
  • 请您之后使用高级编辑器的工具来上传代码

    “目前我使用以下代碼測試CAN0與CAN1發送與接收測試
    但是好像無法正常工作,是不是還有哪裡沒設定正確呢?”

    请问能否详细说一下您的硬件情况吗?是否使用开发板,几块开发板?是否有接transceiver?

    另外是否有测量CAN引脚的波形?
  • Hi Susan

    目前是使用開發版TM4C1294XL Rev D

    一塊開發版測試CAN0與CAN1發送與接收測試

    一開始就有提到沒有接transceiver測試

    無量測CAN引脚的波形

    CANFunctions.c
    #include "CANFunctions.h"
    
    extern uint32_t g_ui32SysClock;
    volatile uint8_t CAN0ErrFlag = 0;
    volatile uint8_t CAN1ErrFlag = 0;
    tCANMsgObject CAN0RxMsgObject,CAN0TxMsgObject; //CAN0 have32 objects
    tCANMsgObject CAN1RxMsgObject,CAN1TxMsgObject; //CAN1 have32 objects
    uint8_t CAN0_Obj1RxData[8],CAN0_Obj2RxData[8],CAN0_Obj3RxData[8];
    uint8_t CAN1_Obj1RxData[8],CAN1_Obj2RxData[8],CAN1_Obj3RxData[8];
    
    uint8_t CAN0_Obj1TxData[8],CAN1_Obj1TxData[8];
    volatile bool CAN0TxMsgObj4Sent = 0;
    volatile bool CAN1TxMsgObj4Sent = 0;
    
    void
    CAN0IntHandler(void)
    {
        uint32_t ui32Status;
    
        //
        // Read the CAN interrupt status to find the cause of the interrupt
        //
        ui32Status = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE);
    
        //
        // If the cause is a controller status interrupt, then get the status
        //
        if(ui32Status == CAN_INT_INTID_STATUS)
        {
            //
            // Read the controller status.  This will return a field of status
            // error bits that can indicate various errors.  Error processing
            // is not done in this example for simplicity.  Refer to the
            // API documentation for details about the error status bits.
            // The act of reading this status will clear the interrupt.
            //
            ui32Status = CANStatusGet(CAN0_BASE, CAN_STS_CONTROL);
    
            CAN0ErrFlag++;
        }
    
        //
        // Check if the cause is message object 1.
        //
        else if(ui32Status == 1)
        {
            CANIntClear(CAN0_BASE, ui32Status);
    
            CAN0RxMsgObject.pui8MsgData = CAN0_Obj1RxData;
    
            CANMessageGet(CAN0_BASE, ui32Status, &CAN0RxMsgObject, 0);
    
            CAN0ErrFlag = 0;
        }
    
        //
        // Check if the cause is message object 2.
        //
        else if(ui32Status == 2)
        {
            CANIntClear(CAN0_BASE, ui32Status);
    
            CAN0RxMsgObject.pui8MsgData = CAN0_Obj2RxData;
    
            CANMessageGet(CAN0_BASE, ui32Status, &CAN0RxMsgObject, 0);
    
            CAN0ErrFlag = 0;
        }
    
        //
        // Check if the cause is message object 3.
        //
        else if(ui32Status == 3)
        {
            CANIntClear(CAN0_BASE, ui32Status);
    
            CAN0RxMsgObject.pui8MsgData = CAN0_Obj3RxData;
    
            CANMessageGet(CAN0_BASE, ui32Status, &CAN0RxMsgObject, 0);
    
            CAN0ErrFlag = 0;
        }
    
        // Check if the cause is message object 4, which is used for sending messages.
    
        else if(ui32Status == 4)
        {
    
            CANIntClear(CAN0_BASE, ui32Status);
    
            CAN0TxMsgObj4Sent = 1;
    
            CAN0ErrFlag = 0;
        }
    }
    
    void
    CAN1IntHandler(void)
    {
        uint32_t ui32Status;
    
        //
        // Read the CAN interrupt status to find the cause of the interrupt
        //
        ui32Status = CANIntStatus(CAN1_BASE, CAN_INT_STS_CAUSE);
    
        //
        // If the cause is a controller status interrupt, then get the status
        //
        if(ui32Status == CAN_INT_INTID_STATUS)
        {
            //
            // Read the controller status.  This will return a field of status
            // error bits that can indicate various errors.  Error processing
            // is not done in this example for simplicity.  Refer to the
            // API documentation for details about the error status bits.
            // The act of reading this status will clear the interrupt.
            //
            ui32Status = CANStatusGet(CAN1_BASE, CAN_STS_CONTROL);
    
            CAN1ErrFlag++;
        }
    
        //
        // Check if the cause is message object 1.
        //
        else if(ui32Status == 1)
        {
            CANIntClear(CAN1_BASE, 1);
    
            CAN1RxMsgObject.pui8MsgData = CAN1_Obj1RxData;
    
            CANMessageGet(CAN0_BASE, ui32Status, &CAN1RxMsgObject, 0);
    
            CAN1ErrFlag = 0;
    
        }
    
        //
        // Check if the cause is message object 2.
        //
        else if(ui32Status == 2)
        {
            CANIntClear(CAN1_BASE, 2);
    
            CAN1RxMsgObject.pui8MsgData = CAN1_Obj2RxData;
    
            CANMessageGet(CAN0_BASE, ui32Status, &CAN1RxMsgObject, 0);
    
            CAN1ErrFlag = 0;
        }
    
        //
        // Check if the cause is message object 3.
        //
        else if(ui32Status == 3)
        {
            CANIntClear(CAN1_BASE, 3);
    
            CAN1RxMsgObject.pui8MsgData = CAN1_Obj3RxData;
    
            CANMessageGet(CAN0_BASE, ui32Status, &CAN1RxMsgObject, 0);
    
            CAN1ErrFlag = 0;
        }
    
        // Check if the cause is message object 4, which is used for sending messages.
    
        else if(ui32Status == 4)
        {
    
            CANIntClear(CAN1_BASE, ui32Status);
    
            CAN1TxMsgObj4Sent = 1;
    
            CAN1ErrFlag = 0;
        }
    }
    
    void CAN0RXConfig(uint8_t ObjNum,uint32_t MsgID)
    {
        // Initialize a message object to receive CAN messages with ID 0x1001.
        // The expected ID must be set along with the mask to indicate that all
        // bits in the ID must match.
        //
        CAN0RxMsgObject.ui32MsgID = MsgID;
        CAN0RxMsgObject.ui32MsgIDMask = 0xfffff;
        CAN0RxMsgObject.ui32Flags = (MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER |
                                 MSG_OBJ_EXTENDED_ID);
        CAN0RxMsgObject.ui32MsgLen = 8;
    
        // Now load the message object into the CAN peripheral message object 1.
        // Once loaded the CAN will receive any messages with this CAN ID into
        // this message object, and an interrupt will occur.
        //
        CANMessageSet(CAN0_BASE, ObjNum, &CAN0RxMsgObject, MSG_OBJ_TYPE_RX);
    }
    
    void CAN1RXConfig(uint8_t ObjNum,uint32_t MsgID)
    {
        // Initialize a message object to receive CAN messages with ID 0x1001.
        // The expected ID must be set along with the mask to indicate that all
        // bits in the ID must match.
        //
        CAN1RxMsgObject.ui32MsgID = MsgID;
        CAN1RxMsgObject.ui32MsgIDMask = 0xfffff;
        CAN1RxMsgObject.ui32Flags = (MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER |
                                 MSG_OBJ_EXTENDED_ID);
        CAN1RxMsgObject.ui32MsgLen = 8;
    
        // Now load the message object into the CAN peripheral message object 1.
        // Once loaded the CAN will receive any messages with this CAN ID into
        // this message object, and an interrupt will occur.
        //
        CANMessageSet(CAN0_BASE, ObjNum, &CAN1RxMsgObject, MSG_OBJ_TYPE_RX);
    }
    
    void CANMultiRXConfig()
    {
        CAN0RXConfig(1,0x1001);
        CAN0RXConfig(2,0x1002);
        CAN0RXConfig(3,0x1003);
    
        CAN1RXConfig(1,0x2001);
        CAN1RXConfig(2,0x2002);
        CAN1RXConfig(3,0x2003);
    }
    
    void CAN0TXSend(uint8_t ObjNum,uint32_t MsgID)
    {
        CAN0TxMsgObject.ui32MsgID = MsgID;
        CAN0TxMsgObject.ui32MsgIDMask = 0;
        CAN0TxMsgObject.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
        CAN0TxMsgObject.ui32MsgLen = sizeof(CAN0_Obj1TxData);
    
        CAN0_Obj1TxData[0]++;
        CAN0TxMsgObject.pui8MsgData = CAN0_Obj1TxData;
    
        CAN0TxMsgObj4Sent=0;
        CANMessageSet(CAN0_BASE, ObjNum, &CAN0TxMsgObject, MSG_OBJ_TYPE_TX);
    }
    
    void CAN1TXSend(uint8_t ObjNum,uint32_t MsgID)
    {
        CAN1TxMsgObject.ui32MsgID = MsgID;
        CAN1TxMsgObject.ui32MsgIDMask = 0;
        CAN1TxMsgObject.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
        CAN1TxMsgObject.ui32MsgLen = sizeof(CAN1_Obj1TxData);
    
        CAN1_Obj1TxData[0]++;
        CAN1TxMsgObject.pui8MsgData = CAN1_Obj1TxData;
    
        CAN1TxMsgObj4Sent=0;
        CANMessageSet(CAN1_BASE, ObjNum, &CAN1TxMsgObject, MSG_OBJ_TYPE_TX);
    }
    
    
    void CANInitial(void)
    {
        SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0); // The GPIO port and pins have been set up for CAN.  The CAN peripheral must be enabled.
    
        CANInit(CAN0_BASE); // Initialize the CAN controller
    
        CANBitRateSet(CAN0_BASE, g_ui32SysClock, 1000000u); // Set up the 1M bit rate for the CAN bus.
    
        //HWREG(CAN0_BASE+CAN_O_CTL) |= CAN_CTL_TEST;
        //HWREG(CAN0_BASE+CAN_O_TST) |= CAN_TST_LBACK;
    
        //CANIntRegister(CAN0_BASE, CAN0IntHandler); // if using dynamic vectors
    
        CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
    
        IntEnable(INT_CAN0);// Enable the CAN interrupt on the processor (NVIC).
    
        CANEnable(CAN0_BASE);// Enable the CAN for operation.
    
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN1); // The GPIO port and pins have been set up for CAN.  The CAN peripheral must be enabled.
    
        CANInit(CAN1_BASE); // Initialize the CAN controller
    
        CANBitRateSet(CAN1_BASE, g_ui32SysClock, 1000000u); // Set up the 1M bit rate for the CAN bus.
    
        //CANIntRegister(CAN1_BASE, CAN1IntHandler); // if using dynamic vectors
    
        CANIntEnable(CAN1_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
    
        IntEnable(INT_CAN1);// Enable the CAN interrupt on the processor (NVIC).
    
        CANEnable(CAN1_BASE);// Enable the CAN for operation.
    
        CANMultiRXConfig();
    }
    

  • 询问是否有接transceiver測試也是为了再次确认一下,毕竟我并知道实际的测试情况

    若是不使用transceiver的话,可以使用loopback模式,如下文档所示:

    www.ti.com/.../spna245.pdf

    5.1 Internal Loopback With Interrupts (simple_can_loopback)

    This example is the only one of these examples that can be run on the Launchpad without a CAN transceiver or a CAN network. When in loopback mode, the CAN module is allowed to receive the message it transmits if an additional mailbox is configured to receive that message.
  • 看到您确认了答案,请问现在测试成功了?
  • spna245.pdf這裡面的範例不使用CAN transceiver的话就可以成功測試了
    謝謝協助
  • 很高兴您能测试成功。后续有其他问题,请随时发新帖,谢谢