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.

[参考译文] TMS320F28377D:CANbus 可以发送但不能接收

Guru**** 2577385 points
Other Parts Discussed in Thread: C2000WARE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1025405/tms320f28377d-canbus-can-transmit-but-not-receive

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

大家好、

我一直在努力将 CAN_EXTERNAL_Transmit 示例修改为与物理2节点(2个板)系统的通信。

我使用的是 CANA、而不是 CANB。 我成功测试了单向通信、即我可以从一个节点传输数据、并在另一个节点上正确接收数据。 对于我的应用、我有一个主节点和一个从节点。 从机每次从机接收到一条消息时都需要发回一个特定的数据。 为此、我想我可以简单地构建消息、然后在由 CANbus 消息接收触发的 ISR 中使用 CANMessageSet。  

为什么这不起作用? 我的错在哪里? 这是正确的方法吗? 我附上下面的代码。 接收到之后、我基本上停用了用于在主代码中传输的代码并在 ISR 中使用了相同的函数。  

非常感谢、

Nicola

//
// Main
//
void main(void)
{
   
    InitSysCtrl();

    InitGpio();

    // additional function for setting up toggling checking pins for timing
    InitGpioPins();

    // Setup GPIO pin mux for CAN-A TX/RX and CAN-B TX/RX
    // NC modification according to board
    GPIO_SetupPinMux(36, GPIO_MUX_CPU1, 6); //GPIO36 -  CANRXA
    GPIO_SetupPinOptions(36, GPIO_INPUT, GPIO_ASYNC);
    GPIO_SetupPinMux(37, GPIO_MUX_CPU1, 6); //GPIO36 - CANTXA
    GPIO_SetupPinOptions(37, GPIO_OUTPUT, GPIO_PUSHPULL);

    // Initialize the CAN controllers
    CANInit(CANA_BASE);
    
    // Setup CAN to be clocked off the PLL output clock
    CANClkSourceSelect(CANA_BASE, 0);   // 500kHz CAN-Clock

    // set up timing 1Mbit/s 
    CANBitRateSet(CANA_BASE, 200000000, 1000000);

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

    // Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts
    DINT;

    // Initialize the PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    InitPieCtrl();

    // Disable CPU interrupts and clear all CPU interrupt flags
    IER = 0x0000;
    IFR = 0x0000;

    InitPieVectTable();

    EALLOW;
    PieVectTable.CANA0_INT = canaISR;
    EDIS;

    PieCtrlRegs.PIEIER9.bit.INTx5 = 1;
    IER |= M_INT9;
    EINT;

    CANGlobalIntEnable(CANA_BASE, CAN_GLB_INT_CANINT0);     // enable CANA

    //
    // Initialize the transmit message object used for sending CAN messages.
    // Message Object Parameters:
    //      Message Identifier: 0x5555
    //      Message ID Mask: 0x0
    //      Message Object Flags: None
    //      Message Data Length: 4 Bytes
    //      Message Transmit data: txMsgData
    //
    //sTXCANMessage.ui32MsgID = 0x5555; // deafult example message
    sTXCANMessage.ui32MsgID = 0x096;    // master to slave
    sTXCANMessage.ui32MsgIDMask = 0;
    sTXCANMessage.ui32Flags = 0;
    sTXCANMessage.ui32MsgLen = MSG_DATA_LENGTH;
    sTXCANMessage.pucMsgData = txMsgData;

    //
    // Initialize the receive message object used for receiving CAN messages.
    // Message Object Parameters:
    //      Message Identifier: 0x5555
    //      Message ID Mask: 0x0
    //      Message Object Flags: Receive Interrupt
    //      Message Data Length: 4 Bytes
    //      Message Receive data: rxMsgData
    //
    //sRXCANMessage.ui32MsgID = 0x5555; // deafult example message
    sRXCANMessage.ui32MsgID = 0x226;    // receive message from slave
    sRXCANMessage.ui32MsgIDMask = 0;
    sRXCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE;
    sRXCANMessage.ui32MsgLen = MSG_DATA_LENGTH;
    sRXCANMessage.pucMsgData = rxMsgData;

    // set received message
    CANMessageSet(CANA_BASE, RX_MSG_OBJ_ID, &sRXCANMessage, MSG_OBJ_TYPE_RX);

    // Initialize the transmit message object data buffer to be sent
    txMsgData[0] = 0x12;
    txMsgData[1] = 0x34;
    txMsgData[2] = 0x56;
    txMsgData[3] = 0x78;
    txMsgData[4] = 0x12;
    txMsgData[5] = 0x34;
    txMsgData[6] = 0x56;
    txMsgData[7] = 0x78;

    CANEnable(CANA_BASE); // Start CAN module A and B operations
   
   // DE ACTIVATED THIS PART OF CODE, THIS NODE RECEIVES THE MESSAGE AND THEN TRANSMIT ACCORDINGLY
   
#if 0

    //for(i = 0; i < TXCOUNT; i++)
    for(;;)
    {
        // Check the error flag to see if errors occurred
        if(errorFlag)
        {
            asm("   ESTOP0");
        }

        // timing the transmission of the message
        GpioDataRegs.GPBSET.bit.GPIO53 = 1; // set test point high for execution time measurement

        // verify transmission
        if(txMsgCount == rxMsgCount)
        {
            // Transmit Message
            CANMessageSet(CANA_BASE, TX_MSG_OBJ_ID, &sTXCANMessage,
                          MSG_OBJ_TYPE_TX);

            txMsgCount++;
        }
        else
        {
            errorFlag = 1;
        }

        GpioDataRegs.GPBCLEAR.bit.GPIO53 = 1;   // set point low for execution time measurements

        DELAY_US(1000 * 1000); // delay of 1 sec 

        // Increment the value in the transmitted message data

        txMsgData[0] += 0x01;
        txMsgData[1] += 0x01;
        txMsgData[2] += 0x01;
        txMsgData[3] += 0x01;

        // Reset data if exceeds a byte
        if(txMsgData[0] > 0xFF)
            txMsgData[0] = 0;  
        if(txMsgData[1] > 0xFF)
            txMsgData[1] = 0; 
        if(txMsgData[2] > 0xFF)
            txMsgData[2] = 0; 
        if(txMsgData[3] > 0xFF)
            txMsgData[3] = 0; 
    }

    asm("   ESTOP0"); // Stop application

#endif

}

//
// CAN B ISR - The interrupt service routine called when a CAN interrupt is
//             triggered on CAN module B.
// MODIFIED TO CAN A
__interrupt void
canaISR(void)
{
    uint32_t status;

    // testing time
    //GpioDataRegs.GPBSET.bit.GPIO53 = 1; // set test point high for execution time measurement

    // Read the CAN-B 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)
    {
        //
        // 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))
        {
            // Set a flag to indicate some errors may have occurred.
            errorFlag = 1;
        }
    }
    
    // Check if the cause is the CAN-B receive message object 1

    else if(status == RX_MSG_OBJ_ID)
    {
    
        // Get the received message
        CANMessageGet(CANA_BASE, RX_MSG_OBJ_ID, &sRXCANMessage, true);

        //
        // 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, 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;

        

        // MODIFICATION ---
        trigger_transmit = true;
        
        // before transmitting increment the data (as in main)
        // Increment the value in the transmitted message data.

        txMsgData[0] += 0x01;
        txMsgData[1] += 0x01;
        txMsgData[2] += 0x01;
        txMsgData[3] += 0x01;

        // Reset data if exceeds a byte

        if(txMsgData[0] > 0xFF)
            txMsgData[0] = 0;
        if(txMsgData[1] > 0xFF)
            txMsgData[1] = 0;
        if(txMsgData[2] > 0xFF)
            txMsgData[2] = 0;
        if(txMsgData[3] > 0xFF)
            txMsgData[3] = 0;

    }
    // If something unexpected caused the interrupt, this would handle it.
    else
    {
        //
        // Spurious interrupt handling can go here.
        //
    }

    // THIS SECTION GENERATES ERROR WHEN RUNNING
#if 0
    // ---------------------------------------------------------
    if (trigger_transmit == true)
    {
        CANMessageSet(CANA_BASE, TX_MSG_OBJ_ID, &sTXCANMessage,
                                              MSG_OBJ_TYPE_TX);

        txMsgCount++;
        trigger_transmit = false;
     }
     // ---------------------------------------------------------
#endif

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

    // Acknowledge this interrupt located in group 9
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;

    // GpioDataRegs.GPBCLEAR.bit.GPIO53 = 1;   // set point low for execution time measurements

}

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

    尼科拉

                 此帖子是否与此 帖子相关? 在任何情况下、我们都不能在 e2e 上支持调试代码。 Driverlib 下的 C2000ware 中提供了发送和接收示例。 请仔细查看代码的不同之处。 请不要忘记查看 www.ti.com/lit/SPRACE5中的调试提示。  

    如果帧未被接收、那么它是否首先被发送? 如果不是、您需要先对此进行调查。 如果 帧确实被发送、那么检查接收报文对象是否被正确配置为接收。 请注意 SPRACE5中的以下调试提示:

    当第一次尝试在总线上发起通信时、请确保 发送节点和接收节点中的邮箱 使用相同的 MSGID 进行编程。  请勿首先使用接受屏蔽过滤。 一旦确认 总线没有硬件问题、可以在稍后添加滤波。

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

    Hareesh、

    感谢您的回复。

    否、它与上一个帖子无关。 这个问题得到了解决。  

    在这种情况下、情况如下:我可以发送和接收、但只能以一种方式发送和接收。 这意味着我可以从节点1传输到节点2、通过 触发 ISR、使1仅发送、2仅接收。 我可以从节点2 (发送)到节点1 (接收)执行相同的操作。 当它们都需要发送和接收时、根据接收到的消息而产生问题。 例如、节点1发送包含一些信息的消息、我的应用程序需要节点2接收这些信息、并尽快将包含其他信息的消息发送回。

    为此、我在 ISR 中放置一个 MessageSet、该 ISR 在节点2中执行接收、因此在接收后、我立即将信息传输到节点1。 这会引发错误。  

    从本质上讲、无论接收到什么信息、我都无法在每个节点上执行传输和接收。 我可以执行传输或接收、但不能响应接收。 这就是为什么我想知道我的回应方法是否错误的原因。

    此致、

    Nicola  

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

    我还观察到以下情况:

    -我在两个节点中都使用 external_transmit。 传输的节点我注释掉启用 ISR 以进行 CAN 总线接收、并仅在一次传输和另一次传输之间延迟主器件传输。 接收 I 的节点执行相反的操作、不发送、而只是接收保持 ISR 设置和接收到位。  

    我甚至可以在表达式列表中观察到传输正确,接收到的数据是正确的

    -我将计数器设置为全局变量,以监视调用 ISR 的次数。 负责接收的 ISR 比接收本身更频繁地被调用。 这是我不理解的

    -当我取消注释传输节点 external_transmit 上的 ISR 初始化设置时,执行就会停止抛出错误。 这意味着尽管我只是在传输、ISR 会被触发。 我尝试强制执行以下代码  

    while(CanaRegs.CAN_IF1CMD.bit.Busy)
    {
    }
    CanaRegs.CAN_IF1MCTL.bit.TxIE = 0;

    以防止在发生传输时触发 ISR。 尽管如此、触发仍会发生。 您能否将我指向我缺少的寄存器? 或者、我通常缺少什么?

    希望这能提供一个更全面的想法,以便在有什么线索可以解决这个问题时提出建议。

    我个人不想使用 driverlib、但请坚持使用 device_support 示例、因为我的大多数应用都基于这些驱动程序。  

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

    因此、通信是双向工作的。 即1至2和2至1。 即使它只能以某种方式工作、它也表示没有硬件问题。

    [引用 userid="488465" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1025405/tms320f28377d-canbus-can-transmit-but-not-receive/3791336 #3791336">这会引发错误。  [/报价]

    什么错误?

    [引用 userid="488465" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1025405/tms320f28377d-canbus-can-transmit-but-not-receive/3791336 #3791336"]我可以执行传输或接收,但不能响应接收[/quot]

    您肯定应该能够响应接收 ISR 中的接收。

    [引用 userid="488465" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1025405/tms320f28377d-canbus-can-transmit-but-not-receive/3791715 #3791715"]ISR 处理接收的频率高于接收本身的频率。 [/报价]

    ISR 进入两次、一次用于状态更改、另一次用于实际报文对象中断。 ISR 的执行次数是否是预期的两倍?

    请查看 此帖子 、看看它是否对您有所帮助。

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

    该错误与错误标志相关、错误标志会由于我假设的错误状态而变为错误标志。 这可以通过使用 ISR 并在接收完成后使用 CANMessageSet 例程在接收成功完成后进行消息传输来实现。

    正确、正是状态的变化触发了 ISR。 我在 ISR 中看到两个入口:一个在状态变化时、一个在接收消息对象时。

    我想、对于通过使用 ISR 对接收做出响应、我的主要问题是如何不允许 ISR 被我的任何传输触发为响应。 为此、我初始化了寄存 器 CanaRegs.CAN_IF1MCTL.bit.TxIE = 0。 尽管如此、我注意到这已经在纯示例初始化中实现。 因此、我不知道如何规避该问题。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="488465" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1025405/tms320f28377d-canbus-can-transmit-but-not-receive/3792963 #3792963"]错误与错误标志相关,错误状态是我假定的。 这可以通过使用 ISR 并在接收完成后使用 CANMessageSet 例程在接收成功完成后进行消息传输来实现。[/QUERP]

    很抱歉,我不知道你在这里想说什么。

    让我们离线继续对话。