📄 sja1000.c
字号:
bit ErrorFlag =1;
unsigned char ErrorCount = 0x20; //32次报错
if(CAN_ByteRate>14){
ErrorFlag =1;
}
else{
while(--ErrorCount)
{
WriteDataToSJA1000(REG_CAN_BTR0,SJA_BTR_CODETAB[CAN_ByteRate*2]);
WriteDataToSJA1000(REG_CAN_BTR1,SJA_BTR_CODETAB[CAN_ByteRate*2+1]);
if(ReadDataFromSJA1000(REG_CAN_BTR0) != SJA_BTR_CODETAB[CAN_ByteRate*2])
{
continue;
}
if(ReadDataFromSJA1000(REG_CAN_BTR1) != SJA_BTR_CODETAB[CAN_ByteRate*2+1])
{
continue;
}
ErrorFlag=0;
break;
}//while结束
}
return ErrorFlag ;
}
/**********************使能SJA1000的各种中断***************************/
/**********************************************************************/
bit BCAN_SET_INT(unsigned char inter)
{
bit ErrorFlag =1;
unsigned char TempData=ReadDataFromSJA1000(REG_CAN_IER); //中断使能寄存器IER
unsigned char ErrorCount = 0x20; //32次报错
while(ErrorCount--)
{
TempData |= inter;
WriteDataToSJA1000(REG_CAN_IER, TempData);
if(ReadDataFromSJA1000(REG_CAN_IER)!= TempData) //校验写入值
{
continue;
}
ErrorFlag =0;
break;
}
return ErrorFlag;
}
/************************************************************************
*以下为应用函数实现源代码 *
***********************************************************************
*/
/************************************************************************
*函数原型: bit BCAN_HW_INIT(unsigned char BCAN_ACR, *
* unsigned char BCAN_AMR, *
* unsigned char Bus_Timing0, *
* unsigned char Bus_Timing1, *
* unsigned char Out_Control, *
* unsigned char Clock_Out *
* ) *
*参数说明: *
* BCAN_ACR:存放验收代码寄存器(ACR)的参数设置 *
* BCAN_AMR:存放接收屏蔽寄存器(AMR)的参数设置 *
* Bus_Timing0:存放总线定时0寄存器(BTR0)的参数设置 *
* Bus_Timing1:存放总线定时1寄存器(BTR1)的参数设置 *
* Out_Control:存放输出控制寄存器 (OC) 的参数设置 *
* Clock_Out:存放时钟分频寄存器 (CDR) 的参数设置 *
* *
*返回值: *
* 0 ; 表示初始化成功 *
* 1 ; 表示初始化失败 *
* *
*说明:CAN控制器的初始化只能在复位模式下才能完成。初始化操作之前请先进入*
* 到复位操作模式,并将要初始化的各参数的值按数据手册中的计算方法,正 *
* 确的按实际需要计算好参数后,将参数写入对应的寄存器 。 *
*注: 为了CAN控制器的正确运行,请务必仔细的阅读SJA1000的数据手册 *
* *
*示例:设应用系统中晶体频率16MHZ,节点只接收ID(标志符)高八位为 *
* '10101010'的消息,系统波特率为50Kbit/s,关闭CLKOUT输出。 *
* 则根据数据手册中的计算方法的各参数如下: *
* ACR==0AAH,AMR==00H,BTR0==0C9H,BTR1==0C9H,OC==0FFH,CDR=48H *
* 则调用本函数为: *
* BCAN_HW_INIT(0xaa,0x00,0xc9,0xc9,0xff,0x48) *
***********************************************************************
*/
bit PELICAN_HW_INIT( unsigned char idata out_control,unsigned char idata clk_out,unsigned char idata bandrate,unsigned char idata inter)
{
bit Flag =1;
if(BCAN_CREATE_COMMUNATION() != 0) //检测CAN控制器的接口是否正常
{
return Flag;
}
if(BCAN_ENTRY_RETMODEL() != 0) //CAN控制器进入复位工作模式
{
return Flag;
}
if(BCAN_SET_OUTCLK(out_control,clk_out) !=0) //设置SJA1000的输出模式和时钟分频 。该子程序只能用于复位模式
{
return Flag;
}
if(BCAN_SET_OBJECT(0x00,0x01,0x00,0x00,0xff,0xff,0xff,0xff)!=0) // 设置CAN节点的通讯对象,允许接收的报文ID号的高8位(D10--D3) 。 *
//允许接收的报文,是由AMR和ACR共同决定的.该子程序只能用于复位模式
{
return Flag;
}
if(BCAN_SET_BANDRATE(bandrate) !=0) //该函数用于设定在系统晶体为16MHZ时,常用的标准波特率的值,该子程序只能用于复位模式
{
return Flag;
}
if(BCAN_SET_INT(inter) !=0) //使能SJA1000的各种中断
{
return Flag;
}
if(BCAN_QUIT_RETMODEL() !=0) //CAN控制器退出复位工作模式
{
return Flag;
}
Flag=0;
return Flag;
}
/*
***********************************************************************
*函数原型: bit BCAN_DATA_WRITE(unsigned char *SendDataBuf) *
*参数说明: 特定帧各式的数据? *
*返回值: *
* 0 ; 表示将数据成功的送至发送缓冲区 *
* 1 ; 表示上一次的数据正在发送, *
* ; 表示发送缓冲区被锁定,不能写入数据 *
* ; 表示写入数据错误 *
*说明: 将待发送特定帧各式的数据,送入SJA1000发送缓存区中,然后启动 *
* SJA1000发送。 *
* 特定帧格式为:开始的两个字节存放 '描述符' ,以后的为数据 *
* 描述符包括11位长的ID(标志符)\1位RTR\4位描述数据长度的DLC共16位 *
* *
*注:本函数的返回值仅指示,将数据正确写入SJA1000发送缓存区中与否。 *
* 不指示SJA1000将该数据正确发送到CAN总线上完毕与否 *
***********************************************************************
*/
bit BCAN_DATA_WRITE(unsigned char *SendDataBuf)
{
bit flag=1;
unsigned char idata len,i;
if((ReadDataFromSJA1000(REG_CAN_SR) &0x10) == 0)//SR.4=0,空闲; #define REG_CAN_SR 0x02 //状态寄存器
{
if((ReadDataFromSJA1000(REG_CAN_SR) &0x08) != 0)//SR.3=0,未完;当前请求的发送未处理完
//SR.3=1,完毕;最后一次发送已被成功处理
{
if((ReadDataFromSJA1000(REG_CAN_SR) &0x04) != 0)//Trans Buffer is released
//SR.2=0,锁定;CPU不能访问发送缓冲器;SR.2=1,释放;CPU可以向发送缓冲器中写信息
{
if((SendDataBuf[0]&0x40)==0)
{
len=SendDataBuf[0]&0x0f;
if(len>8)
{
len=8;
}
len += 5;
}
else
{
len=5;
}
for(i=0;i<len;i++)
{
WriteDataToSJA1000(REG_CAN_TXFMINFO+i, SendDataBuf[i]);
}
flag = 0;
}//1
}
}
return flag;
}
/*
***********************************************************************
*函数原型: bit BCAN_DATA_RECEIVE(unsigned char *RcvDataBuf); *
*参数说明: RcvDataBuf,存放微处理器保存数据缓冲区 *
*返回值: 0;接收成功 *
* 1;接收失败 *
*说明:CAN控制器接收数据,仅限于接收数据 *
***********************************************************************
*/
bit BCAN_DATA_RECEIVE(unsigned char *RcvDataBuf,unsigned char *pLen)
{
bit flag=1;
unsigned char len=0,i=0;
if((ReadDataFromSJA1000(REG_CAN_SR)&0x01) !=0) //SR.0=1,满;RXFIFO(接受缓冲器)中有可用信息 SR.0=0,空;无可用信息
{
//if(1)
if((ReadDataFromSJA1000(REG_CAN_RXFMINFO)&0x40)==0) //非扩展幀
{
len=ReadDataFromSJA1000(REG_CAN_RXFMINFO)&0x0f;
len=8;
if(len>8)
{
len=8;
}
len += 5;
}
else
{
len = 5;
}
*pLen = len;
for(i=0;i<len;i++)
{
RcvDataBuf[i]=ReadDataFromSJA1000(REG_CAN_RXFMINFO+i); //从第16个寄存器开始读数据
// delay(100);
}
flag=0;
}
return flag;
}
/************************************************************************
*函数原型: bit BCAN_CMD_PRG(unsigned char cmd) *
*参数说明: cmd:sja1000运行的命令字 *
* 01:发送请求 *
* 02:中止发送 *
* 04:释放接收缓冲区 *
* 08:清除超载状态 *
* 0x10:进入睡眠状态 *
* *
*返回值: *
* 0 ; 表示命令执行成功 *
* 1 ; 表示命令执行失败 *
* *
*说明: 执行sja1000命令 *
************************************************************************/
bit BCAN_CMD_PRG(unsigned char cmd)
{
bit flag=1;
switch(cmd)
{
case TR_BIT: //发送请求命令
case AT_BIT: //夭折发送命令
case RRB_BIT: //释放接收缓冲区
case CDO_BIT: //清除超载状态
case SRR_BIT: //进入睡眠状态命令
flag=0;
break;
default:
break;
}
if(!flag)
{
WriteDataToSJA1000(REG_CAN_CMR, cmd);
}
return flag;
}
/*************************************************************************************************************************
**函数原型: void SJASendData(unsigned char *databuf,
** unsigned char cmd
** )
**参数说明: databuf 存放要发送到总线的特定帧格式的数据的缓冲区首地址
** cmd 发送命令
**返回值:
**说明: 本函数用于向can总线发送数据
************************************************************************************************************************
*/
bit SJASendData(unsigned char *databuf,
unsigned char cmd
)
{
if(BCAN_DATA_WRITE(databuf) == 0)
{
BCAN_CMD_PRG(cmd);
return 0;
}
else
return 1;
}
/*************************************************************************************************************************
**函数原型: void SJARcvData(unsigned char *databuf)
**参数说明: databuf 存放要接收数据缓冲区首地址
**
**返回值:
**说明: 本函数用于接收can总线数据
************************************************************************************************************************
*/
bit SJARcvData(unsigned char *databuf,unsigned char *pLen)
{
unsigned char nLen = 0;
unsigned char flag ;
flag = BCAN_DATA_RECEIVE(databuf,&nLen);
*pLen = nLen;
if(flag == 0)
{
BCAN_CMD_PRG(RRB_BIT);
return 0;
}
else
return 1;
}
/*************************************************************************************************************************
**函数原型: void SJA1000(void) interrupt 1
**参数说明:
**
**返回值:
**说明: 本函数是中断函数,应用于can中断
************************************************************************************************************************
*/
void SJA1000(void) interrupt 1 //can总线上有数据进来
{
unsigned char rcanlen;
unsigned char rlen_t;
debug = 0x02;
putbytes(&debug,1);
flag = SJARcvData(canbuf,&rcanlen);
if(rcanlen < 13)
return; //13位为扩展帧
putbytes(canbuf,rcanlen); //串口发送数据
}
/*
/*************************************************************************************************************************
**函数原型: void InitCanBuffer(void)
**参数说明:
**
**返回值:
**说明: 本函数是初始化can数据缓冲区
************************************************************************************************************************
*/
/* void InitCanBuffer(void) //CAN数据缓冲区初始化
{
inTxBufCan = TxBufCan; outTxBufCan = TxBufCan; //CAN数据缓冲区初始化 TxBufCan[LenTxBufCan],RxBufCan[LenRxBufCan];
inRxBufCan = RxBufCan; outRxBufCan = RxBufCan;
}
*/
/*************************************************************************************************************************
**函数原型: unsigned char ReceivedBytesCan(void)
**参数说明:
**
**返回值:
**说明: 本函数是得出can接收数据的长度
************************************************************************************************************************
*/
/*
unsigned char ReceivedBytesCan(void) //判断串口缓冲区是否为空,若为空返回0,否则返回缓冲区字节数
{
char lenCan;
lenCan=inRxBufCan-outRxBufCan;
if(lenCan<0)
lenCan+=LenRxBufCan;
return lenCan;
}
*/
//#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -