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

📄 can_sja1000.c

📁 开发环境为GCC,AVR单片机与SJA1000实现CAN通讯。
💻 C
字号:
#include <avr/io.h>
#include <stdio.h>
//#include <avr/signal.h>
#include <avr/interrupt.h>
#include <util/delay_basic.h>
#include "SJA_BcanConf.h"

#define nop asm("NOP") 
#define FREQ 8    //时钟8M

unsigned char Rec_Flag  = 0;  //接受标志位
unsigned char Send_Flag = 0;  //发送标志位
//volatile unsigned char  *p;

/**** 定义发送,接受帧结构 ****/
struct BCAN_BUFstruct
{
	unsigned char FrameID_H;    
	unsigned char FrameID_L3;
	unsigned char FrameKIND;
	unsigned char FrameLENGTH;
	unsigned char Frame_Data[8];
}BCAN_FRAME,Receive_BUF,Send_BUF;


/**** 延时函数 ****/
void delayMs(unsigned int t)
{
	unsigned int i;
	for(i=0; i<t; i++)           
		_delay_loop_2(FREQ*250);	//约1ms
}
/**** 写SJA1000寄存器 ****/
void CANREG_WRITE(unsigned int SJAREG_ADR,unsigned char Data)
{
    unsigned char  *aa;
    aa=SJAREG_ADR;
	*aa= Data;
}
/**** 读SJA1000寄存器 ****/
unsigned char CANREG_READ(unsigned int SJAREG_ADR)
{
    unsigned char *p;
	unsigned char SJAREG_data;
	p= SJAREG_ADR;
	SJAREG_data = *p;
	return SJAREG_data;
}


/***** CAN控制器进入复位模式 ****/ 
unsigned char BCAN_ENTER_RETMODEL(void)
{
	unsigned char TempData;
	TempData  = CANREG_READ(REG_CONTROL);  //读控制寄存器
	TempData  = TempData | 0x01;
	CANREG_WRITE(REG_CONTROL, TempData);  //写控制寄存器
	if((CANREG_READ(REG_CONTROL) & 0X01) == 1)
	{
		return 0;                           //置复位模式成功
	}
	else
	{
		return 1;                           //置复位模式失败
	}
}



/***** CAN控制器进入正常模式 ****/ 
unsigned char BCAN_QUIT_RETMODE(void)
{
	unsigned char TempData;
	TempData  = CANREG_READ(REG_CONTROL);  //读控制寄存器
	TempData  = TempData & 0xfe;
	CANREG_WRITE(REG_CONTROL, TempData);  //写控制寄存
	if((CANREG_READ(REG_CONTROL) & 0X01) == 0)
	{
		
		return 0;                           // 进入正常模式成功
	}
	else
	{
		return 1;                           //进入正常模式失败
	}
}


/**** 设置CAN控制器验收代码寄存器ACR、验收屏蔽寄存器AMR ****/
unsigned char BCAN_SET_OBJECT(unsigned char BCAN_ACR,unsigned char BCAN_AMR)
{
	CANREG_WRITE(REG_ACR, BCAN_ACR);  //写验收代码寄存器
	if(CANREG_READ(REG_ACR) != BCAN_ACR)
	{
		return 1;          //写失败
	}
	
	CANREG_WRITE(REG_AMR, BCAN_AMR);  //写验收屏蔽寄存器
	if(CANREG_READ(REG_AMR) != BCAN_AMR)
	{
		
		return 1;          //写失败
	}
	
	return 0; 
}

/**** 设置CAN控制器通讯波特率 ****/
unsigned char BCAN_SET_BANDRATE(unsigned char BCAN_BTR0,unsigned char BCAN_BTR1)
{
	CANREG_WRITE(REG_BTR0, BCAN_BTR0);  
	if(CANREG_READ(REG_BTR0) != BCAN_BTR0)
	{
		return 1;
	}
	
	CANREG_WRITE(REG_BTR1, BCAN_BTR1); 
	if(CANREG_READ(REG_BTR1) != BCAN_BTR1)
	{
		return 1;
	}
	
	return 0;
}

/**** 设置CAN输出控制器OCR、时钟分频器CDR ****/
unsigned char BCAN_SET_OUTCLK(unsigned char Out_Control,unsigned char Clock_Out)
{
	CANREG_WRITE(REG_OCR, Out_Control);
	if(CANREG_READ(REG_OCR) != Out_Control)
	{
		return 1;
	}
	
	CANREG_WRITE(REG_CDR, Clock_Out);
	if(CANREG_READ(REG_CDR) != Clock_Out)
	{
		return 1;
	}
	
	return 0;
}
/**** 数据发送至发送缓冲区 ****/
unsigned char BCAN_DATA_SEND(void)
{
	unsigned char i ;
	if((CANREG_READ(REG_STATUS) & 0x08) == 0)  //判断上次发送是否完成
    {
		return 1;
	}
	if((CANREG_READ(REG_STATUS) & 0x04) == 0)  //判断发送缓冲区是否锁定
	{
		return 1;
	}	
    CANREG_WRITE(REG_TxBuffer1,Send_BUF.FrameID_H); //写ID码10~3位 
	                                               //写ID码2~0,帧类型,发送数据长度
	CANREG_WRITE(REG_TxBuffer2,(Send_BUF.FrameID_L3<<5)|(Send_BUF.FrameKIND<<4)|(Send_BUF.FrameLENGTH));
	if(Send_BUF.FrameKIND ==0 )       //数据帧,写数据缓冲区
	{
		for(i=0; i<Send_BUF.FrameLENGTH; i++)
		{
			CANREG_WRITE(REG_TxBuffer3+i,Send_BUF.Frame_Data[i]);
		}
	}
	return 0;                 
}

/****  从接受缓冲区接受数据  ****/
unsigned char BCAN_DATA_RECEIVE(void)
{
	unsigned char i;
	if((CANREG_READ(REG_STATUS) & 0x01) == 0)    //判断接受缓冲区是否有报文
	{
		return 1;
	}
    Receive_BUF.FrameID_H   = CANREG_READ(REG_RxBuffer1);
	Receive_BUF.FrameLENGTH = (CANREG_READ(REG_RxBuffer2))&0x0f;
	Receive_BUF.FrameKIND   = (CANREG_READ(REG_RxBuffer2)&0x10)>>4;
	Receive_BUF.FrameID_L3 = (CANREG_READ(REG_RxBuffer2)&0xE0)>>5;
	if(Receive_BUF.FrameKIND == 0)
	{
		for(i=0;i<Receive_BUF.FrameLENGTH;i++)
		{
			Receive_BUF.Frame_Data[i] = CANREG_READ(REG_RxBuffer3+i);
		}
	}
	return 0;
}

/**** 接受的CAN数据处理 ****/
void CanRcv_Prg(void)
{
	unsigned char status;
	status =  BCAN_DATA_RECEIVE();     //接受数据
	if(status ==0 )
	{
		if(Receive_BUF.FrameKIND == 1)    //远程帧处理
		{
			nop;                        
		}
		else                             //数据帧处理
		{                         
			nop;
		}
	}
}



void SJA1000_Init(void)
{	
	unsigned char status;
	cli();
	CANREG_WRITE(REG_CONTROL,0x07); //接受中断使能
	delayMs(1);
	status=BCAN_ENTER_RETMODEL();	
	delayMs(1);
	
	CANREG_WRITE(REG_COMMAND,0x0e);  //工作在正常模式
    delayMs(1);
    status=BCAN_SET_OBJECT(0x00,0xff); //验收代码寄存器ACR、验收屏蔽寄存器AMR   
	delayMs(1);    
	
	status=BCAN_SET_BANDRATE(0x04,0x1C);//设置CAN控制器通讯波特 12M,100k/s
	delayMs(1);
	
	status=BCAN_SET_OUTCLK(0x1a,0x48);//设置CAN输出控制器OCR、时钟分频器CDR
	delayMs(1);
    
	status=BCAN_QUIT_RETMODE(); 
	delayMs(1);

    sei();
} 


void MCU_Init(void)
{
	
	cli();
	MCUCR |= (1<<SRE);        //使能外部存储器
	XMCRA = 0x80;          //外部存储器地址空间为一个大区,无等待周期
	XMCRB = 0x00;          //端口C全部用于高位地址
	DDRD  |=(1<<DDD0)|(1<<DDD1);  //PD0,PD1输出
	PORTD &=(~((1<<PD0)|(1<<PD1)));
	DDRE  &=(~(1<<DDE4));   //中断引脚输入上拉
	cli();            
	EICRB &=(~((1<<ISC41)|(1<<ISC40)));  //INT4低电平产生中断
	EIMSK |=(1<<INTF4);                    //INT4中断使能
	DDRB  |= 1<<DDB0;      //配置PB0为输出
	PORTB &=(~(0<<PB0));        //pB0输出低电平,硬件复位sja1000
	delayMs(200);  // 延时200ms
	PORTB |= (1<<PB0);
	delayMs(200);
	//sei();              //开总中断
	
	
}
      

int main(void)
{
	unsigned char i,flag1=0;
	unsigned char cmd_data,status;
	MCU_Init();
    SJA1000_Init();

	while(1)
	{
		delayMs(100);
		//PORTD &= (~(1<<PD1));
		delayMs(100);
		if(flag1==0)
		{
			Send_BUF.FrameID_H   = 0;
			Send_BUF.FrameLENGTH = 8;
			Send_BUF.FrameKIND   = 0;
			Send_BUF.FrameID_L3  = 0;
			if(Send_BUF.FrameKIND == 0)
			{
				for(i=0;i<Send_BUF.FrameLENGTH;i++)
				{
					Send_BUF.Frame_Data[i] = i;
				}
			}
			BCAN_DATA_SEND();
			cmd_data =0x01;       //发送请求
            CANREG_WRITE(REG_COMMAND,0X01); 
			delayMs(100);
			status=CANREG_READ(REG_INTERRUPT);
			if((status&0x02) == 0x02)  PORTD |= (1<<PD1);
			while(1);
		//	PORTD |= (1<<PD1);
		}
		if(Send_Flag ==1)
		{
			Send_Flag =0;
			//PORTD |= (1<<PD1);
			flag1=0;
		}
		
	
	}
	return (0);
}

/**** 外部中断4中断处理函数 ****/
SIGNAL(SIG_INTERRUPT4)
{
	unsigned char sta;
	cli();
	PORTD |= (1<<PD1);
	while(1);
	sta=CANREG_READ(REG_INTERRUPT);
	if((sta & 0x10) == 0x10)	
	   { 

		  PORTD |= (1<<PD0);
		  delayMs(1000);
		  PORTD &= (~(1<<PD0));
		  while(1);
		  SJA1000_Init();    //唤醒中断处理
		}
	if((sta & 0x04) == 0x04)	
	{
		PORTD |= (1<<PD0);
		while(1);
		SJA1000_Init();    //错误中断处理
	}
	if((sta & 0x80) == 0x80)  
	{
		PORTD |= (1<<PD1);
		while(1);
	}
	if((sta & 0x02) == 0x02)	
	{

		Send_Flag = 1;           //发送中断处理
	//	PORTD |= (1<<PD1);
		//while(1);
	}   
	if((sta & 0x01) == 0x01)	
	 { 
		Rec_Flag = 1;         //接受中断处理
		PORTD |= (1<<PD1);
		delayMs(1000);
		PORTD &= (~(1<<PD1));
		while(1);
	   
	   }
	sei();
}
// #asm("nop")            //空操作的汇编代码,等待中断发生 
//#define nop asm("NOP")  
//#define NOP asm volatile ("nop") 
           

⌨️ 快捷键说明

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