⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 canbus.c

📁 单片机实现CAN总线
💻 C
字号:
#include<reg51.h>
#include<SJA1000REG.h>
#define uchar unsigned char

unsigned char Send_CAN_Filter[8]={0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff};
unsigned char  Send_CAN_Info_ID[5]={0x88,0x00,0x00,0x00,0x00};
unsigned char  BTR0,BTR1;
unsigned char Send_CAN_Data[8]={0x31,0x32,0x13,0x14,0x05,0x06,0x07,0x08};
unsigned char Rec_CAN_Filter[8]={0x00,0x0D,0x0C,0x0A,0x45,0x01,0x23,0x12};
unsigned char Rec_CAN_Data[8];
bit Send_Enable;
bit SJAQuitResetMode();
sbit SJA_RST=P2^5;//硬件复位信号
sbit SJA_CS=P2^7;//片选择
sbit SJA_MODE=P2^6;//模式选择
sbit INIT_ERR_LED=P1^1;//初始化错误指示。
sbit RST=P1^3;//硬件复位
uchar bdata EINT_flag=0x00;
sbit  Rec_flag=EINT_flag^0;
sbit Send_flag=EINT_flag^1;


/*****************************************************************************************************
/*************延时N ms******************************************** 
******************************************************************************************************/

void	delay_NMS(int j)
{
  int k,l;
  	for(l=0;l<=j;l++)
 		for(k=0;k<=250;k++); 
}

/*--------------------------------------------------------------------------------------------------------
** 函数原型:	unsigned char   ReadSJAReg(unsigned char RegAdr)
** 功能描述:	该函数用于读出sja1000的指定的寄存器
** 参数说明:	RegAdr	要读的sja1000的内部寄存器地址                                     
** 返回值:    	内部寄存器Reg的值
** 全局变量:
** 调用模块:
** 作 者:
** 日 期:
/*------------------------------------------------------------------------------------------------------*/
unsigned char  ReadSJAReg(unsigned char RegAdr)
{
    uchar tes,TES1,T;
	tes=RegAdr;
    T=*(SJA_CS_Point+RegAdr);
	delay_NMS(100);
    TES1=RegAdr;
	return T;
}
/*--------------------------------------------------------------------------------------------------------
** 函数原型:	unsigned char   WriteSJAReg(unsigned char RegAdr,unsigned char  Value)
** 功能描述:	该函数用于将指定的数值写入sja1000的指定的寄存器
** 参数说明:	RegAdr		要读的sja1000的内部寄存器地址 
**				Value  		写入寄存器的值                                             
** 返回值:    	0			写入正确
**				1			写入不正确
** 全局变量:
** 调用模块:
** 作 者:
** 日 期:
/*------------------------------------------------------------------------------------------------------*/
bit WriteSJAReg(unsigned char RegAdr,unsigned char Value)
{  
 
	*(SJA_CS_Point+RegAdr)=Value;
	if(*(SJA_CS_Point+RegAdr)==Value)
        return 0;
	else
       return 1;
}
/*--------------------------------------------------------------------------------------------------------
** 函数原型:	unsigned char   WriteSJARegBlock(unsigned char RegAdr,unsigned char  *ValueBuf,unsigned char len)
** 功能描述:	该函数用于将指定的数值写入sja1000的指定的寄存器
** 参数说明:	RegAdr		要写入的sja1000的内部寄存器地址 
**				ValueBuf	要写入寄存器的值 
**              len			要写入sja1000内部寄存器的长度                         
** 返回值:    	1			写入正确
**				0			写入不正确
** 全局变量:
** 调用模块:
** 作 者:
** 日 期:
/*------------------------------------------------------------------------------------------------------*/
bit WriteSJARegBlock(unsigned char RegAdr,unsigned char *ValueBuf,unsigned char len)  reentrant
{
	unsigned char i;
    uchar val0=0xff,val1=0xff,SR_VAL=0xff; 
	for(i=0;i<len;i++)
	{   
	    SR_VAL=*(SJA_CS_Point+2);
		*(SJA_CS_Point+RegAdr+i)=ValueBuf[i];  
  	    val0=ValueBuf[i];
		val1=*(SJA_CS_Point+RegAdr+i);
	}
	for(i=0;i<len;i++)
	{
		if(ValueBuf[i]!=*(SJA_CS_Point+RegAdr+i))
			return 1;			//当出现一个不相等就返回
	}
	return 0;	
}
/*--------------------------------------------------------------------------------------------------------
** 函数原型:	unsigned char ReadSJARegBlock(unsigned char RegAdr,unsigned char *ValueBuf,unsigned char len)
** 功能描述:	该函数用	于读一串寄存器的值
** 参数说明:	RegAdr		要读的sja1000的内部寄存器地址 
**				ValueBuf	要存储读出寄存器的值的存储器地址
**              len			要读出sja1000内部寄存器的长度                     
** 返回值:    	0			读出正确
**				1			读出不正确
** 全局变量:
** 调用模块:
** 作 者:
** 日 期:
/*------------------------------------------------------------------------------------------------------*/
bit ReadSJARegBlock(unsigned char RegAdr,unsigned char *ValueBuf,unsigned char len)
{
	unsigned char i;
	for(i=0;i<len;i++)
	{
		ValueBuf[i]=*(SJA_CS_Point+RegAdr+i);
	}
	for(i=0;i<len;i++)
	{
		if(ValueBuf[i]!=*(SJA_CS_Point+RegAdr+i))
			return 1;	//当出现一个不相等就返回		
	}
	return 0;
}
/**************************************************************************************************************
	进入复位模式
**************************************************************************************************************/
bit SJAEntryResetMode(void)
{
	unsigned char TempData;
	TempData=*SJA_CS_Point;
	*SJA_CS_Point=TempData|0x01;
	if((*SJA_CS_Point&0x01)==1)
		return 0;
	else
		return 1;
}
/**************************************************************************************************************
	进入复位模式
**************************************************************************************************************/
bit SJAQuitResetMode(void)
{
	unsigned char TempData;
	TempData=*SJA_CS_Point;
	*SJA_CS_Point=TempData&0xfe;
	if((*SJA_CS_Point&0x01)==1)
		return 1;
	else
		return 0;
}
/*----------------------------------------------------------------------------------------------------------------
**错误闪烁   
-------------------------------------------------------------------------------------------------------------------*/
void led(){
      uchar i;
	  for(i=0;i<4;i++){
      INIT_ERR_LED=0;
	  delay_NMS(200);
	  INIT_ERR_LED=1;
	  delay_NMS(200);
	  }
}
 


/*-----------------------------------------------------------------------------------------------------------------
**初始化函数
--------------------------------------------------------------------------------------------------------------------*/
void SJA1000_Config_Normal()													//正常模式的初始化
{    
	bit i;
	BTR0=0x00;
	BTR1=0x14;
	do{
	i=SJAEntryResetMode();										//进入复位模式                                  
	if(i)
		led();
	   }while(i);
	do{
	i=WriteSJAReg(REG_CAN_CDR,0xC8);										//配置时钟分频寄存器,选择PeliCAN模式
	if(i)
		led();
		}while(i);		
	do{
	i=WriteSJAReg(REG_CAN_MOD,0x05);										//配置模式寄存器,选择双滤波MOD.3=0、正常模式MOD.4=0,MOD.4=1自测模式    
      if(i)
    	led();
      }while(i);
	  do{
    i=WriteSJARegBlock(16,Send_CAN_Filter,8);								//配置验收代码/屏蔽寄存器 --------已经全部屏蔽                   
	if(i)
		led();
       }while(i);
	do{
	i=WriteSJAReg(REG_CAN_BTR0,BTR0);										//配置总线定时器0                      
	if(i)
		led();
	  }while(i);
	 do{
	i=WriteSJAReg(REG_CAN_BTR1,BTR1);									//配置总线定时器1                   
	if(i)
		led();
	  } while(i);
	 do{
	i=WriteSJAReg(REG_CAN_OCR,0x1a);									//配置输出管脚                        
	if(i)
		led();
		}while(i);
	 do{
	 i=SJAQuitResetMode();												//退出复位模式,进入工作模式                     
     led();
 	 }while(i);
	}
/*--------------------------------------------------------------------------------------------------------
**外部中断初始化
---------------------------------------------------------------------------------------------------------*/
void Init_Cpu( void )
{
  PX1=1;
  IT1=1;
  EX1=1;
  EA=1;
}
/*------------------------------------------------------------------------------------------------------
**串口初始化函数
--------------------------------------------------------------------------------------------------------*/
void UART_init(){
     SCON=0x50;//工作在方式1,允许接受?
     PCON=0x00;
     TMOD=0x20;//定时器1工作在方?2
     TH1=0xfd;
     TL1=0xfd;//实现数据传送速率9600bit/s 11.0592M系统时
     TR1=1;
    ES=1;
    PS=1;
    EA=1;
  }

/*------------------------------------------------------------------------------------------------------
**硬件复位函数
---------------------------------------------------------------------------------------------------------*/
void SJAHardwareReset(){
 RST=1;
 delay_NMS(500);
 RST=0;
 }
/*------------------------------------------------------------------------------------------------------
**接收中断
--------------------------------------------------------------------------------------------------------*/
void Receive_int() interrupt 2 using 2{
  uchar x;
  x=*(SJA_CS_Point+REG_CAN_IR);
  EINT_flag=x;
   }

/*----------------------------------------------------------------------------------------------------
**SJA1000发送函数
-----------------------------------------------------------------------------------------------------*/
void send()
{
	bit Send_Enable;
	unsigned char sr,i;

	sr=ReadSJAReg(2);
	if((sr&0x0C)==0x0C)
	    Send_Enable=1;
	else
		Send_Enable=0;
	if(Send_Enable==1)
	{
		//WriteSJARegBlock(21,Send_CAN_Data,8);
        for(i=0;i<8;i++){
		   *(SJA_CS_Point+21+i)=Send_CAN_Data[i];
		   }
       WriteSJAReg(REG_CAN_CMR,0x012);	//使能发送请求,产生字接收性质的发送
	   while(((ReadSJAReg(REG_CAN_SR))&0x08)!=0x08);
       

        //sr=ReadSJAReg(REG_CAN_IR);
		if((ReadSJAReg(REG_CAN_SR)&0x08)==0x08)						
			led();
		else
		{	
			delay_NMS(200);							    //延时200ms再判断
			if((ReadSJAReg(REG_CAN_IR)&0x08)!=0x08)		//发送失败,停止发送
				Send_Enable=0;
			else
				led();
		}
       



	delay_NMS(100);
      }

}
void UART_send(uchar dat){
  SBUF=dat;
  while(TI==0);
  TI=0;
}




void main(){

   uchar tes=0xff,i,tes1=0x55;
   uchar R_data[8];
   //bit test=0,;
   P1=0xff;       //熄灭指示灯
   RST=0;
   SJAHardwareReset();
   SJA_CS_Point=&CAN_SJA_BaseAdr;
   SJA1000_Config_Normal();	

   while(1){
    *(SJA_CS_Point)=0x21;
	 tes1=*(SJA_CS_Point);
	 *(SJA_CS_Point+16)=0x22;
	 tes=*(SJA_CS_Point+16);
     }


   Init_Cpu();
   Send_flag=0;
   Rec_flag=0;
   WriteSJAReg(REG_CAN_IER,0x01);      //0x01使能SJA1000接收中断位,0x02发送中断

   //  tes=ReadSJAReg(REG_CAN_IER);      //使能SJA1000发送中断位
   //WriteSJAReg(28,0x12);
   //WriteSJAReg(REG_CAN_CMR,1);	//使能发送请求
   //tes=ReadSJAReg(28);

   tes=ReadSJAReg(2);
   WriteSJAReg(REG_CAN_CMR,4);
   tes=ReadSJAReg(2);
   for(i=0;i<5;i++){                        //写识别码
      *(SJA_CS_Point+16+i)=Send_CAN_Info_ID[i];
	  }

      
 
    //tes1=ReadSJAReg(REG_CAN_IR);
//	tes=TCON;
    send();
    tes=ReadSJAReg(REG_CAN_IR);

 
     
 /*	WriteSJAReg(21,0x25);
	tes=ReadSJAReg(21);
    tes1=ReadSJAReg(REG_CAN_IR);//读取中断状态则INT变高
    WriteSJAReg(22,0x26);
 	tes=ReadSJAReg(22);*/

	while(1){
	   if(ReadSJAReg(REG_CAN_IR)&0x01==0x01){
	      R_data[0]=ReadSJAReg(21);
          R_data[1]=ReadSJAReg(23);
		  }
         }
     
   }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -