工具/软件:
大家好:
我当前正在使用 TM4C 微控制器的 CAN 模块、在多个器件之间的通信过程中遇到了一个奇怪的问题。
CAN 总线上有16个器件。 每个器件监控来自其他器件的 CAN 消息、并根据接收到的消息的 ID 确定哪些器件处于联机状态。 例如、如果器件1、2、3和4在线、则每个器件都会通过检查接收消息的器件 ID 来计算活动节点的数量。
问题如下:
如果在保持器件1、2和4连接的同时断开器件3、器件1会继续认为器件3仍在线、即使很长时间也是如此。 为了排除器件1可能会错误地将来自器件2或4的消息解释为来自器件3的可能性、我还断开了器件2和4的连接、仅保留器件1的连接状态。
令人惊讶的是、即使只有器件1位于 CAN 总线上、它仍然会继续使用器件3的 CAN ID 来接收消息。
总线上没有来自器件3的物理 CAN 消息(通过 CAN 分析仪/监听器确认)、但器件1中的中断处理程序继续接收一条消息、其中消息的 message_ID 对应于器件3。
我怀疑这可能是由于 CAN FIFO 或消息对象缓冲区未正确清除、并且中断处理程序中仍在触发旧/过时消息。
以下是我使用的 CAN 初始化配置:
CAN Init Code
CANInit(CAN0_BASE); // Initialize the CAN controller
CANBitRateSet(CAN0_BASE, g_ui32SysClock, ui32BitRate); // Set up the bit rate for the CAN bus.
CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS); // Enable interrupts on the CAN peripheral.
IntEnable(INT_CAN0); // Enable the CAN interrupt on the processor (NVIC).
CANEnable(CAN0_BASE); // Enable the CAN for operation.
//接收初始化
sCANMessage.ui32MsgID = 0;
sCANMessage.ui32MsgIDMask = 0;
sCANMessage.ui32Flags = (MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER|MSG_OBJ_FIFO);
sCANMessage.ui32MsgLen = 8;
// MsgBox1-20 is Rx, MsgBox21-30 is TX
for(i=1;i<=(CANMaxRXObject-1);i++)
{
CANMessageSet(CAN0_BASE, i, &sCANMessage, MSG_OBJ_TYPE_RX);
}
sCANMessage.ui32Flags = (MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER);
CANMessageSet(CAN0_BASE, CANMaxRXObject, &sCANMessage, MSG_OBJ_TYPE_RX);
以下是 CAN 中断 代码:
void CAN0IntHandler(void)
{
uint32_t status;
uint8_t i = 0;
uint8_t dataBuffer[8] = {0};
tCANMsgObject receivedMsg;
// Get the interrupt status
status = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE);
// Handle controller status interrupt
if (status == CAN_INT_INTID_STATUS)
{
status = CANStatusGet(CAN0_BASE, CAN_STS_CONTROL);
}
// Check if the interrupt is from a receive message object
if (status <= MAX_RX_OBJECT)
{
for (i = 1; i <= MAX_RX_OBJECT; i++)
{
if (status == i)
{
CANIntClear(CAN0_BASE, i);
g_rxFlag = 1;
receivedMsg.pui8MsgData = dataBuffer;
CANMessageGet(CAN0_BASE, i, &receivedMsg, true);
ProcessCANMessage(receivedMsg); // User-defined message processing
}
}
}
else
{
// Clear interrupts for other message objects (e.g., transmit objects)
for (i = 9; i <= 32; i++)
{
if (status == i)
{
CANIntClear(CAN0_BASE, i);
}
}
}
}
我正在使用 CAN 初始化 FIFO 模式 使用MSG_OBJ_USE_FIFO标志将多个消息对象链接在一起。 例如、消息对象1至4设置为接收 FIFO 链。
在中断处理程序中、当我检测到已收到消息时、我调用:CANMessageGet (CAN0_BASE、Objid、&receivedMsg、TRUE);
我的问题是: CANMessageGet()使用bClrPendingInt = true接收 FIFO 中断内部进行调用是否不正确?
根据我的观察、有时 FIFO 的行为似乎异常、例如似乎多次收到相同的消息、或者缓冲区中仍然存在过时的消息 ID、即使总线上没有新数据也是如此。
我怀疑这可能是由于我使用CANMessageGet() FIFO 的方式造成的。 也许以这种方式清除中断不会正确地使 FIFO 指针前进?
是否有人遇到过类似的问题、或者您是否建议如何确保 CAN 接收缓冲区或 FIFO 被正确清除以避免这种"重影"消息行为?
希望得到任何帮助!
提前感谢!