工具/软件:
大家好:
我当前正在使用 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 被正确清除以避免这种"重影"消息行为?
希望得到任何帮助!
提前感谢!