我建一个CAN的环形缓冲,每个周期将要发送的CAN报文写到环形缓冲区里,然后调用SendCanTxBufInt()触发中断发送,在报文发送完后触发中断,在中断canStatusChangeNotification()中发送下一个报文,发送邮箱只用一个。
static uint32_t TransmitCanFrame(canBASE_t *CanX, uint32_t nMessageBox, const CanTRMsg * const TxMsg) { uint32_t success = 0U; if(canIsTxMessagePending(CanX, nMessageBox) != 0U) /* 邮箱忙状态 */ { return 0U; } canUpdateID(CanX, nMessageBox, TxMsg->MsgId | (uint32_t)0x40000000U | (uint32_t)0x20000000U); success = canTransmit(CanX, nMessageBox, TxMsg->Data); return success; } /* 中断程序 */ void canStatusChangeNotification(canBASE_t *node, uint32 notification) { uint32_t success = 0U; /* 发送状态标志 */ SetCan_MsgBuf *TxBuf = &g_Can1TxBuf; CanTRMsg *TxMsg = NULL; if((uint8)notification & canLEVEL_TxOK) /* 发送完成 */ { if(TxBuf->Cnt != 0U) { TxMsg = &TxBuf->Buf[TxBuf->Head]; success = TransmitCanFrame(node , canMESSAGE_BOX1, TxMsg); /* 报文发送 */ if(1U == success) { TxBuf->Head = (TxBuf->Head + 1U) % CAN_BUF_SIZE; /* 写缓冲头 */ TxBuf->Cnt--; } } else { canDisableStatusChangeNotification(node); } } } /* 中断触发发送 */ void SendCanTxBufInt(canBASE_t *CanX, uint32_t nMessageBox) { uint32_t success = 0U; /* 发送状态标志 */ SetCan_MsgBuf *TxBuf = &g_Can1TxBuf; CanTRMsg *TxMsg = NULL; if(TxBuf->Cnt != 0U) { TxMsg = &TxBuf->Buf[TxBuf->Head]; if(TxMsg == NULL) { return; } canEnableStatusChangeNotification(CanX); /* 使能中断 */ success = TransmitCanFrame(CanX , nMessageBox, TxMsg); /* 报文发送 */ if(1U == success) { TxBuf->Head = (TxBuf->Head + 1U) % CAN_BUF_SIZE; TxBuf->Cnt--; } } }
现在情况是,我一个周期发送多个报文,假设顺序是报文1->报文2->报文3->报文4,发送有时总线上收到的报文数据是报文2的ID和报文1的数据,ID和数据发生错位。我在刷新ID时专门判断了邮箱是否为空,防止ID刷新数据刷新失败(我是中断触发,发送成功触发中断,邮箱理论上是空的),但是该现象偶尔还会出现,我这个用法伤和程序上有没有问题?官方有没有相关的例程或者源码可以参考的?我在论坛上看了其它相关的问题,例如https://e2echina.ti.com/support/microcontrollers/hercules/f/hercules-safety-microcontrollers-forum/194236/tms570-can-id/600776的TMS570 动态CAN发送 ID 和 数据 发生错位现象,他的用法上跟我有点区别,其内部有一个回复指向英文论坛的帖子,但是打开是该帖子不存在,目前我现在只能在协议上想办法。
期待你们的回复~~ ^__^