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

📄 canceshi.c

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



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

sbit RST_SJA1000=P1^7;//SJA1000硬件复位
sbit CS_SJA1000= P2^7;//片选信号

unsigned char  BTR0,BTR1;
unsigned    char	xdata	CAN_SJA_BaseAdr	_at_ 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[12];          //CAN总线通讯接受存储单元
unsigned char xdata Rev_COM_data[12];		  //串口通讯接受存储单元
unsigned char xdata Signal_Stor_data[6];//要传给串口需要上传的信息 ,0 1字节    速度、
                                      //  2字节状态信号 ,BIT4上电 BIT3状态4 BIT2状态3 BIT1状态2 BIT0刹车
									  //  3  4字节  发动机转速。
									  //  5  6字节 水温
unsigned char xdata 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(5);
	   Delay_ms(5);
	   Delay_ms(5);
	   RST_SJA1000=1;
	   Delay_ms(5);
	   }


/*--------------------------------------------------------------------------------------------------------
** 函数原型:	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 	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);}                   //测试接口
	SJAReg_bz=1;
	while(SJAReg_bz)
	     {SJAReg_bz=WriteSJARegByte(REG_CAN_TEST,0x55);} 
    SJAReg_bz=1;
	while(SJAReg_bz)
	     {SJAReg_bz=SJAEntryResetMode();}                                //进入复位模式  	                                              
	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                           
	SJAReg_bz=1;
	while(SJAReg_bz)
	     {SJAReg_bz=WriteSJARegByte(REG_CAN_BTR1,BTR1);}					//配置总线定时器1                            
	WriteSJARegByte(REG_CAN_OCR,0x1a);										//配置输出管脚                             
	SJAReg_bz=1;
	while(SJAReg_bz)
	     {SJAReg_bz=SJAQuitResetMode();}							   //退出复位模式,进入工作模式                              
  }
/*------------------------------------------------------------------------------------------------------*/



main()
 { 	//IP=1;
	//IPH=1;
	//TMOD=0x21;
 //	TH0=0x00;
 //	TL0=0x00;	  //定时器0设置,暂时先开开,可能用不上
//	TR0=1;
	//ET0=1;
	//RCLK=1;
	//TCLK=1;        //定时器2用作波特率发生器   T2CON中的值
	//RCAP2H=0xff;
	//RCAP2L=0xB8;   //初步设定波特率为9600
	//SCON=0x50;     //串口方式为模式1,无校验,定时器2产生波特率 
	//TR2=1;        //开定时器2
	//ES=1;          //使能串口 
 
  while (1)
   { 
    CS_SJA1000=0;//开片选信号
	_nop_();
	 _nop_();
	 _nop_();
	 _nop_();
	 _nop_();
	 _nop_();	
	SJA_CS_Point=&CAN_SJA_BaseAdr;		//确定基址指针的值
	SJA1000_HardwareRst();
	SJA1000_Config_Normal();			//调用SJA1000初始化配置函数

	SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_SR;
	while((*SJA_CS_Point&0x01) == RBS_BIT)
	    {  unsigned   char   TempData,j;
			      TempData=*SJA_CS_Point&0x0F;		 //取数据字节数目   
				  TempData=TempData+0x04;             //ID29位加上数据的字节数   ,不用要信息帧。	
			      for(j=0;j<TempData;j++)                             //开始将接收到的TempData个字节的数据存到CPU的数据缓冲区里
				     {
					   SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_TXBUF1+j;    
                       Rev_CAN_data[j] = *SJA_CS_Point; 
				      }
				  SJA_CS_Point  = CAN_SJA_BaseAdr+REG_CAN_CMR;      //释放接收缓冲区,可以直接接收了
		          *SJA_CS_Point = RRB_BIT;
		  }
    }
  }

⌨️ 快捷键说明

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