最近通过2812调试CAN碰到一个奇特问题描述如下
三个2812通过can总线连接到一起,每块cpu上跑的程序相同,can总线设置频率1M。每块cpu在ms中断中向其他2块cpu发送一帧数据,在can接收中断中接收其他2块cpu的数据。这时会有小概率发生收到数据中4个字有一个字变为0(大概十万分之一)。程序如下:
ecan.h
#define MOTO_OFFSET 2
#define EN_TX_FUNC 0x8
#define EN_RX_FUNC 0x8
#define MSG_IDL_ENABLE_IDE 0x80000000
#define MSG_IDL_DISABLE_IDE 0
#define MSG_IDL_ENABLE_AME 0x40000000
#define MSG_IDL_DISABLE_AME 0
#define MSG_IDL_ENABLE_AAM 0x20000000
#define MSG_IDL_DISABLE_AAM 0
#define MSG_IDL_ENABLE_RTR 0x10
#define MSG_IDL_DISABLE_RTR 0
void InitEcan(void);
void SetMailData(unsigned int MailNo,unsigned int *pData,unsigned int btDataLen);
void GetMailData(unsigned int MailNo,unsigned int *pData,unsigned int btDataLen);
interrupt void CAN_ISR(void);
void SetMailCtrl(unsigned int MailNo,unsigned int bEnable,unsigned int bSend,unsigned long bIDE,unsigned long bAME,unsigned long bAAM,
unsigned long msgID,unsigned int TPL,unsigned long bRTR,unsigned int Len);
void SetExtMailCtrl(unsigned int MailNo,unsigned long LAM,unsigned long MOTS,unsigned long MOTO);
void SendMailData(unsigned int MailNo);
ecan.c
#ifdef RUN_IN_FLASH
#pragma CODE_SECTION(CAN_ISR, "ramfuncs");
#pragma CODE_SECTION(SetMailData, "ramfuncs");
#pragma CODE_SECTION(GetMailData, "ramfuncs");
#endif
extern volatile struct tagRec recieveStruct;
extern volatile unsigned long g_ulTimer;
extern volatile unsigned long g_CCC;
extern volatile unsigned long g_AAA[6];
extern volatile unsigned g_BBB[4];
void InitEcan(void)
{
unsigned long ultmp=0;
unsigned int index=0;
unsigned int RTAddress=7;
unsigned int Data[4];
EALLOW; //允许改变配置寄存器
IOOut32(CANTIOC,EN_TX_FUNC);//初始化引脚
IOOut32(CANRIOC,EN_RX_FUNC);//初始化引脚
IOOut32(CANMC,0x2000); //选择eCAN模式
EDIS; //禁止改变配置寄存器
for(index=0;index<4;index++)//初始化数据区
{
Data[index]=0; }
for(index=0;index<32;index++) //初始化邮箱设置
{
SetMailCtrl(index,FALSE,TRUE,MSG_IDL_DISABLE_IDE,MSG_IDL_DISABLE_AME,MSG_IDL_DISABLE_AAM,
0,0,MSG_IDL_DISABLE_RTR,0); //设置CAN控制模式
SetExtMailCtrl(index,0,0,0); //设置eCAN控制模式
SetMailData(index,Data,4); //初始化数据缓存
}
RTAddress=aceGetRTAddr(); //得到RT子地址
if(7==RTAddress) //如果是7设置7发送8,9接收
{
SetMailCtrl(0,TRUE,TRUE,MSG_IDL_ENABLE_IDE,MSG_IDL_DISABLE_AME,MSG_IDL_DISABLE_AAM, 7,0,MSG_IDL_DISABLE_RTR,8); SetMailCtrl(1,TRUE,FALSE,MSG_IDL_ENABLE_IDE,MSG_IDL_DISABLE_AME,MSG_IDL_DISABLE_AAM,
8,0,MSG_IDL_DISABLE_RTR,8);
SetMailCtrl(2,TRUE,FALSE,MSG_IDL_ENABLE_IDE,MSG_IDL_DISABLE_AME,MSG_IDL_DISABLE_AAM,
9,0,MSG_IDL_DISABLE_RTR,8);
}
if(8==RTAddress) //如果是8设置8发送7,9接收
{
SetMailCtrl(0,TRUE,TRUE,MSG_IDL_ENABLE_IDE,MSG_IDL_DISABLE_AME,MSG_IDL_DISABLE_AAM, 8,0,MSG_IDL_DISABLE_RTR,8); SetMailCtrl(1,TRUE,FALSE,MSG_IDL_ENABLE_IDE,MSG_IDL_DISABLE_AME,MSG_IDL_DISABLE_AAM,
7,0,MSG_IDL_DISABLE_RTR,8);
SetMailCtrl(2,TRUE,FALSE,MSG_IDL_ENABLE_IDE,MSG_IDL_DISABLE_AME,MSG_IDL_DISABLE_AAM,
9,0,MSG_IDL_DISABLE_RTR,8);
}
if(9==RTAddress) //如果是9设置9发送8,7接收
{
SetMailCtrl(0,TRUE,TRUE,MSG_IDL_ENABLE_IDE,MSG_IDL_DISABLE_AME,MSG_IDL_DISABLE_AAM, 9,0,MSG_IDL_DISABLE_RTR,8); SetMailCtrl(1,TRUE,FALSE,MSG_IDL_ENABLE_IDE,MSG_IDL_DISABLE_AME,MSG_IDL_DISABLE_AAM,
8,0,MSG_IDL_DISABLE_RTR,8);
SetMailCtrl(2,TRUE,FALSE,MSG_IDL_ENABLE_IDE,MSG_IDL_DISABLE_AME,MSG_IDL_DISABLE_AAM,
7,0,MSG_IDL_DISABLE_RTR,8);
}
EALLOW; //允许改变配置寄存器
IOOut32(CANMIM,0x7); //设置CAN中断屏蔽寄存器
IOOut32(CANTA,0xffffffff); //清空发送响应寄存器
IOOut32(CANRMP,0xffffffff); //清除消息挂起寄存器
IOOut32(CANGIF0,0xffffffff); //清除挂起中断
IOOut32(CANGIF1,0xffffffff);
IOOut32(CANGIF1,0xffffffff);
IOOut32(CANOPC,0xffffffff);
ultmp=IOIn32(CANMC); //设置配置模式
ultmp=ultmp|0x1000;
IOOut32(CANMC,ultmp);
EDIS; //禁止改变配置寄存器
ultmp=IOIn32(CANES);
while(!((ultmp&0x10)!=0)) //等待配置模式设置成功
{
ultmp=IOIn32(CANES);
}
EALLOW;
IOOut32(CANBTC,0x9002a); //设置波特率1M
ultmp=IOIn32(CANMC);
ultmp=ultmp&(~0x1000);
IOOut32(CANMC,ultmp);
EDIS;
ultmp=IOIn32(CANES); //退出配置模式
while((ultmp&0x10)!=0) //等待退出模式成功
{
ultmp=IOIn32(CANES);
}
EALLOW;
IOOut32(CANMC,0x2080); //设置全局控制寄存器
EDIS;
EALLOW;
IOOut32(CANMIL,0); //设置中断寄存器
IOOut32(CANGIM,1);
EDIS;
return;
}
void SetMailData(unsigned int MailNo,unsigned int *pData,unsigned int btDataLen)
{
unsigned int index=0;
if(btDataLen>=4) //限制发送长度
{
btDataLen=4;
}
for(index=0;index<btDataLen;index++)
{
IOOut(MAIL_BASE+MailNo*MAIL_OFFSET+MDLL_OFFSET+index,pData[index]); //发送数据
}
return;
}
void GetMailData(unsigned int MailNo,unsigned int *pData,unsigned int btDataLen)
{
unsigned int index=0;
if(btDataLen>=4) //限制读入长度
{
btDataLen=4;
}
for(index=0;index<btDataLen;index++)
{
pData[index]=IOIn(MAIL_BASE+MailNo*MAIL_OFFSET+MDLL_OFFSET+index); //读取数据
}
return;
}
interrupt void CAN_ISR(void)
{
unsigned long ultmp=0;
unsigned int Data[4];
unsigned int index=0,i;
ultmp=IOIn32(CANGIF0); //询问原因
if((ultmp&0x8000)!=0) //如果是油箱消息
{
if((ultmp&0x1f)==0) //如果是邮箱0清除中断
{
IOOut32(CANTA,0x1);
}
if((ultmp&0x1f)==1) //如果是邮箱1
{
GetMailData(ultmp&0x1f,Data,4); //得到数据
if((Data[0]!=0x5555)||(Data[1]!=0x5555)||(Data[2]!=0x5555)||(Data[3]!=0x5555))
{
g_CCC++;
}
recieveStruct.lefttime=g_ulTimer; //记录当前时间
for(index=0;index<4;index++) {
recieveStruct.Left[index]=(int)(Data[index]); //缓存数据
}
IOOut32(CANRMP,0x2); //清除中断
}
if((ultmp&0x1f)==2)
{
GetMailData(ultmp&0x1f,Data,4); if((Data[0]!=0x5555)||(Data[1]!=0x5555)||(Data[2]!=0x5555)||(Data[3]!=0x5555))
{
g_CCC++;
}
recieveStruct.righttime=g_ulTimer; //记录当前时间
for(index=0;index<4;index++)
{
recieveStruct.Right[index]=(int)(Data[index]); //缓存数据
}
IOOut32(CANRMP,0x4); //清除中断
}
}
IOOut(REG_PIEACK,PIE_ACK_GROUP9); //中断返回
return;
}
void SetMailCtrl(unsigned int MailNo,unsigned int bEnable,unsigned int bSend,unsigned long bIDE,unsigned long bAME,unsigned long bAAM,
unsigned long msgID,unsigned int TPL,unsigned long bRTR,unsigned int Len)
{
unsigned long ultmp=0;
unsigned long ultmp1=1;
ultmp=ultmp|bIDE|bAME|bAAM; //设置是否有扩展位
ultmp=ultmp|(msgID&0x1fffffff);
IOOut32(MAIL_BASE+MailNo*MAIL_OFFSET+MSGIDL_OFFSET,ultmp); //设置邮箱标志寄存器
ultmp=0;
ultmp=ultmp|bRTR; //设置远程发送请求 ultmp=ultmp|((TPL&0x1f)<<8); //设置优先级
ultmp=ultmp|(Len&0xf);
IOOut32(MAIL_BASE+MailNo*MAIL_OFFSET+MSGCTRL_OFFSET,ultmp); //设置消息控制寄存器
ultmp=IOIn32(CANME);
ultmp=ultmp&(~(ultmp1<<MailNo)); //允许邮箱
if(bEnable!=0)
{
ultmp=ultmp|(ultmp1<<MailNo);
}
IOOut32(CANME,ultmp);
ultmp=IOIn32(CANMD); //设置邮箱方向
ultmp=ultmp&(~(ultmp1<<MailNo));
if(bSend==0)
{
ultmp=ultmp|(ultmp1<<MailNo);
}
IOOut32(CANMD,ultmp);
return;
}
void SetExtMailCtrl(unsigned int MailNo,unsigned long LAM,unsigned long MOTS,unsigned long MOTO)
{
IOOut32(LAM_BASE +MailNo*LAM_OFFSET ,LAM); //设置LAM
IOOut32(MOTS_BASE+MailNo*MOTS_OFFSET,MOTS); //设置MOTS
IOOut32(MOTO_BASE+MailNo*MOTO_OFFSET,MOTO); //设置MOTO
return;
}
void SendMailData(unsigned int MailNo)
{
unsigned long ultmp=0;
unsigned long ultmp1=1;
ultmp=ultmp|(ultmp1<<MailNo);
IOOut32(CANTRS,ultmp); //发送相应的邮箱
return;
}
ms中断:
…..
for(index=0;index<4;index++)
{
iDiffrence[index]=0x5555;
}
SetMailData(0,(unsigned int *)iDiffrence,4);//发送差值
/* GetMailData(0,(unsigned int *)Data,4);
if((Data[0]!=0x5555)||(Data[1]!=0x5555)||(Data[2]!=0x5555)||(Data[3]!=0x5555))
{
GetMailData(0,(unsigned int *) g_BBB,4);
g_eee++;
}*/
SendMailData(0);
….
另外在ms中断中如果把注释代码去掉断点设在g_eee++处但 g_BBB是全0x5555。猜测是2812can模块和cpu模块同时对邮箱读写会产生冲突,谁能向ti证实一下,本人英文太差不知如何描述如此复杂问题,另外ti那套技术支持实在太差那套东西太复杂不知如何填写。
mangui zhang:
这种小概率事件 确实不好解释 感觉不像是读写冲突
还需你找找规律
TI技术支持可以通过邮箱支持 可以写中文描述