TI中文支持网
TI专业的中文技术问题搜集分享网站

TM4C1294 CAN

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

Susan Yang:

您可以尝试使用下面的代码

e2e.ti.com/…/1280698

,

user6438409:

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,0×1001);CAN0RXConfig(2,0×1002);CAN0RXConfig(3,0×1003);
CAN1RXConfig(1,0×2001);CAN1RXConfig(2,0×2002);CAN1RXConfig(3,0×2003);
}

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 functionCAN0TXSend(4,0×2001);CAN1TXSend(4,0×1001);

,

Susan Yang:

请您之后使用高级编辑器的工具来上传代码

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

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

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

,

user6438409:

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 controllerCANBitRateSet(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 vectorsCANIntEnable(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 controllerCANBitRateSet(CAN1_BASE, g_ui32SysClock, 1000000u); // Set up the 1M bit rate for the CAN bus.//CANIntRegister(CAN1_BASE, CAN1IntHandler); // if using dynamic vectorsCANIntEnable(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();
}

,

Susan Yang:

询问是否有接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.

,

Susan Yang:

看到您确认了答案,请问现在测试成功了?

,

user6438409:

spna245.pdf這裡面的範例不使用CAN transceiver的话就可以成功測試了
謝謝協助

,

Susan Yang:

很高兴您能测试成功。后续有其他问题,请随时发新帖,谢谢

赞(0)
未经允许不得转载:TI中文支持网 » TM4C1294 CAN
分享到: 更多 (0)