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.

[参考译文] TMS320F28379D:发送/接收数据时、出现错误期间的 CAN 总线操作

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1231126/tms320f28379d-can-bus-action-during-error-when-transmitting-receive-data

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

您好 

我目前正在查看 driverlib 示例代码 can_ex3_external_transmit (\C2000Ware_4_01_00_00\driverlib\f2837xd\examples\cpu1\can)

其中 CAN-A 用于传输数据、CAN-B 用于接收数据

这就是 ISR 函数

//
// CAN B ISR - The interrupt service routine is called when an interrupt is
//             triggered on CAN module B. It will be executed twice for every
//             frame received.
//             First time for status-change; second time for Mailbox receive.
//
__interrupt void
canbISR(void)
{
    uint32_t status;

    //
    // Read the CAN-B interrupt status (in the CAN_INT register) to find the
    // cause of the interrupt
    //
    status = CAN_getInterruptCause(CANB_BASE);

    //
    // If the cause is a controller status interrupt, then get the status.
    // During first iteration of every ISR execution, status = 0x8000,
    // which simply means CAN_ES != 0x07.
    //
    if(status == CAN_INT_INT0ID_STATUS)
    {
        //
        // 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 = CAN_getStatus(CANB_BASE);  // Return CAN_ES value.
        //
		// Now status = 0x00000010, indicating RxOK.
        //

        //
        // Check to see if an error occurred.
        //
        if(((status  & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_MSK) &&
           ((status  & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_NONE))
        {
            //
            // Set a flag to indicate some errors may have occurred.
            //
            errorFlag = 1;
        }
    }
    //
    // Check if the cause is the CAN-B receive message object 1. Will be skipped
    // in the first iteration of every ISR execution
	//
    else if(status == RX_MSG_OBJ_ID)
    {
        //
        // Get the received message
        //
        CAN_readMessage(CANB_BASE, RX_MSG_OBJ_ID, rxMsgData);

        //
        // 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.
        //
        CAN_clearInterruptStatus(CANB_BASE, RX_MSG_OBJ_ID);

        //
        // 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;
    }
    //
    // If something unexpected caused the interrupt, this would handle it.
    //
    else
    {
        //
        // Spurious interrupt handling can go here.
        //
    }

    //
    // Clear the global interrupt flag for the CAN interrupt line
    //
    CAN_clearGlobalInterruptStatus(CANB_BASE, CAN_GLOBAL_INT_CANINT0);

    //
    // Acknowledge this interrupt located in group 9
    //
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}

基于上述,我 为我的应用程序创建了这个 ISR 框架,我们在其中检查是否接收到任何帧,传输或是否有任何错误。

#define CTRL_BRD_CAN                        CANA_BASE
#define CTRL_BRD_CAN_INT                    INT_CANA0
#define CTRL_BRD_CAN_TX_MSG_OBJ_ID_1        1
#define CTRL_BRD_CAN_TX_MSG_OBJ_ID_1_LEN    1
#define CTRL_BRD_CAN_RX_MSG_OBJ_ID_1        1
#define CTRL_BRD_CAN_RX_MSG_OBJ_ID_1_LEN    2
#define CTRL_BRD_CAN_MSG_ID                 0x01

__interrupt void INT_CAN_CTRL_ISR(void)
{
    uint32_t status;
    //
    // Read the interrupt cause
    //
    status = CAN_getInterruptCause(CTRL_BRD_CAN);
    if (status == CAN_INT_INT0ID_STATUS)
    {
        status = CAN_getStatus(CTRL_BRD_CAN);  // Return CAN_ES value.
        //
        // Check to see if an error occurred.
        //
        if (((status & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_MSK)
                && ((status & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_NONE))
        {
            //
            // Set a flag to indicate some errors may have occurred.
            //
            //errorFlag = 1;
            // 
            // TODO: Do error handling in here
            ;
        }
    }
    //
    // Check if the cause is the CAN receive message object 1. Will be skipped
    // in the first iteration of every ISR execution
    //
    else if(status == CTRL_BRD_CAN_RX_MSG_OBJ_ID_1)
    {
        //TODO: Do something
        //
        //Clear the RX message object interrupt.
        //
        CAN_clearInterruptStatus(CTRL_BRD_CAN, CTRL_BRD_CAN_RX_MSG_OBJ_ID_1);
    }
    //
    // Check if the cause is the transmit message object 1
    //
    else if (status == CTRL_BRD_CAN_TX_MSG_OBJ_ID_1)
    {
        //TODO: Do something
        //
        //Clear the TX message object interrupt.
        //
        CAN_clearInterruptStatus(CTRL_BRD_CAN, CTRL_BRD_CAN_TX_MSG_OBJ_ID_1);
    }
    //
    // Clear the global interrupt flag for the CAN interrupt line
    //
    CAN_clearGlobalInterruptStatus(CTRL_BRD_CAN, CAN_GLOBAL_INT_CANINT0);

    //
    // Acknowledge this interrupt located in group 9
    //
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}

我的问题是,如果发生错误(从 CAN_ES 读取),

  1. CAN 总线是自动再次重新传输数据、还是我们必须手动重新传输数据? 这与 CAN_enableRetry ()函数有什么关系吗?
  2. 如果发生错误、您能建议我们采取任何纠正措施、以便将总线恢复到无错误状态吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    CAN 总线是否会自动再次重新传输数据,还是必须手动传输数据? 这与 can_enableRetry ()函数有什么关系吗?

    在传输过程中、如果总线上的任何节点检测到错误、则会通过发送错误帧来破坏正在进行的传输。 该错误帧故意违反了位填充规则。 总线上的其他节点要么亲自检测原始错误、要么检测由检测错误的节点发送的错误帧、然后再传输自己的错误帧。 您在总线上看到的是总线上每个节点传输的错误帧的叠加。 现在、您的问题是、当正在进行的帧的传输由于错误而被破坏时、传输节点将自动重新传输该帧。 这种情况无需任何代码干预。 这是 CAN 协议要求。

    发生错误时,您能建议我们采取任何纠正措施以使总线恢复到无错误状态吗?

    在正确设计/配置的网络中、很少出现通信错误。 常见错误的原因是

    1. 振荡器容差宽松
    2. 采样点选择不正确
    3. 节点之间的比特率不匹配。 这种情况可能是由于振荡器容差的松散造成的
    4. 电气噪声。 如果该噪声是瞬态的、那么一旦干扰消失、总线就应自行恢复。 这就是该协议的设计方式。  

    总线关闭是一个严重的错误情况。 应该在通信期间调查错误(导致总线关闭)的根本原因。

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

    谢谢你这么详细的答复,如果我们有任何进一步的问题,会告诉你