89C52控制的SJA1000的CAN电路问题请教
如图是电路,在控制中配置SJA1000的寄存器,现在是可以发送,不可以接收,请各位大侠指点一下程序 #include <reg51.h>#include <absacc.h>
#define uchar unsigned char
#define uintunsigned int
#define MODE 0x00 //模式寄存器
#define CMR 0x01 //命令寄存器
#define SR 0x02 //状态寄存器
#define IR 0x03 //中断状态寄存器
#define IER 0x04 //中断使能寄存器
#define BTR0 0x06 //总线定时器0
#define BTR1 0x07 //总线定时器1
#define OCR 0x08 //输出控制寄存器
#define ECC 0x0C //错误代码捕捉寄存器
#define RXERR 0x0E //接收错误寄存器
#define TXERR 0x0F //发送错误寄存器
#define ACR 0x10 //识别码信息寄存器
#define AMR 0x14 //屏蔽码寄存器
#define RBSA 0x1E //接收信息计数器
#define CDR 0x1F //时钟分频器
#define HEAD_F 0x20
#define BODY 0x21
#define CHECK 0x22
#define END_F 0x23
sbitSEL_CANd3=P3^4;
sbitSEL_CANd4=P3^5;
sbitint2=P3^3;
sbitint1=P3^2;
sbitRestCANd3=P3^0;
sbitRestCANd4=P3^1;
sbitfrq=P1^7;
uchar idata can_send,can3_rec,can4_rec,can3_send_set_frq,can4_send_set_frq,can3_send_frq,can4_send_frq,address; //
uchar can3_error,can4_error,zj_result,dog_flag,dog_flag2;
uchar can3_counter,can4_counter,flag,msg_flag;
void main(void)
{
int i;
init();
delay();
delay();
delay();
delay();
init();
init_sja1000d3();
init_sja1000d4();
can3_counter=0;
can4_counter=0;
i=0x0;
dog_flag=0;
dog_flag2=0;
SEL_CANd3=1;
SEL_CANd4=1;
can3_send_set_frq=30;
can4_send_set_frq=30;
can3_send_frq=0;
can4_send_frq=0;
can3_error=0xff;
can4_error=0xff;
can_send=0x08;
can_send=0x05;
can_send=0x00;
can_send=0x01;
can_send=0x02;
can_send=0x03;
can_send=0x05;
can_send=0x05;
can_send=0x06;
can_send=0x07;
can_send=0x08;
can_send=0x0c;
can_send=0x0d;
while(1)
{
//can_send=can_send^can_send^can_send^can_send^can_send^can_send^can_send;
//Xor (can_send ~ can_send) ==> LRC Check Value
can_send=can_send;
for(i = 4; i < 10; i ++)
{
can_send ^= can_send;
}
if(can3_send_frq>=(can3_send_set_frq-3))
{
can3_send_frq=0;
send_cand3(0x0);
frq=~frq;
}
if(can4_send_frq>=(can4_send_set_frq-3))
{
can4_send_frq=0;
send_cand4(0x0);
frq=~frq;
}
rec_can4();
address=((can4_rec<<8)+can4_rec)>>5;
if(address==0x29)
{
if(can4_rec==0x25)
{
if(can4_rec==0x55)
{
if(can4_rec==(can4_rec^can4_rec^can4_rec^can4_rec^can4_rec^can4_rec^can4_rec))
{
if(can4_rec!=0x00) {
can4_send_set_frq=can4_rec;
if(can4_send_set_frq<=0x0a)
can4_send_set_frq=0x0a;
}
}
}
}
}
if(can4_send_frq>=(can4_send_set_frq-3))
{
can4_send_frq=0;
send_cand4(0x0);
frq=~frq;
}
if(can4_error==0x00)
{
if(can4_counter>20)
{
init_sja1000d4();
can4_counter=0;
//XBYTE=1;
}
else
{
can4_counter++;
}
can4_error=0xff;
}
rec_can3();
address=((can3_rec<<8)+can3_rec)>>5;
if(address==0x29)
{
if(can3_rec==0x25)
{
if(can3_rec==0x55)
{
if(can3_rec==(can3_rec^can3_rec^can3_rec^can3_rec^can3_rec^can3_rec^can3_rec))
{
if(can3_rec!=0x00) {
can3_send_set_frq=can3_rec;
if(can3_send_set_frq<=0x0a)
can3_send_set_frq=0x0a;
}
}
}
}
}
if(can3_send_frq>=(can3_send_set_frq-3))
{
can3_send_frq=0;
send_cand3(0x0);
frq=~frq;
}
if(can3_error==0x00)
{
if(can3_counter>20)
{
init_sja1000d3();
can3_counter=0;
//XBYTE=1;
}
else
{
can3_counter++;
}
can3_error=0xff;
}
}
}
void send_cand3(uchar ch)
{
uchar can_flag,can_dog;
dog_flag=0;
TH1=(65536-917)/256;
TL1=(65536-917)%256;
TR1=1;
SEL_CANd3=0x0;//XBYTE=0x00; //CAN片选有效
can_flag=XBYTE&0x08; //读状态寄存器
while(can_flag==0x00) //上次发送没有完成,等待
{
SEL_CANd3=0x1; //XBYTE=0xFF;//片选无效
can_dog=dog_flag;//读看门狗状态
if((can_dog&0x01)==0x01)
{
can3_error=0x00;
SEL_CANd3=0x1;
return;
}
SEL_CANd3=0x0;// XBYTE=0x00;//CHANNEL_SJA1000=0;
XBYTE=0x02;//停止发送
can_flag=XBYTE;
can_flag=can_flag&0x08; //读状态寄存器,
}
SEL_CANd3=0x0;
can_flag=XBYTE;
can_flag=can_flag&0x04; //读状态寄存器
while(can_flag==0x00) //缓冲器没有释放,等待
{
SEL_CANd3=0x1; //XBYTE=0xFF;//片选无效
can_dog=dog_flag;//读看门狗状态
if((can_dog&0x01)==0x01)
{
can3_error=0x00;
SEL_CANd3=0x1;
return;
}
SEL_CANd3=0x0;//XBYTE=0x00;//CHANNEL_SJA1000=0;
can_flag=XBYTE;
can_flag=can_flag&0x04; //读状态寄存器
}
SEL_CANd3=0x0;
switch(ch)
{
case 0x00:// 正常100ms周期发送自搜索目标信息
XBYTE=can_send;//发送帧信息
XBYTE=can_send;//发送识别地址1 给综合管理器和操控单元
XBYTE=can_send;//发送识别地址2
XBYTE=can_send;//发送识别地址3
XBYTE=can_send;//发送识别地址4
XBYTE=can_send;//发送第1字节
XBYTE=can_send;//发送第2字节
XBYTE=can_send;//发送第3字节
XBYTE=can_send;//发送第4字节
XBYTE=can_send;//发送第5字节
XBYTE=can_send;//发送第6字节
break;
case 0x01://发送自检结果
XBYTE=0x85;//发送帧信息
XBYTE=0x18;//发送识别地址1 给综合管理器和操控单元
XBYTE=0xf0;//发送识别地址2
XBYTE=0x78;//发送识别地址3
XBYTE=0x76;//发送识别地址4
XBYTE=zj_result;//0x11;//zj_result设备自检正常0x11,0x12自检故障
break;
case 0x02://发送软件版本信息
XBYTE=0x85;//发送帧信息
XBYTE=0x18;//发送识别地址1 给综合管理器和操控单元
XBYTE=0xf0;//发送识别地址2
XBYTE=0x78;//发送识别地址3
XBYTE=0x76;//发送识别地址4
XBYTE=1;//信息长度
XBYTE=0;//信息串序列
XBYTE=0x6f;//软件标识
XBYTE=0x8c;//软件配置项编码
XBYTE=0;//软件版本号 0:方案样机;1:初样;2:正样;3:定型样机
XBYTE=0;//软件更改版本号,起始0,更改1次加1
XBYTE=0;//软件修订版本号,起始0,更改1次加1
XBYTE=0x63;//保留
break;
case 0x03://发送开机自检结果
XBYTE=0x85;//发送帧信息
XBYTE=0x18;//发送识别地址1 给综合管理器和操控单元
XBYTE=0xf0;//发送识别地址2
XBYTE=0x78;//发送识别地址3
XBYTE=0x76;//发送识别地址4
XBYTE=zj_result;//0x11;//zj_result设备自检正常0x15,0x16自检故障
break;
default:
break;
}
XBYTE=0x01;//启动发送
SEL_CANd3=0x1;//XBYTE=0xFF;//片选无效
can3_error=0xff;
can3_counter=0;
TR1=0;
TH1=(65536-917)/256;
TL1=(65536-917)%256;
can_flag=0x00;//将can总线清除到目标信息发送
return;
}
/**************定时器0中断服程序****************************/
voidtime0_int(void) interrupt 1
{
TH0=(65536-917)/256;
TL0=(65536-917)%256; //1ms定时
can3_send_frq=can3_send_frq+1;
can4_send_frq=can4_send_frq+1;
}
/**************定时器1中断服程序****************************/
voidtime1_int(void) interrupt 3
{
TH1=(65536-917)/256;
TL1=(65536-917)%256; //1ms定时
dog_flag=0x01;
test=~test;
}
/**************定时器2中断服程序****************************/
voidtime2_int(void) interrupt 5
{
TF2=0; //!!!注意!!! 定时器2必须由软件对溢出标志位清零,硬件不能清零,这里与定时器0和定时器1不同!!!
TH2=(65536-917)/256;
TL2=(65536-917)%256; //1ms定时
dog_flag2=0x01;
// dog_flag=0x01;
// test=~test;
}
/****************************sja1000d4 int**************/
void init_sja1000d4(void)//can口初始化程序
{
uchar can_temp;
RestCANd4=0; //can硬件复位
delay();
RestCANd4=1;
SEL_CANd4=0x0;//片选有效,可以对SJA1000进行操作了
XBYTE=0xaa;//测试CAN连接
can_temp=XBYTE;
if(can_temp!=0xaa)
{
//不相等连接没有 ,初始化失败,退出
SEL_CANd4=0x1;//片选无效
//XBYTE=0x1;//点故障灯3个灯全亮
//XBYTE=0x1;
//XBYTE=0x1;
return;
}
SEL_CANd4=0x0;//XBYTE=0x00;
XBYTE=0x09; //进入软件复位
can_temp=XBYTE&0x01;//确认进入了复位
if(can_temp==0x00)
{
SEL_CANd4=0x1;//XBYTE=0x0FF;//片选无效
//XBYTE=0x1;//XBYTE=0x03;//点故障灯2个灯亮
//XBYTE=0x1;
return;
}
XBYTE =0xC8 ;//c8设置时钟分频器CDR CAN工作在扩展模式,RX1必须接到固定电平,关闭时钟输出B
//XBYTE =0x09 ;//中断使能,开放发送中断超载中断和错误警告中断 IER0x09
XBYTE=0x03 ;//设置波特率 同步跳转为2,晶振频率16M,分频数为16,波特率为001c,500K011c,250KBTR0 031c125k
XBYTE=0x1c ;//总线定时寄存器1 BTR1
XBYTE =0x1a ;//aa输出控制寄存器设置 OCR 正常工作模式
XBYTE =0x00 ;//RXERR 清0 接收错误寄存器
XBYTE =0x00 ;//发送错误寄存器
XBYTE =0x05 ;//设置帧信息,验收码ACR 0~3BIT7=1 CAN工作在扩展模式;BIT3=1数据为8个
XBYTE =0x00 ;
XBYTE =0x80 ;
XBYTE =0x00 ;
XBYTE =0xfa ;//设置屏蔽码,bitx=1表示该位不参与校验AMR0~3
XBYTE =0xff ;
XBYTE =0xff ;
XBYTE =0xff ;
XBYTE=0x00 ;//设置接收缓冲器起始地址
XBYTE=0x08; //清除软件复位
// XBYTE=0x88; //发送帧信息
XBYTE =0x09 ;//中断使能,开放发送中断超载中断和错误警告中断 IER0x09
SEL_CANd4=0x1;//XBYTE=0xFF;//片选无效
SEL_CANd4=0x1;//XBYTE=0xFF;
return;
}
/********************************************send_can4********************/
void send_cand4(uchar ch)
{
uchar can_flag,can_dog;
// dog_flag=0;
// TH1=(65536-917)/256;
// TL1=(65536-917)%256;
// TR1=1;
dog_flag2=0;
TH2=(65536-917)/256;
TL2=(65536-917)%256;
TR2=1; //启动定时器2
//XBYTE=0xFF; //关狗,复位狗
//XBYTE=0x00; //开狗
SEL_CANd4=0x0;//XBYTE=0x00; //CAN片选有效
can_flag=XBYTE&0x08; //读状态寄存器,
while(can_flag==0x00) //上次发送没有完成,等待
{
SEL_CANd4=0x1; //XBYTE=0xFF;//片选无效
// XBYTE=0x01;//点灯1个亮
can_dog=dog_flag2;//读看门狗状态
if((can_dog&0x01)==0x01)
{
can4_error=0x00;
SEL_CANd4=0x1;
return;
}
SEL_CANd4=0x0;// XBYTE=0x00;//CHANNEL_SJA1000=0;
XBYTE=0x02;//停止发送
can_flag=XBYTE;
can_flag=can_flag&0x08; //读状态寄存器,
}
SEL_CANd4=0x0;
can_flag=XBYTE;
can_flag=can_flag&0x04; //读状态寄存器
while(can_flag==0x00) //缓冲器没有释放,等待
{
SEL_CANd4=0x1; //XBYTE=0xFF;//片选无效
//XBYTE=0x01; //点灯1个亮
can_dog=dog_flag2;//读看门狗状态
if((can_dog&0x01)==0x01)
{
can4_error=0x00;
SEL_CANd4=0x1;
return;
}
SEL_CANd4=0x0;// XBYTE=0x00;// CHANNEL_SJA1000=0;
can_flag=XBYTE;
can_flag=can_flag&0x04; //读状态寄存器
}
SEL_CANd4=0x0;
switch(ch)
{
case 0x00:// 正常100ms周期发送自搜索目标信息
XBYTE=can_send;//发送帧信息
XBYTE=can_send;//发送识别地址1 给综合管理器和操控单元
XBYTE=can_send;//发送识别地址2
XBYTE=can_send;//发送识别地址3
XBYTE=can_send;//发送识别地址4
XBYTE=can_send;//发送第1字节
XBYTE=can_send;//发送第2字节
XBYTE=can_send;//发送第3字节
XBYTE=can_send;//发送第4字节
XBYTE=can_send;//发送第5字节
XBYTE=can_send;//发送第6字节
//XBYTE=can_send;//发送第7字节
//XBYTE=can_send;//发送第8字节
break;
case 0x01://发送自检结果
XBYTE=0x85;//发送帧信息
XBYTE=0x18;//发送识别地址1 给综合管理器和操控单元
XBYTE=0xf0;//发送识别地址2
XBYTE=0x78;//发送识别地址3
XBYTE=0x76;//发送识别地址4
XBYTE=zj_result;//0x11;//zj_result设备自检正常0x11,0x12自检故障
//XBYTE=zj_data;
//XBYTE=rec_m2;
break;
case 0x02://发送软件版本信息
XBYTE=0x85;//发送帧信息
XBYTE=0x18;//发送识别地址1 给综合管理器和操控单元
XBYTE=0xf0;//发送识别地址2
XBYTE=0x78;//发送识别地址3
XBYTE=0x76;//发送识别地址4
XBYTE=1;//信息长度
XBYTE=0;//信息串序列
XBYTE=0x6f;//软件标识
XBYTE=0x8c;//软件配置项编码
XBYTE=0;//软件版本号 0:方案样机;1:初样;2:正样;3:定型样机
XBYTE=0;//软件更改版本号,起始0,更改1次加1
XBYTE=0;//软件修订版本号,起始0,更改1次加1
XBYTE=0x63;//保留
break;
case 0x03://发送开机自检结果
XBYTE=0x85;//发送帧信息
XBYTE=0x18;//发送识别地址1 给综合管理器和操控单元
XBYTE=0xf0;//发送识别地址2
XBYTE=0x78;//发送识别地址3
XBYTE=0x76;//发送识别地址4
XBYTE=zj_result;//0x11;//zj_result设备自检正常0x15,0x16自检故障
//XBYTE=zj_data;
break;
default:
break;
}
XBYTE=0x01;//启动发送
SEL_CANd4=0x1;//XBYTE=0xFF;//片选无效
can4_error=0xff;
can4_counter=0;
// TR1=0;
// TH1=(65536-917)/256;
// TL1=(65536-917)%256;
TR2=2; //关闭定时器2
TH2=(65536-917)/256;
TL2=(65536-917)%256;
can_flag=0x00;//将can总线清除到目标信息发送
return;
}
void rec_can3(void)
{
uchar can_reg,can_flag;
SEL_CANd3=0x0; //XBYTE=0x00;//CHANNEL_SJA1000=0;//片选有效
can_reg=XBYTE;//读状态寄存器
can_flag=can_reg&0x08;//看是否为数据溢出中断
if(can_flag==0x08)
{
XBYTE=0x0c;//清除数据溢出以及释放接收缓冲器
SEL_CANd3=0x1; //XBYTE=0xFF;//CHANNEL_SJA1000=1;//取消片选
can3_error=0x00;
//XBYTE=0x1;//写灯
return;
}
can_flag=can_reg&0x01;//接收中断位为继续执行,否则跳出子程序
if(can_flag==0x00)
{
SEL_CANd3=0x1; //XBYTE=0xFF;//CHANNEL_SJA1000=1;//取消片选
//XBYTE=0x1;//写灯
can3_error=0x00;
return;
}
//开始接收
can3_rec=XBYTE;//接收中断位为1跳转 ACR0
can_flag=can3_rec&0x40;//远程帧判断
if(can_flag==0x40)
{
XBYTE=0x04;//信息为远程帧,释放接收缓冲后退出
SEL_CANd3=0x1; //XBYTE=0xFF;//CHANNEL_SJA1000=1;//取消片选
//XBYTE=0x1;//写灯
can3_error=0x00;
return;
}
can3_rec=XBYTE;// ACR1
can3_rec=XBYTE;// ACR2
can3_rec=XBYTE;// ACR3
can3_rec=XBYTE;// ACR4
can3_rec=XBYTE;// DATA1
can3_rec=XBYTE;// DATA2
can3_rec=XBYTE;// DATA3
can3_rec=XBYTE;// DATA4
can3_rec=XBYTE;// DATA5
can3_rec=XBYTE;// DATA6
//can3_rec=XBYTE;// DATA7
//can3_rec=XBYTE;// DATA8
XBYTE=0x04;//读完数据后,释放接收缓冲后退出
SEL_CANd3=0x1;//XBYTE=0xFF;//CHANNEL_SJA1000=1;//取消片选
return;
}
/****************554判断*************/
void read_554_cha(void)//554通道判读
{
uchar flag;
//EA=0;
CSA=0; //选中554,对554进行操作
flag=XBYTE&0x0c; //判断数据口
switch(flag)//完整接收
{
case 0x04:
read554(0x01);
data_process_ch(0x01);//正常接收
break;
case 0x0c:
read554(0x01);
data_process_ch(0x01);//超时中断,将接收FIFO读空
break;
default:
break;
}
CSA=1;//取消554选择
//EA=1;
return;
}
void read_554_chb(void)//554通道判读
{
uchar flag;
//EA=0;
CSB=0; //选中554,对554进行操作
flag=XBYTE&0x0c; //判断数据口
switch(flag)//完整接收
{
case 0x04:
read554(0x02);
data_process_ch(0x02);//正常接收
break;
case 0x0c:
read554(0x02);
data_process_ch(0x02);//超时中断,将接收FIFO读空
break;
default:
break;
}
CSB=1;//取消554选择
//EA=1;
return;
}
void rec_can4(void)
{
uchar can_reg,can_flag;
SEL_CANd4=0x0; //XBYTE=0x00;//CHANNEL_SJA1000=0;//片选有效
can_reg=XBYTE;//读状态寄存器
can_flag=can_reg&0x08;//看是否为数据溢出中断
if(can_flag==0x08)
{
XBYTE=0x0c;//清除数据溢出以及释放接收缓冲器
SEL_CANd4=0x1; //XBYTE=0xFF;//CHANNEL_SJA1000=1;//取消片选
can3_error=0x00;
//XBYTE=0x1;//写灯
return;
}
can_flag=can_reg&0x01;//接收中断位为继续执行,否则跳出子程序
if(can_flag==0x00)
{
SEL_CANd4=0x1; //XBYTE=0xFF;//CHANNEL_SJA1000=1;//取消片选
//XBYTE=0x1;//写灯
can3_error=0x00;
return;
}
//开始接收
can4_rec=XBYTE;//接收中断位为1跳转 ACR0
can_flag=can4_rec&0x40;//远程帧判断
if(can_flag==0x40)
{
XBYTE=0x04;//信息为远程帧,释放接收缓冲后退出
SEL_CANd4=0x1; //XBYTE=0xFF;//CHANNEL_SJA1000=1;//取消片选
//XBYTE=0x1;//写灯
can3_error=0x00;
return;
}
can4_rec=XBYTE;// ACR1
can4_rec=XBYTE;// ACR2
can4_rec=XBYTE;// ACR3
can4_rec=XBYTE;// ACR4
can4_rec=XBYTE;// DATA1
can4_rec=XBYTE;// DATA2
can4_rec=XBYTE;// DATA3
can4_rec=XBYTE;// DATA4
can4_rec=XBYTE;// DATA5
can4_rec=XBYTE;// DATA6
//can4_rec=XBYTE;// DATA7
//can4_rec=XBYTE;// DATA8
XBYTE=0x04;//读完数据后,释放接收缓冲后退出
SEL_CANd4=0x1;//XBYTE=0xFF;//CHANNEL_SJA1000=1;//取消片选
return;
}
这个程序是可以发送的,没有问题,但不能接收
我把接收程序里的下面一段程序注销了可以接收,但会频繁死机,可能是发送时导致总线数据冲突自动关闭
can_reg=XBYTE;//读状态寄存器
can_flag=can_reg&0x08;//看是否为数据溢出中断
if(can_flag==0x08)
{
XBYTE=0x0c;//清除数据溢出以及释放接收缓冲器
SEL_CANd4=0x1; //XBYTE=0xFF;//CHANNEL_SJA1000=1;//取消片选
can3_error=0x00;
//XBYTE=0x1;//写灯
return;
}
can_flag=can_reg&0x01;//接收中断位为继续执行,否则跳出子程序
if(can_flag==0x00)
{
SEL_CANd4=0x1; //XBYTE=0xFF;//CHANNEL_SJA1000=1;//取消片选
//XBYTE=0x1;//写灯
can3_error=0x00;
return;
} 我之前用51+SJA1000,C51写的,多个项目,运行良好,商品化出货。
没有因为CAN接收卡壳的,SJA1000超稳定好使得很。
相信他,没问题。 jiki119 发表于 2016-9-19 16:52
我之前用51+SJA1000,C51写的,多个项目,运行良好,商品化出货。
没有因为CAN接收卡壳的,SJA1000超稳定好 ...
能给我一份参考程序吗,或者你看一下我的程序有哪里配置不合理,我在网上看到一个人做的CAN只用到CS,INT和RST都不用,这是什么原因
http://wenku.baidu.com/link?url=pC3B1iVgng4zRY19uNr1QCWcFobVh4R9gPFPKQMswktSyIQCDPnAOGlfUA8GGjb85NXBmW4MSECWWwJ8-3-W-0_CKiWorAjcv1AvGqkqQ1K
页:
[1]