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
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    #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;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • 询问是否有接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的话就可以成功測試了
    謝謝協助
  • 很高兴您能测试成功。后续有其他问题,请随时发新帖,谢谢