📄 sja1000.txt
字号:
[单片机应用]CAN节点(SJA1000)的通讯程序
沙漠风雨 发表于 2008-1-26 9:58:20
以下是我做的CAN节点的测试程序, 实现两个节点传送数据,程序主要分三部分 SJA1000 的初始化,接收数据,发送数据.
以下程序如要转载,请注明出处
/****************************************************
**函数原型: bit Sja_1000_Init(void)
**功 能: 初始化SJA10000
**入口参数: 无
**返 回 值:
0: 初始化成功
1: 复位失败
2: 测试sja1000失败
3: 设置失败
4: 设置验收滤波器失败
5: 设置波特率失败
*****************************************************/
unsigned char Sja_1000_Init(void)
{
bit s;
EA=0;
s=BCAN_ENTER_RETMODEL();
if (s==1) return 1;
s=BCAN_CREATE_COMMUNATION();
if (s==1) return 2;
s=BCAN_SET_OUTCLK(0xc0);//Pelican
if (s==1) return 3;
s=BCAN_SET_OBJECT(0xFF,0x4E,0x16,0x00,0xff,0x00,0x00,0x00);
if (s==1) return 4;
s=BCAN_SET_BANDRATE(CAN_BPS_1M);
if (s==1) return 5;
SJA_BCANAdr=REG_OCR ;
*SJA_BCANAdr=0x1a;
SJA_BCANAdr=REG_IER;
*SJA_BCANAdr=0x03;
s=BCAN_SET_CONTROL(0x08);
if (s==1) return 6;
EA=1;
return 0;
}
}
/************************************************************************
*函数原型: bit BCAN_SET_OUTCLK( unsigned char Clock_Out) *
*参数说明: *
* Clock_Out:存放时钟分频寄存器(CDR)的参数设置 *
*返回值: *
* 0 ;设置成功 *
* 1 ;设置失败 *
*说明:设置SJA1000的时钟分频 。该子程序只能用于复位模式
************************************************************************/
bit BCAN_SET_OUTCLK(unsigned char Clock_Out)
{
SJA_BCANAdr=REG_CDR;
*SJA_BCANAdr=Clock_Out;
if(*SJA_BCANAdr != Clock_Out)
return 1;
else
return 0;
}
/************************************************************************
*函数原型: bit BCAN_SET_OBJECT(unsigned char BCAN_ACR0,BCAN_ACR1,BCAN_ACR2,BCAN_ACR3
BCAN_AMR0, BCAN_AMR1, BCAN_AMR2, BCAN_AMR3
*参数说明: *
* BCAN_ACR(0-3):存放验收代码寄存器(ACR)的参数设置 *
* BCAN_AMR(0-3):存放接收屏蔽寄存器(AMR)的参数设置 *
*返回值: *
* 0 ;设置成功 *
* 1 ;设置失败 *
*说明:设置CAN节点的通讯对象,允许接收的报文,是由AMR和ACR共同决定的. *
*************************************************************************/
bit BCAN_SET_OBJECT(unsigned char BCAN_ACR0,BCAN_ACR1,BCAN_ACR2,BCAN_ACR3,BCAN_AMR0,BCAN_AMR1,BCAN_AMR2,BCAN_AMR3)
{
SJA_BCANAdr=REG_TxBuffer1;
*SJA_BCANAdr=BCAN_ACR0; //写入参数
SJA_BCANAdr=REG_TxBuffer2;
*SJA_BCANAdr=BCAN_ACR1;
SJA_BCANAdr=REG_TxBuffer3;
*SJA_BCANAdr=BCAN_ACR2;
SJA_BCANAdr=REG_TxBuffer4;
*SJA_BCANAdr=BCAN_ACR3;
//校验写入值
if(*SJA_BCANAdr != BCAN_ACR3) return 1;
SJA_BCANAdr=REG_TxBuffer5;
*SJA_BCANAdr=BCAN_AMR0; //写入参数
SJA_BCANAdr=REG_TxBuffer6;
*SJA_BCANAdr=BCAN_AMR1;
SJA_BCANAdr=REG_TxBuffer7;
*SJA_BCANAdr=BCAN_AMR2;
SJA_BCANAdr=REG_TxBuffer8;
*SJA_BCANAdr=BCAN_AMR3;
//校验写入值
if(*SJA_BCANAdr != BCAN_AMR3) return 1;
return 0;
}
/********************************************************************
;*函数原型: bit BCAN_SET_BANDRATE(unsigned char CAN_ByteRate) *
;*返回值: *
;* 0 ;波特率设置成功 *
;* 1 ;波特率设置失败 *
;* *
;*说明:设置CAN控制器SJA1000通讯波特率.SJA1000的晶振必须为16MHZ, *
;* 其它晶体的频率的值的波特率,需自己计算 。该子程序只能用于 *
;* 复位模式 *
;************************************************************************/
bit BCAN_SET_BANDRATE(unsigned int CAN_ByteRate)
{
//将波特率的的预设值装入sja1000的总线定时器
SJA_BCANAdr =REG_BTR0;
*SJA_BCANAdr =CAN_ByteRate>>8; // 取CAN_ByteRate的高8位写入 写入参数
//校验写入值
if(*SJA_BCANAdr !=(CAN_ByteRate>>8)) return 1;
SJA_BCANAdr=REG_BTR1;
*SJA_BCANAdr=CAN_ByteRate;
//校验写入值
if(*SJA_BCANAdr !=CAN_ByteRate) return 1;
return 0;
}
/************************************************************************
*函数原型: bit BCAN_SET_CONTROL(unsigend char CMD) *
*参数说明: 设置控制寄存器 *
************************************************************************/
bit BCAN_SET_CONTROL(unsigned char CMD)
{ unsigned char TempData;
SJA_BCANAdr=REG_CONTROL; //SJA_BaseAdr+0x00 控制寄存器
TempData= *SJA_BCANAdr;
*SJA_BCANAdr=CMD;
if (*SJA_BCANAdr == CMD)
return 0;
else
return 1;
}
/************************************************************************
*函数原型: bit BCAN_CREATE_COMMUNATION(void) *
*参数说明: 无 *
*返回值: *
* 0 ; 表示SJA1000接口正常 *
* 1 ; 表示SJA1000与处理器接口不正常 *
*说明:该函数用于检测CAN控制器的接口是否正常 *
************************************************************************/
bit BCAN_CREATE_COMMUNATION(void)
{
SJA_BCANAdr=REG_TEST;
*SJA_BCANAdr=0xaa; //写入测试值
if(*SJA_BCANAdr == 0xaa)
return 0; //读测试正确
else
return 1;
}
/************************************************************************
*函数原型: bit BCAN_ENTER_RETMODEL(void) *
*参数说明: 无 *
*返回值: *
* 0 ; 表示成功进入复位工作模式 *
* 1 ; 表示不能进入复位工作模式 *
* *
*说明: CAN控制器进入复位工作模式 *
************************************************************************/
bit BCAN_ENTER_RETMODEL(void) //置位复位请求
{
unsigned char TempData;
SJA_BCANAdr = REG_CONTROL;
TempData= *SJA_BCANAdr;
*SJA_BCANAdr=0x01; //置位复位请求
if((*SJA_BCANAdr&0x01) == 1)
return 0;
else
return 1;
}
/****************************************************
**函数原型: void ex0_int(void) interrupt 0 //using 1
**功 能: 中断接收函数
**入口参数: 无
**出口参数: RevceData[]数组
**说 明: 当sja1000 收到正确的报文时,会产生int中断
*****************************************************/
void ex0_int(void) interrupt 0 //using 1
{ unsigned char tt;
SJA_BCANAdr=REG_INTERRUPT;
if((*SJA_BCANAdr)&0x01) //产生了接收中断
{
SJA_BCANAdr=REG_RxBuffer1;
tt=*SJA_BCANAdr;
if ((tt&0x40)!=0x40) //数据帧 = 为远程帧
{ memcpy(REG_RxBuffer6,RevceData,8);
send_char_com(RevceData[1]);//以下代码是发送到串口
send_char_com(RevceData[2]);
send_char_com(RevceData[3]);
send_char_com(RevceData[4]);
send_char_com(RevceData[5]);
send_char_com(RevceData[6]);
send_char_com(RevceData[7]);
send_char_com(RevceData[8]);
}
BCAN_CMD_PRG(4);//释放SJA1000接收缓冲区
}
}
unsigned char BCAN_DATA_WRITE(unsigned char *SendDataBuf)
{ unsigned char temp;
SJA_BCANAdr = REG_STATUS;
temp=*SJA_BCANAdr;
if ((temp&0x08)==0) return 1; //上次发送未完成
if ((temp&0x04)==0) return 2; //发送缓冲区是否锁定
if ((temp&0x10)==0x10) return 3; //判断是否正在接收
SJA_BCANAdr = REG_TxBuffer1; //访问地址指向发送缓冲区1
memcpy(SJA_BCANAdr,SendDataBuf,13);
BCAN_CMD_PRG(0x03);
return 0;
}
bit BCAN_CMD_PRG(unsigned char cmd)
{
SJA_BCANAdr=REG_COMMAND; //访问地址指向命令寄存器
*SJA_BCANAdr=cmd; //启动命令字
switch(cmd)
{ case TR_CMD:
return 0;
break;
case SRR_CMD:
return 0;
break;
case AT_CMD:
SJA_BCANAdr = REG_STATUS; //访问地址指向状态寄存器
if((*SJA_BCANAdr & 0x20)==0)//判断是否正在发送
return 0;
else
return 1;
break;
case RRB_CMD:
SJA_BCANAdr = REG_STATUS; //访问地址指向状态寄存器
if((*SJA_BCANAdr & 0x01)==1)
return 1;
else
return 0;
break;
case COS_CMD:
SJA_BCANAdr = REG_STATUS;
if((*SJA_BCANAdr & 0x02)==0)//判断清除超载是否成功
return 0;
else
return 1;
break;
default:
return 1;
break;
}
}
主程序部分:
void main(void)
{ unsigned char temptt,ss;
CS=0;
Init_Cpu();
EA=0;
//initialize Sja1000
ss=Sja_1000_Init();
if (ss!=0)//初始化失败
send_string_com("init fail!");
else
EA=1; //初始化成功,开中断
RECOK=0;
send_data[0]=Send_CAN_Info_ID[0];
send_data[1]=Send_CAN_Info_ID[1];
send_data[2]=Send_CAN_Info_ID[2];
send_data[3]=Send_CAN_Info_ID[3];
send_data[4]=Send_CAN_Info_ID[4];
while(1)
{
SJA_BCANAdr = REG_STATUS;
temptt=*SJA_BCANAdr;
if ((temptt&0x40)==0x40)
{
Sja_1000_Init();
send_char_com(0xee);
}
if (RECOK==1)
{ RECOK=0;
SJA_BCANAdr = REG_STATUS;
temptt=*SJA_BCANAdr;
if((temptt&0x04)==0x04) //可以向发送缓冲器写数据
{
send_data[5]=Com_RecBuff[0];
send_data[6]=Com_RecBuff[1];
send_data[7]=Com_RecBuff[2];
send_data[8]=Com_RecBuff[3];
send_data[9]=Com_RecBuff[4];
send_data[10]=Com_RecBuff[5];
send_data[11]=Com_RecBuff[6];
send_data[12]=Com_RecBuff[7];
ss=BCAN_DATA_WRITE(send_data);
if (ss==0) //发送正常
send_char_com(0x11);
else
{
send_char_com(0xFF);
send_char_com(ss);
SJA_BCANAdr= REG_ECC;
send_char_com(*SJA_BCANAdr);
}
}
}
}
}
以上程序只能做为试验使用!!! 如要转载,请注明出处
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -