This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F28377S:CAN 从器件无法接收指定的 ID 数据

Guru**** 1168930 points
Other Parts Discussed in Thread: C2000WARE
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1288845/tms320f28377s-can-slave-cannot-receive-the-specified-id-data

器件型号:TMS320F28377S
主题中讨论的其他器件:C2000WARE

主设备和从属设备:F28377S

波特率: 500kHz

主器件每1ms 向从器件发送一帧数据、长度为5字节。

从机使用中断 方式从主机处接收数据。  起初、从器件正常接收。 经过一段时间后、从机无法从主机接收数据(仅指定的 ID)。 时间间隔不是固定的、从器件有时会正常工作很长时间。

主器件和从器件之间的连接正常。

发生错误后、使用 CAN 工具将其他帧 ID 的数据发送到从机、从机可以正常接收。

它还可以检测主器件使用这个指定的帧 ID 发送的数据是否输出。

使用 CAN 工具发送具有这个指定 ID 的数据、而从器件无法接收该 ID。

// ====================================================================
// === 1. 主函数初始化部分 ============================================
// ====================================================================
void main(void)
{
    //
    // Initialize the CAN controllers
    //
    CANInit(CANA_BASE);

    //
    // Setup CAN to be clocked off the PLL output clock
    //
    CANClkSourceSelect(CANA_BASE, 0);

    //
    // Set up the CAN bus bit rate to 500kHz for each module
    // This function sets up the CAN bus timing for a nominal configuration.
    // You can achieve more control over the CAN bus timing by using the
    // function CANBitTimingSet() instead of this one, if needed.
    // Additionally, consult the device data sheet for more information about
    // the CAN module clocking.
    //
    CANBitRateSet(CANA_BASE, 200000000, 500000);
//    CANBitRateSet(CANA_BASE, 200000000, 1000000);

    //
    // Enable interrupts on the CAN A peripheral.
    //
//    CANIntEnable(CANA_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
    CANIntEnable(CANA_BASE, CAN_INT_MASTER | CAN_INT_ERROR);

    // Enable AutoBusOn
    CAN_enableAutoBusOn(CANA_BASE);
    CAN_setAutoBusOnTime(CANA_BASE, 100000);
    CAN_disableRetry(CANA_BASE);
    //
    // Enable the CAN-A interrupt signal
    //
    CANGlobalIntEnable(CANA_BASE, CAN_GLB_INT_CANINT0);

    CanObjInit();

    //
    // Start CAN module A operations
    //
    CANEnable(CANA_BASE);
}

// ====================================================================
// === 2. 主机DSP CanObjInit()初始化配置邮箱,及发送程序  =============
// ====================================================================
void CanObjInit()
{
    // 两DSP CAN通信,发送
    sTXCANMsgDspComm01.ui32MsgID = 0x0C100201;
    sTXCANMsgDspComm01.ui32MsgIDMask = 0;
    sTXCANMsgDspComm01.ui32Flags = 0;
    sTXCANMsgDspComm01.ui32MsgLen = 5;
    sTXCANMsgDspComm01.pucMsgData = TxMsgDspCommData01;
}


// ====== 发送部分程序,1ms发送1次 =====================================
    // 发送给从机电流设定值
    TxMsgDspCommData01[0] = ((int)(onGridCloseLoopIdref * 100) & 0x00FF);
    TxMsgDspCommData01[1] = ((int)(onGridCloseLoopIdref * 100) & 0xFF00) >> 8;
    TxMsgDspCommData01[2] = ((int)(onGridCloseLoopIqref * 100) & 0x00FF);
    TxMsgDspCommData01[3] = ((int)(onGridCloseLoopIqref * 100) & 0xFF00) >> 8;
    TxMsgDspCommData01[4] = 0;
    CANMessageSet(CANA_BASE, 4, &sTXCANMsgDspComm01, MSG_OBJ_TYPE_TX);

// ====================================================================
// === 3. 从机DSP CanObjInit()初始化配置邮箱,及接收程序  =============
// ====================================================================
void CanObjInit()
{
    // 两DSP CAN通信,接收
    sRXCANMsgDspComm01.ui32MsgID = 0x0C100201;
    sRXCANMsgDspComm01.ui32MsgIDMask = 0;
    sRXCANMsgDspComm01.ui32Flags = MSG_OBJ_RX_INT_ENABLE;
    sRXCANMsgDspComm01.ui32MsgLen = 5;
    sRXCANMsgDspComm01.pucMsgData = RxMsgDspCommData01;
    CANMessageSet(CANA_BASE, 15, &sRXCANMsgDspComm01, MSG_OBJ_TYPE_RX);
}

// ======== 在中断中接收主机发送过来的数据(status = 15时接收该帧  ) ============================
#if (G9_5PL != 0)
__interrupt void CANA0_ISR(void)    // CAN-A
{
    // Set interrupt priority:
    volatile Uint16 TempPIEIER = PieCtrlRegs.PIEIER9.all;
    IER |= M_INT9;
    IER    &= MINT9;                         // Set "global" priority
    PieCtrlRegs.PIEIER9.all &= MG9_5;   // Set "group"  priority
    PieCtrlRegs.PIEACK.all = 0xFFFF;   // Enable PIE interrupts
    __asm("  NOP");
    EINT;

    uint32_t status;

    //
    // Read the CAN-A interrupt status to find the cause of the interrupt
    //
    status = CANIntStatus(CANA_BASE, CAN_INT_STS_CAUSE);

    //
    // If the cause is a controller status interrupt, then get the status
    //
    if(status == CAN_INT_INT0ID_STATUS)
    {
//        DSP_OUT1_TOGGLE;

        //
        // 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.
        //
        status = CANStatusGet(CANA_BASE, CAN_STS_CONTROL);

        //
        // Check to see if an error occurred.
        //
//        if(((status  & ~(CAN_ES_RXOK)) != 7) &&
//           ((status  & ~(CAN_ES_RXOK)) != 0))
//        if(((status  & ~(CAN_ES_RXOK | CAN_ES_TXOK | CAN_ES_BOFF)) != 7) &&
//           ((status  & ~(CAN_ES_RXOK | CAN_ES_TXOK | CAN_ES_BOFF)) != 0))
        if(((status  & ~(CAN_ES_RXOK | CAN_ES_TXOK)) != 7) &&
           ((status  & ~(CAN_ES_RXOK | CAN_ES_TXOK)) != 0))
        {
            //
            // Set a flag to indicate some errors may have occurred.
            //
            errorFlag = 1;   // 调试
            CanConfigInit();
//            DSP_OUT1_TOGGLE;   // 调试
        }
    }
    else if(status == 15)
    {
        DSP_OUT1_TOGGLE;

        errorFlag = 0;
        CanReceiveDsp01();

        CANIntClear(CANA_BASE, 15);
    }
    else if(status == 16)
    {
        CanReceiveDsp02();

        CANIntClear(CANA_BASE, 16);
    }
    else if(status == 17)
    {
//        DSP_OUT1_TOGGLE;   // 调试

        CanReceiveDsp03();

        CANIntClear(CANA_BASE, 17);
    }
    //
    // Check if the cause is the CAN-A receive message object 1
    //
    else if(status == 25)
    {
        //
        // Get the received message
        //
//        CANMessageGet(CANA_BASE, 2, &sRXCANMsgChkInfo, true);

        CanReceiveSrhInfo();

        //
        // Getting to this point means that the RX interrupt occurred on
        // message object 1, and the message RX is complete.  Clear the
        // message object interrupt.
        //
        CANIntClear(CANA_BASE, 25);

        //
        // Increment a counter to keep track of how many messages have been
        // received. In a real application this could be used to set flags to
        // indicate when a message is received.
        //
//        rxMsgCount++;

        //
        // Since the message was received, clear any error flags.
        //
//        errorFlag = 0;
    }
    else if(status == 26)
    {
        CanReceiveRdSet();

        CANIntClear(CANA_BASE, 26);
    }
    else if(status == 27)
    {
        CanReceiveCtlSet();

        CANIntClear(CANA_BASE, 27);
    }
    else if(status == 28)
    {
        CanReceiveParaSet();

        CANIntClear(CANA_BASE, 28);
    }

    //
    // If something unexpected caused the interrupt, this would handle it.
    //
    else
    {
        //
        // Spurious interrupt handling can go here.
        //
//        errorFlag = 2;   // 调试
    }

    //
    // Clear the global interrupt flag for the CAN interrupt line
    //
    CANGlobalIntClear(CANA_BASE, CAN_GLB_INT_CANINT0);


    //
    // Restore registers saved:
    //
    DINT;
    PieCtrlRegs.PIEIER9.all = TempPIEIER;
}
#endif

--

谢谢、此致

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    耶鲁大学

               由于它在一段时间内可以正常工作、因此我们不能怀疑中断初始化或配置是否正确。 浏览代码、似乎没有使用接受屏蔽过滤。 如果为 true、则针对总线上传输的每一条报文配置单独的报文对象。 可能会发生的情况是、中断未得到及时处理、从而导致消息丢失。 如果未使用屏蔽并且消息对象保留了正确的 MSGID (ARBID)、它 将会 接收一条传输的消息。 它无法突然停止接收消息。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Hareesh。

    可能发生的情况是中断未被及时处理,从而导致消息丢失。

    什么原因会导致中断程序无法及时得到服务?

    如果未使用屏蔽且消息对象保留了正确的 MSGID (ARBID),IT 将会 接收一条传输的消息。 它不能突然停止接收消息。

    程序中的掩码未使用、MSGID (ARBID)未更改。

    如何进一步找出问题?

    --

    谢谢、此致

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    什么原因会导致中断程序无法及时处理?

    如果应用程序"忙"做其他事情、它可能无法及时为中断提供服务、从而导致消息丢失。 请让客户检查 MsgLst (接收消息丢失)位是否存在可疑的消息对象。 如果某条消息确实被改写(因为没有被软件及时读取)、该位将被置位。  

    如何进一步查找问题?

    如前所述、这不是硬件问题。 应用能够配置更多的接收报文对象、或者以其它方式确保 CAN 中断能够及时提供服务。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    如果消息确实被改写(因为软件没有及时读取),则将设置此位。

    在报文被重写丢失后、出错报文对象是否永远不会接收数据?

    应用程序可以配置更多消息对象以进行接收或以其他方式确保 CAN 中断可以及时得到处理。

    是否可以使用两个不同的消息对象来接收同一 ID 的数据?

    --

    谢谢、此致

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    重新写入消息并丢失后,出错的消息对象是否永远不会接收数据?

    不可以、消息在被读取前被覆盖这一事实不应阻止该消息目标接收未来的消息。

    我可以使用两个不同的消息对象来接收同一 ID 的数据吗?

    接收 FIFO 中的数据包。 否则、数字上最少的消息对象将会一遍又一遍地被覆盖。 对此进行了说明。  

    8.2基本接收过程 www.ti.com/lit/SPRAD59的第21页。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我的客户现在面临的问题是消息对象不再接收消息。 他们是否能够通过将该问题配置为 FIFO 接收模式来解决该问题?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    他们能否通过将其配置为 FIFO 接收模式来解决此问题?

    否、客户应找出问题的根源并了解为何未收到消息。 仅仅配置 FIFO 并不能魔术般地解决这个问题。 报文对象接收的底层机制并没有什么变化、仅仅是因为它现在是 FIFO 的一部分。 如前所述、Message 对象无法突然停止接收消息。 要么是预期的消息根本没有传输。 或者如果它已发送、接收报文对象的配置也会以某种方式发生改变。 客户需要仔细检查接收报文对象的配置。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    请客户检查 MsgLst (Receive Message Lost)位以找到可疑的消息对象。 如果某个消息确实被改写(因为软件没有及时读取)、则该位将被置位。

    他们按照下面的方法检查 MsgLst 位、发现当从器件不能接收来自主器件的数据时、从器件错误报文对象的 MsgLst 位没有被置位。

    if( (sRXCANMsgDspComm05.ui32Flags & MSG_OBJ_DATA_LOST) == 1)
    {
    systemFault.bit.DebugFault = 1;    // Send to the upper computer for observation
    }

    他们还可以执行哪些其他调试操作?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    耶鲁大学

               客户可以禁用其系统中的所有中断、CAN 中断除外。 如果问题消失、它肯定是一种中断处理不够快的情况。  

    客户还可以尝试使用最新 C2000ware 中的 Driverlib。  

    如前所述、这是代码问题。 在不访问 H/W 或 S/W 的情况下、很难远程调试这样的问题。 遗憾的是,我不能就此再进一步。