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

📄 canjishou.c

📁 这是我前一段开发CAN总线通讯时编写的CAN测试程序
💻 C
字号:
/*中断方式接收CAN数据*/



#include<reg52.h>
#include<intrins.h>
#include    "SJA100REG.H"

sfr			   CKCON=0xb6;		   //定义时钟控制寄存器
sfr			   IPH=0xb7;           //中断器优先级高位
sbit RST_SJA1000=P1^7;//SJA1000硬件复位
sbit CS_SJA1000= P2^7;//片选信号


sbit SHANGDIAN_ID1= P1^3;//
sbit STATE_ID2= P1^4;//
sbit STATE_ID3= P1^5;//
sbit STATE_ID4= P1^6;//
sbit LED0= P1^0;//
sbit LED1= P1^1;//
sbit LED2= P1^2;//

unsigned char TIME_counter=0;
unsigned char TIME_counter1=0;
unsigned char TIME_counter2=0;
unsigned char counter=0;

unsigned char  BTR0,BTR1;
//unsigned    char	xdata	CAN_SJA_BaseAdr	_at_ 0x7f00;    			//定义SJA1000的片选基址
#define         CAN_SJA_BaseAdr       0x7f00     //定义sja1000的片选基址

unsigned   	char    xdata   *SJA_CS_Point ; 							//指针指向空
unsigned char Send_CAN_Filter[8]={0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff};//验收及屏蔽数据
//unsigned char Send_CAN_Filter[8]={0x07,0x80,0x07,0xF7,0xE0,0x00,0xE0,0x00};//验收及屏蔽数据  /此数据是根据已知四个
                            											   //四个PGN定义的,如果再加,还得变化
unsigned char Rev_CAN_data[13];          //07 f7 88 00CAN总线通讯接受存储单元
unsigned char Rev_COM_data[13]={0x88,0x07,0xF7,0x88,0x00,0x11,0x01,0x66,0x55,0x44,0x33,0x22,0x11};		  //串口通讯接受存储单元
unsigned char Signal_Stor_data[6];//要传给串口需要上传的信息 ,0 1字节    速度、
                                      //  2字节状态信号 ,BIT4上电 BIT3状态4 BIT2状态3 BIT1状态2 BIT0刹车
									  //  3  4字节  发动机转速。
									  //  5  6字节 水温
//unsigned char Extand_Stor_ID[10];//0存放可选信号的状态(需要采哪些信号1需要,0不需要)
                                       //1字节存可选信号的类型(CAN没有固定的,看是用CAN采1,还是脉冲采0)
									   //2 3字节存状态1信号的ID  上电信号
									   //4 5字节存状态2信号的ID
									   //6 7字节存状态3信号的ID
									   //8 9字节存状态4信号的ID

bit CAN_INT_bz=0;   //看有无报文
bit Com_Begin_bz=0;   //串口数据开始接受
//bit error_bz=0;
bit txcs_bz=0;      //串口通讯超时标志
bit ID_Config_bz=0; //ID初始化标志,进入正常通讯之后还要判断是否进行过了上电初始化。


/*
void	Delay_ms(unsigned char j)
{
  	unsigned char	k,l;
  	for(l=0;l<=j;l++)
	{
		for(k=0;k<=250;k++)
	 	{ 
	   		; 
	 	}
	}
}
------------------------------------------------------------------------------------------------------*/
/*硬件复位SJA1000*/
void SJA1000_HardwareRst(void)
     { RST_SJA1000=0;
	  // Delay_ms(50);
	  // Delay_ms(50);
	  // Delay_ms(50);
	  // RST_SJA1000=1;
	  // Delay_ms(50);
	  // Delay_ms(50);
	  // Delay_ms(10);
	   RST_SJA1000=0;
	   }


/*--------------------------------------------------------------------------------------------------------
** 函数原型:	unsigned char   SJAEntryResetMode(void)
** 功能描述:	该函数用于使sja1000进入复位模式
** 参数说明:	无                                                         
** 返回值:    	1			表示SJA1000进入复位模式成功
**				0			表示SJA1000进入复位模式失败

/*------------------------------------------------------------------------------------------------------*/
 bit  SJAEntryResetMode(void)
 {
    unsigned   char   TempData;
    SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_MOD;                   //访问地址指向控制寄存器 
    TempData=  *SJA_CS_Point;                      //保存原始值
    *SJA_CS_Point=(TempData|0x01);                 //置位复位请求
	_nop_();
	_nop_();
    if((*SJA_CS_Point&0x01) == 1)
    {
       return   0;
    }
    else
    {
       return   1;
    }
    
 }

 /*--------------------------------------------------------------------------------------------------------
** 函数原型:	unsigned char   SJAQuitResetMode(void)
** 功能描述:	该函数用于使sja1000退出复位模式,进入工作模式
** 参数说明:	无                                                         
** 返回值:    	1			表示SJA1000退出复位模式成功
**				0			表示SJA1000退出复位模式失败

/*------------------------------------------------------------------------------------------------------*/
bit  SJAQuitResetMode(void)
{
    unsigned   char   TempData;
    SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_MOD;                   //
    TempData=  *SJA_CS_Point;                      //保存原始值
    *SJA_CS_Point=(TempData&0xfe);                 //释放复位请求
	_nop_();
	_nop_();
    if((*SJA_CS_Point&0x01) == 0)
    {
       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			写入不正确

/*------------------------------------------------------------------------------------------------------*/
  WriteSJARegBlock(unsigned char RegAdr,unsigned char *ValueBuf,unsigned char len)
  {	unsigned   char   TempData;
    	for(TempData=0;TempData<len;TempData++)
	 	{ SJA_CS_Point  = CAN_SJA_BaseAdr+RegAdr+TempData;                   // 
         *SJA_CS_Point  = ValueBuf[TempData];
	 	} 
  }


/*--------------------------------------------------------------------------------------------------------
** 函数原型:	   WriteSJAReg(unsigned char RegAdr,unsigned char  Value)
** 功能描述:	该函数用于将指定的数值写入sja1000的指定的寄存器
** 参数说明:	RegAdr		要读的sja1000的内部寄存器地址 
**				Value  		写入寄存器的值                                             
** 返回值:    	1			写入正确
**				0			写入不正确
/*------------------------------------------------------------------------------------------------------*/
 bit WriteSJAReg(unsigned char RegAdr,unsigned char Value)
{
    
    SJA_CS_Point  = CAN_SJA_BaseAdr+RegAdr;                   //
    *SJA_CS_Point =(*SJA_CS_Point|Value);
	 _nop_();
	 _nop_();
     if(*SJA_CS_Point ==(*SJA_CS_Point|Value))
    {
       return   0;
    }
    else
    {
       return   1;
    }
   
 }
  /*--------------------------------------------------------------------------------------------------------
** 函数原型:	   WriteSJAReg(unsigned char RegAdr,unsigned char  Value)
** 功能描述:	该函数用于将指定的数值写入sja1000的指定的寄存器
** 参数说明:	RegAdr		要读的sja1000的内部寄存器地址 
**				Value  		写入寄存器的值                                             
** 返回值:    	1			写入正确
**				0			写入不正确
适合于向内部寄存器中某存储单元写数据。写入的是一个字节
/*------------------------------------------------------------------------------------------------------*/
 bit WriteSJARegByte(unsigned char RegAdr,unsigned char Value)
{
    
    SJA_CS_Point  = CAN_SJA_BaseAdr+RegAdr;                   //
    *SJA_CS_Point =Value;
	 _nop_();
	 _nop_();
     if(*SJA_CS_Point ==Value)
    {
       return   0;
    }
    else
    {
       return   1;
    }
   
 }

   /*串口发送子程序
void Comout(unsigned char OutData)
 {  
   EA=0;
   SBUF = OutData; //输出字符
   while(!TI); //空语句判断字符是否发完
   TI = 0; //清TI
   EA=1;
  }  */

    /*-------------------------------------------------------------------------------------------------------- 
** 函数原型:	void 	SJA1000_Config_Normal(void)                                                
** 功能描述:	对SJA1000的正常模式的初始化配置                                               
** 参数说明:	无                                                                               
** 返回值:    	无                                                                                 
/*------------------------------------------------------------------------------------------------------*/ 
void SJA1000_Config_Normal(void)													//正常模式的初始化
  { bit SJAReg_bz=1;
	BTR0=0x01;
    BTR1=0x1c;	                                                        //设置为250kb波特率通信
	 																	
	while(SJAReg_bz)
	     {SJAReg_bz=WriteSJARegByte(REG_CAN_TEST,0xaa);}                   //测试接口
		 //SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_TEST;      
		 //Comout(*SJA_CS_Point);
	SJAReg_bz=1;
	while(SJAReg_bz)
	     {SJAReg_bz=WriteSJARegByte(REG_CAN_TEST,0x55);} 
		 //SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_TEST;      
		 //Comout(*SJA_CS_Point);
    SJAReg_bz=1;
	while(SJAReg_bz)
	     {SJAReg_bz=SJAEntryResetMode();}                                //进入复位模式
		 //SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_MOD;      
		 //Comout(*SJA_CS_Point);  	                                              
	WriteSJARegByte(REG_CAN_CDR,0xc8);						                //配置时钟分频寄存器,选择PeliCAN模式 	
	SJAReg_bz=1;
	while(SJAReg_bz)
	     {SJAReg_bz=WriteSJAReg(REG_CAN_MOD,0x01);}						//配置模式寄存器,选择双滤波、正常模式 
	WriteSJARegBlock(16,Send_CAN_Filter,8);								//配置验收代码/屏蔽寄存器                        
	SJAReg_bz=1;
	while(SJAReg_bz)
	     {SJAReg_bz=WriteSJARegByte(REG_CAN_BTR0,BTR0);}					//配置总线定时器0 
		 //SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_BTR0;      
		// Comout(*SJA_CS_Point);                          
	SJAReg_bz=1;
	while(SJAReg_bz)
	     {SJAReg_bz=WriteSJARegByte(REG_CAN_BTR1,BTR1);}					//配置总线定时器1 
		 //SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_BTR1;      
		// Comout(*SJA_CS_Point);                           
	WriteSJARegByte(REG_CAN_OCR,0x1a);										//配置输出管脚 
	     //SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_OCR;      
		// Comout(*SJA_CS_Point);    	
	SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_TXERR;	   //清发送错误计数寄存器.
	*SJA_CS_Point = 0;
	SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_ECC;       // 错误代码捕捉寄存器
	TIME_counter  =  *SJA_CS_Point;
	TIME_counter=0;                                   //清除错误代码捕捉寄存器   
	SJAReg_bz=1;
	while(SJAReg_bz)
	     {SJAReg_bz=SJAQuitResetMode();}							   //退出复位模式,进入工作模式
	     //SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_MOD;      
		 // Comout(*SJA_CS_Point);	                               
  }
/*------------------------------------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------------------------------*/


main()
 { 	
	
	//CKCON=0x04;
	IP=1;
	IPH=1;
	TMOD=0x21;	  //   定时器T0为方式1,T1为方式2
 	TH0=0x00;
 	TL0=0x00;	  //定时器0设置,暂时先开开,可能用不上
	TR0=1;
	ET0=1;
	TH1=0x00;
 	TL1=0x00;	  //定时器1设置,暂时先开开,可能用不上
	TR1=1;
	ET1=1;
	RCLK=1;
	TCLK=1;        //定时器2用作波特率发生器   T2CON中的值
	RCAP2H=0xff;
	//RCAP2L=0xB8;   //初步设定波特率为9600
	RCAP2L=0xDC;   //初步设定波特率为19200
	 //RCAP2L=0xEE; 	  //jiabei

	SCON=0x50;     //串口方式为模式1,无校验,定时器2产生波特率 
	TR2=1;        //开定时器2
	//ET2=1;		  //使能定时器2
	IT0=1;       //		负边缘触发
	//EX0=1;         //外部中断使能 
	ES=1;          //使能串口  
   //	EA=1; 
	CS_SJA1000=0;//开片选信号
	 _nop_();
	 _nop_();
	 _nop_();
	 _nop_();
	 _nop_();
	 _nop_();	
//	SJA_CS_Point=CAN_SJA_BaseAdr;										//确定基址指针的值
	SJA1000_HardwareRst();
	SJA1000_Config_Normal();											//调用SJA1000初始化配置函数
    //WriteSJAReg(REG_CAN_IER,RIE_BIT);               					//使能SJA1000jieshou中断
	EX0=1;																//打开INT0中断
	EA=1;
 
  while (1)
   { 
   
   																//使能MCU总中断	
	/*if( CAN_INT_bz==1)
	 { 
	    unsigned   char   j;
		//EA=0;	
	    CAN_INT_bz=0;
		LED0=!LED0;
	    for(j=0;j<13;j++)
	       { 
	        Comout(Rev_CAN_data[j]);
			Rev_CAN_data[j]=0;
		    }
	   //EA=1;
	   }*/
	  if(counter>=1)
	    {
		counter=0;
		Rev_COM_data[7]++;
	   SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_SR;
	   if((*SJA_CS_Point&0x04) == TBS_BIT)  
		  {  unsigned   char   j;
		          for(j=0;j<13;j++)                             //开始将接收到的TempData个字节的数据存到CPU的数据缓冲区里
				     {
					   SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_RXFMINFO+j;    
                         *SJA_CS_Point=Rev_COM_data[j];
					    
				      }
		   SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_CMR; 
		   *SJA_CS_Point = TR_BIT;
			}
	   }
    }
  }

 /*  void CAN(void) interrupt 0	using 0
     {   LED1=!LED1; 
	   SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_IR;
	   while((*SJA_CS_Point&0x01) == RI_BIT)
	        {  unsigned   char j;  //TempData,j;
			    //  TempData=*SJA_CS_Point&0x0F;		 //取数据字节数目   
			   	//TempData=TempData+0x04;             //ID29位加上数据的字节数   ,不用要信息帧。	
			     
				  for(j=0;j<13;j++)                             //开始将接收到的TempData个字节的数据存到CPU的数据缓冲区里
				     {
					   SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_RXFMINFO+j;    
                       Rev_CAN_data[j] = *SJA_CS_Point;
				      }
				  SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_CMR;      //释放接收缓冲区,可以直接接收了
		         *SJA_CS_Point = RRB_BIT;
				  CAN_INT_bz=1;
		    }
	   }
  */
 
void Timer0() interrupt 1 using 1   //主要作用是定时当一定时间到了可以检测应该完成的任务完成了么
{
    TH0 = 0x99;
    TL0 = 0x99;
    TIME_counter++;
	counter++;
	if(TIME_counter>=10)
	{
	   TIME_counter=0;
	   LED2=!LED2;
	 }   
	    
}
void Timer1() interrupt 3 using 2
  {
  TH1 = 0X00;
    
  TL1 = 0x00;
    TIME_counter1++;
	TIME_counter2++;
	if(TIME_counter1>=254)
	{
	   TIME_counter1=0;
	   //STATE_ID4=!STATE_ID4;
	 }
  }

⌨️ 快捷键说明

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