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.

2812 eCAN 中断接收远程帧,跑了45分钟后,仿真器发现不能进接收中断,收不到上位机发的远程帧了。

代码附上。

#include "DSP281x_Device.h"
#include "app.h"
#include "Debuger.h"
#include "CanToUart.h"

extern void eCanSend(Uint16 x1,Uint16 x2,Uint16 x3,Uint16 x4);

//eCanFIFO
unsigned short eCanReadDataBuffer[eCanReadBufferSize];//接收数据缓冲区
unsigned short eCanWriteDataBuffer[eCanWriteBufferSize];//接收数据缓冲区

unsigned char eCanBufferFlag = 0;//eCanBUFFER标志软寄存器
//bit0: 0, eCan数据应填充至eCanReadDataBuffer1中
// 1, eCan数据应填充至eCanReadDataBuffer2中
//bit1: 0, Buffer1 no overflow
// 1, Buffer1 overflow
//bit2: 0, Buffer2 no overflow
// 1, Buffer2 overflow
struct ECAN_REGS ECanaShadow;
volatile struct CAN_REC_FRAME CAN_REC_frame;
Uint16 CAN_CMD = 0;//CAN总线收到的命令代码

extern Uint32 WatchDog;
Uint16 PackageCount = 0;//CAN的反馈帧计数器
extern Uint16 MFSLData[4];//读到的UART测量数据
//---------------------------------------------------------------------------
// ECan_init:
//---------------------------------------------------------------------------
// This function initializes to a known state.
//需添加eCAN自动应答,否则影响通讯性能
//#pragma CODE_SECTION(ECan_init, "ramfuncs");
void ECan_init(void)
{

/* Create a shadow register structure for the CAN control registers. This is
needed, since only 32-bit access is allowed to these registers. 16-bit access
to these registers could potentially corrupt the register contents or return
false data. This is especially true while writing to/reading from a bit
(or group of bits) among bits 16 - 31 */

asm(" EALLOW");

/* Configure eCAN pins for CAN operation using GPIO regs*/

GpioMuxRegs.GPFMUX.bit.CANTXA_GPIOF6 = 1;
GpioMuxRegs.GPFMUX.bit.CANRXA_GPIOF7 = 1;

// eCAN control registers require 32-bit access.
// If you want to write to a single bit, the compiler may break this
// access into a 16-bit access. One solution, that is presented here,
// is to use a shadow register to force the 32-bit access.

// Read the entire register into a shadow register. This access
// will be 32-bits. Change the desired bit and copy the value back
// to the eCAN register with a 32-bit write.

/* Configure eCAN RX and TX pins for CAN operation using eCAN regs*/

ECanaShadow.CANTIOC.all = ECanaRegs.CANTIOC.all;
ECanaShadow.CANTIOC.bit.TXFUNC = 1;
ECanaRegs.CANTIOC.all = ECanaShadow.CANTIOC.all;

ECanaShadow.CANRIOC.all = ECanaRegs.CANRIOC.all;
ECanaShadow.CANRIOC.bit.RXFUNC = 1;
ECanaRegs.CANRIOC.all = ECanaShadow.CANRIOC.all;

/* Configure eCAN for HECC mode - (reqd to access mailboxes 16 thru 31) */
// HECC mode also enables time-stamping feature

ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
ECanaShadow.CANMC.bit.SCB = 1;
ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;

/* Initialize all bits of 'Master Control Field' to zero */
// Some bits of MSGCTRL register may come up in an unknown state. For proper operation,
// all bits (including reserved bits) of MSGCTRL must be initialized to zero

ECanaMboxes.MBOX0.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX1.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX2.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX3.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX4.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX5.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX6.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX7.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX8.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX9.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX10.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX11.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX12.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX13.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX14.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX15.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX16.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX17.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX18.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX19.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX20.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX21.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX22.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX23.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX24.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX25.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX26.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX27.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX28.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX29.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX30.MSGCTRL.all = 0x00000000;
ECanaMboxes.MBOX31.MSGCTRL.all = 0x00000000;

// TAn, RMPn, GIFn bits are all zero upon reset and are cleared again
// as a matter of precaution.

/* Clear all TAn bits */

ECanaRegs.CANTA.all = 0xFFFFFFFF;

/* Clear all RMPn bits */

ECanaRegs.CANRMP.all = 0xFFFFFFFF;

/* Clear all interrupt flag bits */

ECanaRegs.CANGIF0.all = 0xFFFFFFFF;
ECanaRegs.CANGIF1.all = 0xFFFFFFFF;

/* Configure bit timing parameters */

ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
ECanaShadow.CANMC.bit.CCR = 1 ; // Set CCR = 1
ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;

ECanaShadow.CANES.all = ECanaRegs.CANES.all;

// Wait until the CPU has been granted permission to change the configuration registers
do
{
ECanaShadow.CANES.all = ECanaRegs.CANES.all;
} while(ECanaShadow.CANES.bit.CCE != 1 ); // Wait for CCE bit to be set..
// only as CCR==1 & CCE==1 then ECan start to initialize
ECanaShadow.CANBTC.all = 0;
ECanaShadow.CANBTC.bit.BRPREG = 4;// 4 800K 199(20K); HRL //CLK/( (BRP+1) * ((Tseg1+1)+(Tseg2+1)+1)
ECanaShadow.CANBTC.bit.TSEG2REG =3;//2;//4;//5;
ECanaShadow.CANBTC.bit.TSEG1REG =9;//0xa;//8;//7;
ECanaShadow.CANBTC.bit.SAM = 1;
ECanaRegs.CANBTC.all = ECanaShadow.CANBTC.all;

ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
ECanaShadow.CANMC.bit.CCR = 0 ; // Set CCR = 0
ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;

ECanaShadow.CANES.all = ECanaRegs.CANES.all;

// Wait until the CPU no longer has permission to change the configuration registers
do
{
ECanaShadow.CANES.all = ECanaRegs.CANES.all;
} while(ECanaShadow.CANES.bit.CCE != 0 ); // Wait for CCE bit to be cleared..

/* Disable all Mailboxes */
// Since this write is to the entire register (instead of a bit
// field) a shadow register is not required.

ECanaRegs.CANME.all = 0; // Required before writing the MSGIDs


// Mailboxs can be written to 16-bits or 32-bits at a time
// Write to the MSGID field of TRANSMIT mailboxes MBOX0 - 15

//ECanaMboxes.MBOX0.MSGID.all = 0x01;
//ECanaMboxes.MBOX1.MSGID.all = 0x02;
ECanaMboxes.MBOX0.MSGID.bit.STDMSGID=TEL_ID;
ECanaMboxes.MBOX0.MSGID.bit.IDE=0;
ECanaMboxes.MBOX0.MSGID.bit.AAM=0;
ECanaMboxes.MBOX0.MSGID.bit.AME=1;
ECanaMboxes.MBOX0.MSGID.bit.EXTMSGID_L=0xaaaa;
ECanaMboxes.MBOX0.MSGID.bit.EXTMSGID_H=0x3;

ECanaMboxes.MBOX8.MSGID.bit.IDE=0;// standard frame (ide=0 meas to standard frame ,1 means to extended frame
ECanaMboxes.MBOX8.MSGID.bit.AAM=0;// auto replay set bit
ECanaMboxes.MBOX8.MSGID.bit.AME=0;// acceptance mask bits
ECanaMboxes.MBOX8.MSGID.bit.STDMSGID=TOOL_ID;
ECanaMboxes.MBOX8.MSGID.bit.EXTMSGID_H=0x0;
ECanaMboxes.MBOX8.MSGID.bit.EXTMSGID_L=0xabcd;

// Configure Mailboxes 0-15 as Tx, 16-31 as Rx
// Since this write is to the entire register (instead of a bit
// field) a shadow register is not required.
ECanaRegs.CANMD.all = 0xFFFFFFFE;// 0->send,1->receive

// Enable all Mailboxes */
// Since this write is to the entire register (instead of a bit
// field) a shadow register is not required.
ECanaRegs.CANME.all =(0x1<<0)|(0x1<<8);// 0x03;// 0xFFFFFFFF;

// Specify that 8 bits will be sent
ECanaMboxes.MBOX0.MSGCTRL.bit.DLC = 8;
ECanaMboxes.MBOX1.MSGCTRL.bit.DLC = 8;
ECanaMboxes.MBOX2.MSGCTRL.bit.DLC = 8;
ECanaMboxes.MBOX3.MSGCTRL.bit.DLC = 8;
ECanaMboxes.MBOX4.MSGCTRL.bit.DLC = 8;
ECanaMboxes.MBOX5.MSGCTRL.bit.DLC = 8;
ECanaMboxes.MBOX6.MSGCTRL.bit.DLC = 8;
ECanaMboxes.MBOX7.MSGCTRL.bit.DLC = 8;
ECanaMboxes.MBOX8.MSGCTRL.bit.DLC = 8;
ECanaMboxes.MBOX9.MSGCTRL.bit.DLC = 8;
ECanaMboxes.MBOX10.MSGCTRL.bit.DLC = 8;
ECanaMboxes.MBOX11.MSGCTRL.bit.DLC = 8;
ECanaMboxes.MBOX12.MSGCTRL.bit.DLC = 8;
ECanaMboxes.MBOX13.MSGCTRL.bit.DLC = 8;
ECanaMboxes.MBOX14.MSGCTRL.bit.DLC = 8;
ECanaMboxes.MBOX15.MSGCTRL.bit.DLC = 8;

// Write to the mailbox RAM field of MBOX0 - 15
// Configure the eCAN for self test mode
// Enable the enhanced features of the eCAN.

EALLOW;
ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
ECanaShadow.CANMC.bit.STM = 0; // Configure CAN for self-test mode
ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
EDIS;
EALLOW;
ECanaRegs.CANGIM.bit.GIL=0;
//ECanaRegs.CANMIM.bit.MIM0=1;
ECanaRegs.CANMIM.bit.MIM1=1;
//ECanaRegs.CANMIL.bit.MIL0=0;
ECanaRegs.CANMIL.bit.MIL1=0;
ECanaRegs.CANGIM.bit.I0EN=1;
//ECanaRegs.CANGIM.bit.I1EN=1;
EDIS;

EALLOW;
ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
ECanaShadow.CANMC.bit.ABO = 1; //打开CAN总线自动连接功能
//ECanaShadow.CANMC.bit.DBO = 1;
ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
EDIS;

//没有远方应答帧被请求*/
ECanaMboxes.MBOX8.MSGCTRL.bit.RTR = 0;

//邮箱中断使能
EALLOW;
ECanaRegs.CANMIM.all = 0x00000100;//接收邮箱中断使能
ECanaRegs.CANGIM.all = 0;

//邮箱中断将产生在ECAN0INT
ECanaRegs.CANMIL.all = 0;
ECanaRegs.CANGIF0.all = 0xFFFFFFFF;

//ECAN0INT中断请求线被使能
ECanaRegs.CANGIM.bit.GIL=0;
ECanaRegs.CANGIM.bit.I0EN = 1;

EDIS;

/*设置接收中断服务程序入口地址*/
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.ECAN0INTA = &ECan_int_ISR;
EDIS;


IER |= M_INT9;//开中断
PieCtrlRegs.PIEIER9.bit.INTx5 = 1; //CAN中断0
}

/*------------------------------------------*/
/*形式参数:void */
/*返回值:void */
/*函数描述:CAN中断处理函数 */
/*------------------------------------------*/
//#pragma CODE_SECTION(ECan_int_ISR, "ramfuncs");
interrupt void ECan_int_ISR(void)
{
volatile Uint64 LostData=0;//数据缓冲区满了,丢弃数据,清空mailbox所用变量
TX_sw(1);
DINT;//关闭总中
PieCtrlRegs.PIEACK.bit.ACK9 = 1; //响应中断
if( ECanaRegs.CANRMP.all==(0x00000001<<REC_MSG_box_NO) )//邮箱接收到数据
{
ECanaRegs.CANRMP.all = (0x00000001<<REC_MSG_box_NO);//复位RMP标志,同时也复位中断标志
if(ECanaRegs.CANRFP.all == (0x00000001<<REC_MSG_box_NO) )//邮箱接收到远程帧
{
eCanSend(0x55AA,0x026c,0x0020,0x0000);
eCanSend(0x026c,0xffff,0xffff,0xffff);
eCanSend(PackageCount++,0xffff,0xffff,0xffff);
eCanSend(0xffff,0xffff,0xffff,0xffff);
eCanSend(MFSLData[0],MFSLData[1],MFSLData[2],MFSLData[3]);
eCanSend(0xffff,0xffff,0xffff,0xffff);
eCanSend(0xffff,0xffff,0xffff,0xffff);
eCanSend(0xffff,0xffff,0xffff,0xffff);
CAN_REC_frame.eCanProcessFlag.bit.EPF0 = 1;
CAN_CMD = 0x016c;
ECanaRegs.CANTRR.bit.TRR0 = (0x00000001<<REC_MSG_box_NO);
}
else//收到的是数据帧,井径连斜回复数据
{
if(CanToUartStart == 1)
{
CAN_REC_frame.eCanProcessFlag.bit.EPF0 = 1;//eCan有效数据标志位置1
CAN_CMD= ECanaMboxes.MBOX8.MDL.word.HI_WORD;//读取数据
LostData = ECanaMboxes.MBOX8.MDL.word.LOW_WORD;//读取数据
LostData= ECanaMboxes.MBOX8.MDH.word.HI_WORD;//读取数据
LostData= ECanaMboxes.MBOX8.MDH.word.LOW_WORD;//读取数据
if(CAN_REC_frame.eCanDataCount >= eCanReadBufferSize) CAN_REC_frame.eCanDataCount = 0;
}else
{
LostData = ECanaMboxes.MBOX8.MDL.word.HI_WORD;//读取数据
LostData = ECanaMboxes.MBOX8.MDL.word.LOW_WORD;//读取数据
LostData = ECanaMboxes.MBOX8.MDH.word.HI_WORD;//读取数据
LostData = ECanaMboxes.MBOX8.MDH.word.LOW_WORD;//读取数据
}
}
}
IER |= 0x0100; // Enable INT9
EINT; //开总中断
TX_sw(0);
}

  • 那您45分钟之前都是可以正常接收的?现在是否可以确定上位机一直在发送远程帧?

    能否i请您详细描述下您的实验情况?

  • 可以确认45分钟之前一直都是正常的。45分钟之后,上位机一直也在发,我们拿示波器都测到了DPS的IO口上去了,能看到正确的波形。现在发现这个问题和我的晶振设置有关。我片外晶振是24MHz,倍频5倍到sysclk=60MHz=mclk=lclk。当我采用默认设置的时候,即sysclk:60MHz,mclk=sysclk/2=30MHz,lclk=sysclk/4=15MHz的时候,这个问题就消失了。但是手册里面我看到我这个设置的频率属于合理范围,我的core电压是1.800V,纹波10mV。不太明白为什么不能这么设置。这部分代码如下:
    /*------------------------------------------*/
    /*形式参数:void */
    /*返回值:void */
    /*函数描述:初始化外设时钟 */
    /*------------------------------------------*/
    void InitPeripheralClocks(void)
    {
    EALLOW;

    SysCtrlRegs.HISPCP.all = 0x0000;//MCLK/2^n 60M/1=60M
    SysCtrlRegs.LOSPCP.all = 0x0000;//60M/1=60M

    //使能外围模块时钟
    //SysCtrlRegs.PCLKCR.bit.EVAENCLK=1;
    //SysCtrlRegs.PCLKCR.bit.EVBENCLK=1;
    SysCtrlRegs.PCLKCR.bit.SCIAENCLK=1;
    SysCtrlRegs.PCLKCR.bit.SCIBENCLK=1;
    //SysCtrlRegs.PCLKCR.bit.MCBSPENCLK=1;
    SysCtrlRegs.PCLKCR.bit.SPIENCLK=1;
    SysCtrlRegs.PCLKCR.bit.ECANENCLK=1;
    //SysCtrlRegs.PCLKCR.bit.ADCENCLK=1;
    EDIS;
    }
  • 上个回复是错误的。和MCLK、LCLK的设置无关。什么问题正在查找。目前完全没头绪。
  • 没人回答我就自问自答把。现在终于找到问题所在了,但是BUG的作用机理还是不清楚。经过反复测试,我们需要在主循环中添加一段:
    EALLOW;
    ECanaRegs.CANTSC = 0;
    EDIS;
    这个的作用是清零时间戳计数器数值。
    但是比较奇怪的是2812的手册中显示时间戳功能上电默认状态是禁能的。我的代码中没有理会。也没有开启时间戳中断。为什么必须清零才不会导致CAN中断进不去?这个是个奇怪的问题。