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

📄 stepbystep.c

📁 SJA1000_CAN协议,目前该通信协议主要应用于汽车方面,它具有较好的稳定性和纠错能力.
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <Reg52.h>
#include <SJA1000.h>

void init_port();//初始开I/O口
void init_cpu();
void INIT_SJA1000();
void INIT_SJA1000_CYC();
void MCU_SENT_TO_CAN();
void SJA1000_SEND();
void SJA1000_RECEIVE();
void SetBaund();
void URT_SENT();		//URT SENT
//void URT_SENDIN();
void SJA1000_RECEIVE();
//void SJA1000_RECEIVE_IN_INTERR();
void checklink();
//void checkbound();
unsigned char wait_data();
//void changebound();
void delay();

sbit S_MODE=P1^1;
sbit LED1=P1^2;
sbit LED2=P1^3;

unsigned char CAN_RXD_BUF[13];
unsigned char CAN_TXD_BUF[13];		 
unsigned char r_buf[15];	//URT RECEIVE BUFFER
unsigned char t_buf[15];	//URT SEND BUFFER
unsigned char temp,can_temp,i,m,count_time,can_length,j,k,l,receive_count,BTR0_NUM,BTR1_NUM;

bit URT_RECEIVE=0,link=0,UTR_SENDING=0,URT_SENDING=0;

bit receive_err=0,receive_succeed=0,setbound=0;
bit send_comply=0,baund=0;

void main(void)
{
	init_cpu();
	init_port();
	TJA1050_CLOSE;
	INIT_SJA1000();
	TJA1050_WORK;
	SetBaund();
	EX0=1;
/*	BTR0_NUM=BTR0_500Kbps;
	BTR1_NUM=BTR1_500Kbps;	 */
	ES=1;
	i=0;
	REN=1;
	m=0;
	IT0=1;
	EA=1;
	while(1)
		{
				LED1=0;
				while(!wait_data());
				LED1=1;
				checklink();
//				checkbound();
				if(link)
				{
						URT_SENT();
						LED1=0;
						for(i=0;i<14;i++)
						{
							r_buf[i]=0;
						}
						i=0;
						LED1=1;
						goto loop;
						               
				}
/*				else if(baund)
					{
						URT_SENT();	
						BTR0_NUM=r_buf[5];
						BTR1_NUM=r_buf[6];
					    changebound();							   	
						for(i=0;i<14;i++)
						{
							r_buf[i]=0;
						}
						i=0;
						P2=0x69;
						goto loop;
					}	 */
					else
						{
							LED2=0;
							EX0=1;
							INIT_SJA1000_CYC();
							TJA1050_WORK;
							receive_err=0;
							MCU_SENT_TO_CAN();
							REN=0;
							ES=0;
							EA=1;
							LED2=0;
							while(!receive_err);
							receive_err=0;
							SJA1000_RECEIVE();
							EA=0;
							if(receive_succeed)
							{
								r_buf[0]=can_length+1;
								for(i=0;i<can_length;i++)
								{
									r_buf[i+1]=CAN_RXD_BUF[i];
								}
				/*				for(i=0;i<14;i++)
								{
									 P2=r_buf[i];
									 for(j=0;j<255;j++)
									 	for(k=0;k<255;k++)
											for(l=0;l<4;l++)
												;
								}			 */
									ES=1;
							i=0;
							REN=1;
							m=0;
							IT0=1;
							EA=1;	 
								URT_SENT();
							}
						}	  
loop:		link=0;
			receive_err=0;
//			init_cpu();
//			init_port();
			SetBaund();		   
			EX0=1;
			ES=1;
			REN=1;
			IT0=1;
			EA=1;
			TJA1050_CLOSE;
			}
}	

void init_port()
{
	 P0=0x00;
	 P1=0xff;
	 LED1=0;
	 LED2=0;
	 delay();
	 LED1=1;
	 LED2=1;
//	 P2=0xFE;
}

void delay()
{
	unsigned char i,j,k;
	for(i=0;i<255;i++)
		for(j=0;j<255;j++)
			for(k=0;k<5;k++)
				;;
}

void init_cpu()
{
	ES=0;
	EX0=1;
	TMOD=0x00;
	REN=0;
	IT0=1;
	TL0=0;
	TH0=0;
	TR0=0;
	EA=0;
}

void INIT_SJA1000()           /*initSJA1000*/
{
      SJA1000_ADDRESS=SJA1000_MODEL;	              //指向模式寄存器
      *SJA1000_ADDRESS=SJA1000_RESET_MODEL;           //进入复位模式
       
      while(!(*SJA1000_ADDRESS&SJA1000_RESET_MODEL)); //等待进入复位模式
      
      SJA1000_ADDRESS=SJA1000_CLOCKDIR;	              //指向时钟分频寄存器 
      *SJA1000_ADDRESS=SJA1000_CDR_COMMAND;           //使用Peli CAN模式,CLOCK使用2分频输出
      
      SJA1000_ADDRESS=SJA1000_ENINTERR;	              //指向中断使能寄存器 
      *SJA1000_ADDRESS=SJA1000_IER_COMMAND;           //开放接收,数据溢出,错误报警中断
     
      SJA1000_ADDRESS=SJA1000_OUTCONTR;               //指向输出控制寄存器
      *SJA1000_ADDRESS=SJA1000_OUT_COMMAND;           //正常输出模式
      
      SJA1000_ADDRESS=SJA1000_BUSTIME0;              //指向总线定时0寄存器
      *SJA1000_ADDRESS=0x01;                 	 	//选择500Kbps
      SJA1000_ADDRESS=SJA1000_BUSTIME1;              //指向总线定时1寄存器 
      *SJA1000_ADDRESS=0x05;                  		//选择500Kbps
      
      SJA1000_ADDRESS=SJA1000_RBSA;                  //指向RX缓冲区起始地址寄存器
      *SJA1000_ADDRESS=SJA1000_FIFO_ADD;             //接收缓冲区FIFO起始为内部RAM的0地址
      
      SJA1000_ADDRESS=SJA1000_AMRRX0;                //指向验收屏蔽寄存器,所有位均参加验收
      *SJA1000_ADDRESS=0x18;
      SJA1000_ADDRESS=SJA1000_AMRRX1;
      *SJA1000_ADDRESS=0x2f;
      SJA1000_ADDRESS=SJA1000_AMRRX2;
      *SJA1000_ADDRESS=AMR_CODE2;
      SJA1000_ADDRESS=SJA1000_AMRRX3;
      *SJA1000_ADDRESS=AMR_CODE3;  
      
      SJA1000_ADDRESS=SJA1000_ACRRX0;                //指向验收代码寄存器,送ID码
      *SJA1000_ADDRESS=0xfd;
      SJA1000_ADDRESS=SJA1000_ACRRX1;
      *SJA1000_ADDRESS=0x00; 
      SJA1000_ADDRESS=SJA1000_ACRRX2;
      *SJA1000_ADDRESS=ACR_ID2; 
      SJA1000_ADDRESS=SJA1000_ACRRX3;
      *SJA1000_ADDRESS=ACR_ID3; 
      
      SJA1000_ADDRESS=SJA1000_TX_ERR;                //指向发送错误寄存器   
      *SJA1000_ADDRESS=SJA1000_CLEAR_TX_ERR;         //清除错误

      SJA1000_ADDRESS=SJA1000_RX_ERR;                //指向发送错误寄存器   
      *SJA1000_ADDRESS=SJA1000_CLEAR_TX_ERR;         //清除发送错误
      
      SJA1000_ADDRESS=SJA1000_ALC;                   //指向仲裁丢失捕捉寄存器
      temp=*SJA1000_ADDRESS;                         //通过读取清除
      
      SJA1000_ADDRESS=SJA1000_ECC;                   //指向错误代码捕捉寄存器
      temp=*SJA1000_ADDRESS;                         //通过读取清除

      
      SJA1000_ADDRESS=SJA1000_MODEL;	             //指向模式寄存器
      *SJA1000_ADDRESS=SJA1000_WORK_MODEL;           //设置双滤波接收,进入工作模式
      while(*SJA1000_ADDRESS&SJA1000_RESET_MODEL);   //等待进入工作模式          
}

void SJA1000_SEND()
{
	   LED2=0;;	

       SJA1000_ADDRESS=SJA1000_STATE;        //指向状态寄存器
       temp=*SJA1000_ADDRESS;

      do
        {
         temp=*SJA1000_ADDRESS;               //读出当前状态	
        }
      while(temp&SJA1000_RECEIVING);          //如正在接收,则等待	 
         
		do
		{ 
		 temp=*SJA1000_ADDRESS;               //读出当前状态
		}while(!(temp&SJA1000_SENT_OVER));	  //如正在发送,则等待
			     	   
      do
        {
         SJA1000_ADDRESS=SJA1000_STATE;
		 temp=*SJA1000_ADDRESS;               //读出当前状态	
        }		   
      while(!(temp&SJA1000_SENT_LOCK));       //如发送缓冲区被锁定,则等待释放        

	     SJA1000_ADDRESS=SJA1000_TXBUF;
     for(j=0;j<11;j++)                            //发送到CAN缓冲区
        {
         *(SJA1000_ADDRESS+j)=CAN_TXD_BUF[j];   
        }
     SJA1000_ADDRESS=SJA1000_COMMAND;             //指向命令寄存器
     *SJA1000_ADDRESS=SJA1000_SENT_COMMAND;       //发送请求命令
	 LED2=1;
}

void sja1000_receiving () interrupt 0 using 0
{
	receive_err=1;
//	SJA1000_RECEIVE_IN_INTERR();
	return;
}

void SJA1000_RECEIVE()
{
	  unsigned char data can_temp,j,k,Length;
	  bit FF,RTR;
     	 
      receive_err=0;
	  LED2=0;;	

	  	SJA1000_ADDRESS=SJA1000_STATE;                       //指向状态寄存器
      	can_temp=*SJA1000_ADDRESS;	           //读状态

	  if(can_temp&SJA1000_BUS_ERR)  //0xc3                        //检查总线状态是否有错
        {
         if(can_temp&SJA1000_BUS_CLOSE)  //0x80                  //检查是否是总线关闭状态
           {          	
            SJA1000_ADDRESS=SJA1000_INTERR;                //读中断寄存器,清除总线错误中断
            can_temp=*SJA1000_ADDRESS;
			for(k=0;k<255;k++)
				for(j=0;j<255;j++)
					;
					;
			k=0;
			j=0;       
            SJA1000_ADDRESS=SJA1000_MODEL;                 //指向模式寄存器
            *SJA1000_ADDRESS=SJA1000_WORK_MODEL;           //设置双滤波接收,进入工作模式
            while(*SJA1000_ADDRESS&SJA1000_RESET_MODEL);    //等待进入工作模式
           }
         else
             {
              SJA1000_ADDRESS=SJA1000_INTERR;              //读中断寄存器,检查中断类型
              can_temp=*SJA1000_ADDRESS;
			  

              if(can_temp&SJA1000_DATA_OVER_INTERR) //0x08       //检查是否是数据溢出中断      
                {
                 SJA1000_ADDRESS=SJA1000_COMMAND;          //指向命令寄存器
                 *SJA1000_ADDRESS=SJA1000_CLEAR_DATA_OVER; //清除数据溢出               
                }
              else
                  { 
					if(can_temp&SJA1000_RI_INTERR)          //检查是否是接收中断      
                     {
                      	SJA1000_ADDRESS=SJA1000_RXBUF;       //指向接收数据寄存器首址
                      	CAN_RXD_BUF[0]=*SJA1000_ADDRESS;           //读RX帧信息 

						FF=CAN_RXD_BUF[0]&0x80;					  //格式
					  	RTR=CAN_RXD_BUF[0]&0x40;				  //远程?
					  	Length=CAN_RXD_BUF[0]&0x0F;				  //长度
					  	if(Length>0x08)
					  		Length=0x08;
					  	SJA1000_ADDRESS++;
					  	CAN_RXD_BUF[1]=*SJA1000_ADDRESS;

					  	SJA1000_ADDRESS++;
					  	CAN_RXD_BUF[2]=*SJA1000_ADDRESS;

					  	if(FF)
					  	{
							SJA1000_ADDRESS++;
							CAN_RXD_BUF[3]=*SJA1000_ADDRESS;
							SJA1000_ADDRESS++;
							CAN_RXD_BUF[4]=*SJA1000_ADDRESS;
						}                
					  	for(i=0;i<Length;i++)
					  	{
					  		if(FF)
							{
								SJA1000_ADDRESS++;
								CAN_RXD_BUF[i+5]=*SJA1000_ADDRESS;
							}
							else
							{
								SJA1000_ADDRESS++;
								CAN_RXD_BUF[i+3]=*SJA1000_ADDRESS;
							}
					  	}
						if(FF)
						{
							can_length=Length+5;
						}
						else
						{
							can_length=Length+3;
						} 
						     
                      	SJA1000_ADDRESS=SJA1000_COMMAND;          //指向命令寄存器 
                      	*SJA1000_ADDRESS=SJA1000_RELEASE_FIFO;    //释放接收缓冲器
							receive_succeed=1;   
                     	if(RTR)					  
                        	receive_succeed=1;                      //置接收成功标志
                     }
					 else
					 {
					  	receive_succeed=0;
					  	SJA1000_ADDRESS=SJA1000_COMMAND;          //指向命令寄存器
                      	*SJA1000_ADDRESS=SJA1000_RELEASE_FIFO;    //释放接收缓冲区
                      	SJA1000_ADDRESS=SJA1000_ALC;	        //指向仲裁丢失寄存器

⌨️ 快捷键说明

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