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.

[参考译文] TMS320F280025C:CANbus Tx 中断

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

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1527049/tms320f280025c-canbus-tx-interrupt

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

工具/软件:

大家好!
我在这里分享了我在处理 canbus TX 中断时遇到的一个问题。

我正在使用 F280025C Launchpad、它具有一个 CAN 总线通道 CANA 及其两个可能的中断线路 (CANINT0 和 CANINT1)。

我设置外设和中断表、以便触发:
Rx - CANINT0
TX—CANINT1

此外、关于接口寄存器、我选择使用 IF1 进行数据发送、使用 IF2 进行接收。
我同时启用了 TxIE、RxIE 位文件和 CANbus 的全局中断线路。

关于接收中断一切工作正常,当我尝试发送 CANbus 消息时,传输总是失败(我一直使用 CAN 分析仪作为其他节点)。

从字面上说、就好像什么都没有发生。

之后、我尝试从代码中排除 Rx 中断(第 0 行)并侧重于仅 Tx(第 1 行)。  

通过调试 CANbus 寄存器本身、我可以看到一个非常奇怪的事情:触发的传输线为 0(应该从设置中链接到 Rx)。
我不知道为什么。

然后、另一个非常奇怪的事情是 IPEN_21 寄存器标识了正确的消息对象、TxOk 位为高电平、LEC 1 不显示任何警告。
在这种情况下、会生成 TX 中断、但无法通过常规方式 (IntClrPnd = 1) 清除它。 实际上、TX 中断是  永无休止地进入的。

为什么就在我 排除 Rx 时触发 Tx 中断?
有人能帮我解决这个问题吗?


我附加了一些我一直在写的代码、希望它有助于捕捉问题。
请告诉我:)

Elia

=======================================
PIE SETUP

=======================================

EALLOW;

PieVectTable.CANA0_INT =&cana_rx_ISR;
PieVectTable.CANA1_INT =&cana_TX_ISR;

PieCtrlRegs.PIEIER9.bit.INTx6 = 1;  
PieCtrlRegs.PIEIER9.bit.INTx5 = 1;
//PieCtrlRegs.PIEIER9.bit.INTx6 = 1;

IER |= M_INT9;  
EDIS;




=======================================
初始化

=======================================

void InitCAN (void)

int16_t iMsg;

//
//将 CAN 控制器置于初始化状态、无论先前的状态如何。 减少
//将使控制器处于空闲状态、并允许消息对象 RAM 处于空闲状态
//已编程。
//
CanaRegs.can_CTL.bit.Init = 1;
CanaRegs.CAN_CTL.bit.CCE = 1;
CanarRegs.can_CTL.bit.SWR = 1;//软件复位 (si attiva solo se Init è settato)

//
//等待 BUSY 位清除
//
while (canRegs.can_IF1CMD.bit.busy)// c'μ s un trasferrimento in corso tra è 寄存器 e la ram

}

//
//清除仲裁寄存器中的消息值位。 这一指示
//消息无效、是离开消息的“安全“条件
//对象。 同一 ARB reg 用于对所有消息对象进行编程。
//

CanaRegs.can_IF1CMD.bit.DIR = 1;// 0 读、1 写:0 legge dalla 邮箱 verso l'interface 寄存器、反之亦然
CanaRegs.can_IF1CMD.bit.arb = 1;//仲裁位(标识符+ Dir + XTD + MsgVal)传输位 if -> Mailbox (se write、反之亦然、se read)
CanaRegs.can_IF1CMD.bit.Control = 1;//控制位出现 sopra

CanaRegs.can_IF1ARB.all = 0;

CanaRegs.can_IF1MCTL.all = 0;

CanaRegs.CAN_IF2CMD.bit.DIR = 1;
CanaRegs.can_IF2CMD.bit.arb = 1;
CanaRegs.CAN_IF2CMD.bit.Control = 1;

CanaRegs.can_IF2ARB.all = 0;

CanaRegs.can_IF2MCTL.all = 0;

//
//循环以对所有 32 个消息对象进行编程
//
For (iMsg = 1;iMsg <= 32;iMsg +=2)

//
//等待 BUSY 位清除
//
while (CanaRegs.can_IF1CMD.bit.busy)

}

//
//启动消息对象编程
//
CanaRegs.CAN_IF1CMD.bit.MSG_NUM = iMsg;

//
//等待 BUSY 位清除
//
while (CanaRegs.can_IF2CMD.bit.busy)

}

//
//启动消息对象编程
//
CanaRegs.CAN_IF2CMD.bit.MSG_NUM = iMsg + 1;
}

CanaRegs.CAN_IF1CMD.bit.DATA_A = 1;
CanaRegs.CAN_IF1CMD.bit.DATA_B = 1;

CanaRegs.CAN_IF2CMD.bit.DATA_A = 1;
CanaRegs.CAN_IF2CMD.bit.DATA_B = 1;

//
//确认任何挂起的状态中断。
//
易失性 uint32_t 丢弃读取= CanaRegs.CAN_ES.all;//错误和状态寄存器


}

=======================================
CAN ENABLE

=======================================

Void CAN_Enable (void){

//
//启用 CAN 以运行。
//
CanaRegs.can_CTL.bit.DAR = 1;//禁用自动重新传输

CanaRegs.can_CTL.bit.Test = 0;//启用测试模式并选择外部环回
CanaRegs.can_test.bit.exl = 0;//外部环回

CanarRegs.can_CTL.bit.IE0 = 1;// Abilito 中断
CanaRegs.CAN_GLB_INT_EN.bit.GLBINT0_EN = 1;

CanaRegs.can_CTL.bit.IE1 = 1;
CanaRegs.can_GLB_INT_EN.bit.GLBINT1_EN = 1;

Canares.can_CTL.bit.Init = 0;//启用 CAN 以进行操作 (0 个处理 i messaggi normalmente)


}

=======================================
Tx 邮箱设置

=======================================

void can_objid (uint32_t Mailbox_Setup_、uint32_t msgid、uint16_t DLC)

//
//为 IF1CMD 使用 Shadow 变量。 IF1CMD 应写入中
//单个 32 位写入。
//
UNION CAN_IF1CMD_REG CAN_IF1CMD_SHADOW;

//
//等待 BUSY 位清除。
//
while (CanaRegs.can_IF1CMD.bit.busy)

}

//
//清除和写入寄存器以对消息对象进行编程。
//
CAN_IF1CMD_SHADOL.ALL = 0;
CanaRegs.can_IF1Msk.all = 0;
CanaRegs.can_IF1ARB.all = 0;
CanaRegs.can_IF1MCTL.all = 0;

//
//设置控制位、遮罩位和 ARB 位、以便将其传输到
//消息对象。
//
CAN_IF1CMD_Shadow.bit.Control = 1;
CAN_IF1CMD_SHADOL.BIT.ARB = 1;
CAN_IF1CMD_Shadow.bit.Mask = 1;
CAN_IF1CMD_Shadow.bit.DIR = 1;

CanaRegs.can_IF1ARB.bit.Dir = 1;// se non lo forzo ad 1 manda un messaggio vuoto(远程帧 RTR)
CanaRegs.CAN_IF1MCTL.bit.TxIE = 1;
//
//设置消息 ID(本示例假设 ID 掩码为 11 位)
//
CanaRegs.CAN_IF1ARB.bit.ID =(msgid << CAN_MSG_ID_SHIFT);
CanaRegs.can_IF1ARB.bit.MsgVal = 1;

//
//为所有传输设置数据长度。 这是
//也是单次传输而不是 FIFO 传输、因此设置 EOB 位。
//
CanaRegs.can_IF1MCTL.bit.DLC = DLC;
CanaRegs.can_IF1MCTL.bit.EOB = 1;

//
//将数据传输到消息对象 RAM
//
CAN_IF1CMD_SHADOL.BIT.MSG_NUM = Objid;
CanaRegs.CAN_IF1CMD.ALL = CAN_IF1CMD_SHADOL.ALL;
}

=======================================
Tx 中断处理

=======================================

// devo riuscire a farlo funzionare!
__ interrupt void cana_TX_ISR (void){

dbg.can_tx++;
#if 0
while(!CanaRegs.can_es.bit.TxOk){
}
#endif

#if 0
if(!CanaRegs.can_es.bit.TxOk){
CanaRegs.can_es.bit.TxOk = 0;
GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;
Comando_feeder = 0;
}
#endif

if ((CanaRegs.CAN_IPEN_21 &&(1 <<(CAN_TX_LOCK-1)))&&(CanaRegs.CAN_INT.bit.INT1ID == CAN_TX_LOCK)){
GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;

CanaRegs.CAN_IF1CMD.bit.ClrIntPnd = 1;
}


//volatile uint32_t status = CanaRegs.CAN_ES.all;//错误和状态寄存器
CanaRegs.CAN_GLB_INT_CLR.bit.IN1_FLG_CLR = 1;
PieCtrlRegs.PIEACK.bit.ACK9 = 1;

}







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

    您好 Elia、

    下次在帖子中插入代码时、请使用选项“插入-> 回复时工具栏下方的代码“。  这使帖子更加有序、并保持内容和代码部分之间的边界、更易于阅读、还可以在代码中进行 LINE#引用。

    当使用两条 CAN 中断线路时、必须配置寄存器 CAN_IP_MUX21 以将邮箱(总共 32 个)映射到相应的中断线路。  我在您的代码中看不到 CAN_IP_MUX21 配置。

    此致、

    Joseph

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

    您好、Joseph:
    很抱歉代码部分、下次我将按照您的说明操作、我很感激!
    感谢您的中断建议、我完全丢失了该寄存器。
    只要我回到我的项目,我会给你更新,但我希望这一个解决了它。

    我保持门打开、因为还碰巧没有设置 触发 TX 中断的时间 IntPnd 标志。

    但无论如何,你的暗示是珍贵的!
    周末愉快

    Elia

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

    您好、Joseph:
    现在我可以正确触发 TX 中断。 我之前提到的问题仍然存在。

    TX 中断被触发、然后必须将其清除才能继续。
    深入了解调试步骤。 问题是:
    - CAN_IF1_MCTL 中的 IntPen 寄存器没有转到 1。 因此、此命令 CanaRegs.can_IF1CMD.bit.ClrIntPnd = 1;无效

    - CanarRegs.CAN_GLB_INT_CLR.bit.IN1_FLG_CLR = 1;不会将此类寄存器设为 1(从调试中看到)

    基本上、我无法清除中断、因此我永久留在例程内、没有任何退出的机会。

    你有这方面的线索吗?
    这次我将 ISR 代码附加在正确的部分。

    __interrupt void cana_tx_isr(void){
    
        dbg.can_tx++;
    
    
        if((CanaRegs.CAN_IPEN_21 && (1 << (CAN_TX_LOCK-1))) && (CanaRegs.CAN_INT.bit.INT1ID == CAN_TX_LOCK)){
            GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;
    
            CanaRegs.CAN_IF1CMD.bit.ClrIntPnd = 1;
        }
    
        CanaRegs.CAN_IF1CMD.bit.ClrIntPnd = 1;
    
        CanaRegs.CAN_GLB_INT_CLR.bit.INT1_FLG_CLR = 1;
        PieCtrlRegs.PIEACK.bit.ACK9 = 1;
    
    }


    再见
    Elia  

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

    您好 Elia、

    我强烈建议您查看 C2000Ware 中的可用示例。  您采用的编码样式是我们所称的位字段类型、您可以在其中将位值直接分配给位字段。  我们的 C2000Ware 代码使用 driverlib 编码、这是一种更高效的编码方法、因为它还涉及若干检查以确保写入的位置和值有效。

    对于 CAN、 有几个接收和发送示例 说明了如何正确处理 ISR 并清除中断。  例如,下面的代码片段是如何使用 can_clearInterruptStatus () API 处理和清除 CAN 中断:

    //*****************************************************************************
    //
    // CAN_clearInterruptStatus
    //
    //*****************************************************************************
    void
    CAN_clearInterruptStatus(uint32_t base, uint32_t intClr)
    {
        //
        // Check the arguments.
        //
        ASSERT(CAN_isBaseValid(base));
        ASSERT((intClr == CAN_INT_INT0ID_STATUS) ||
               ((intClr >= 1U) && (intClr <= 32U)));
    
        if(intClr == (uint32_t)CAN_INT_INT0ID_STATUS)
        {
            //
            // Simply read and discard the status to clear the interrupt.
            //
            HWREGH(base + CAN_O_ES);
        }
        else
        {
            //
            // Wait to be sure that this interface is not busy.
            //
            while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) ==
                  CAN_IF1CMD_BUSY)
            {
            }
    
            //
            // Only change the interrupt pending state by setting only the
            // CAN_IF1CMD_CLRINTPND bit.
            //
            // Send the clear pending interrupt command to the CAN controller.
            //
            HWREG_BP(base + CAN_O_IF1CMD) = ((uint32_t)CAN_IF1CMD_CLRINTPND |
                                            (intClr & CAN_IF1CMD_MSG_NUM_M));
    
            //
            // Wait to be sure that this interface is not busy.
            //
            while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) ==
                  CAN_IF1CMD_BUSY)
            {
            }
        }
    }
    

    请注意、在清除中断之前、会通过 CAN 进行检查以检查 IF1CMD 是否处于繁忙状态。

    此致、

    Joseph