我建一个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 和 数据 发生错位现象,他的用法上跟我有点区别,其内部有一个回复指向英文论坛的帖子,但是打开是该帖子不存在,目前我现在只能在协议上想办法。
期待你们的回复~~ ^__^