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

📄 canzj.c

📁 是一个CAN转接的程序
💻 C
📖 第 1 页 / 共 2 页
字号:

#include <P18F258.H>
#include "MCP2510.H"
#include <delays.h>

void MCP2510Rec(void);
//------------------------------------
struct JFSC                        //计时时长、
{
	unsigned char hour;
	unsigned char min;
	unsigned char sec;
	unsigned char msec;
};
typedef union {
	unsigned char word;
	struct {
	  unsigned TMSEC_BIT:1; //100ms事件
	  unsigned TSEC_BIT:1;  //1s事件
	  unsigned TMIN_BIT:1; //1min事件
	  unsigned THOUR_BIT:1; //1hour事件
	  unsigned CANRV_BIT:1;//CAN接收标志
	  unsigned CAN2510RV_BIT:1;//CAN2510接收标志
	  unsigned INT0_BIT:1;
	  unsigned RSV1_BIT:1;
	}Bits;
}uProceSate;
struct CanRevType
{
	unsigned char FrameID[4];
	unsigned char FrameData[8];
};
typedef union {
  	unsigned char word;
	struct {
	  unsigned RX0IF:1; //接收缓冲器0 满中断标志
	  unsigned RX1IF:1; //接收缓冲器1 满中断标志
	  unsigned TX0IF:1; //发送缓冲器0 空中断标志
	  unsigned TX1IF:1; //发送缓冲器1 空中断标志
	  unsigned TX2IF:1; //发送缓冲器2空中断标志
	  unsigned ERRIF:1; //出错中断标志
	  unsigned WAKIF:1; //唤醒中断标志
	  unsigned MERRF:1; //报文出错中断标志
	}Bits;
}CAN2510IntStatus;
//------------变量--------------------
volatile struct JFSC CLOCK;
volatile uProceSate StateTemp;
struct CanRevType CanTxData;
struct CanRevType Can2510TxData;
volatile struct CanRevType CanRevData;
volatile struct CanRevType Can2510RevData;
unsigned char DebugErrorCode;//错误代码
unsigned char TestTryTime;
volatile CAN2510IntStatus MCP2510IntStatus;
unsigned char Thread;
//--------------------------------------
#define NO_THREAD				0x00
#define THREAD_IDLE				0x01
//#define Debug
//----------- 初始化程序---------------
void init_cpu(void)
{
	//---------------------
	INTCON 	= 0x00; //禁止所有中断
	INTCON2	= 0x00;//int0 下降沿中断
	INTCON3	= 0x00;
	ADCON1	= 0x87;	//设置所有与模拟输入共用的管腿为I/O方式
	//---初始化管腿------------
	TRISA	= 0xfc;//RA0 RA1为输出
	TRISB	= 0xfb;//配置CAN
	TRISC	= 0xd0;//配置SPI SDO为输出 SDI为输入 SCK为输出
	//---初始化timer0------------
	T0CON	= 0x8F;//16位定时器,不使用分频器
	TMR0H 	= 0xD8;
	TMR0L	= 0xEF;//定时10ms
	//------初始化CAN控制器--------
	CANCON	= 0x80;//进入配置方式
	//while((CANSTAT&0x80)==0x00);//等待进入配置模式
	DebugErrorCode=0x00;
	TestTryTime=100;
	while(TestTryTime--) //等待进入配置模式
	{
		if((CANSTAT&0x80)==0x80) break;
	}
	if(TestTryTime==0x00) DebugErrorCode=CAN_ENTCONFG_ERR;
	//设置CAN的波特率为5K,在Fosc=4M时,Tbit=200us,假设BRP=39, 则
	//TQ=[2*(1+BRP)]/Fosc=2*(1+39)/4=20us。
	//NOMINAL BIT RATE=10TQ,SJW=1,Sync_Seg=1TQ,Prog _Seg=1TQ,Phase_Seg1=4TQ,Phase_Seg2=4TQ
	BRGCON1	= 0x27; //设置SJW和BRP,SJW=1TQ,BRP=39H
	BRGCON2	= 0x98; //设置Phase_Seg1=4TQ和Prog _Seg=1TQ
	BRGCON3	= 0x43; //设置Phase_Seg2=4TQ
	CIOCON	= 0x00;//设置CAN输入输出控制寄存器
    TXB0CON	= 0x03;//设为最高优先级
	TXERRCNT= 0x00;//清除发送错误计数器
	RXB0CON	= 0x00;//接收所有有效信息
	RXB0DLC	= 0x08;//接收数据长度为8
	RXERRCNT= 0x00;//清除接收错误计数器
	//初始化接收滤波器
	RXF0SIDH= 0xff;
	RXF0SIDL= 0xeb;
	RXF0EIDH= 0xff;
	RXF0EIDL= 0xff;
	RXM0SIDH= 0x00;
	RXM0SIDL= 0x00;
	RXM0EIDH= 0x00;
	RXM0EIDL= 0x00;

	CANCON	= 0x00;//进入正常工作模式
	//while((CANSTAT&0xE0)!=0x00);//等待进入正常模式
	TestTryTime=100;
	while(TestTryTime--) //等待进入正常模式
	{
		if((CANSTAT&0xE0)==0x00) break;
	}
	if(TestTryTime==0x00) DebugErrorCode=CAN_QUITCONFG_ERR;
	PIR3	= 0x00; //清除所有中断标志
	//PIE3	= 0x01; //使能接收0的中断
	//PIE3	= 0xe1; //使能接收0的中断
 	PIE3	= 0x61; //使能接收0的中断
    IPR3	= 0x01; //接收0的中断为最高优先级
	//------初始化SPI------------------
	PIE1bits.SSPIE=0; //禁止中断
	SSPCON1	= 0x30; //SSPEN=1;CKP=1;主控方式Fosc/4(1M波特率)
	SSPSTAT	= 0xc0;
	PIR1bits.SSPIF=0;//清除SSPIF标志
    //------设置中断优先级--------------
	INTCON2bits.TMR0IP=0;//timer0 高优先机
    RCONbits.IPEN=1;//使能中断优先级
	//------初始化管腿----------------
	PORTAbits.RA0=0;
	PORTAbits.RA1=0;
	CAN2510Disable();
	MCP2510REST=1;
	Thread=NO_THREAD;
	StateTemp.word=0x00;//清标志位
}
//------timer0中断程序------------------
void timer0int(void);
#pragma code Low_Vector=0x18
void InterruptVectorLow (void)
{
	_asm 
		goto timer0int
	_endasm
}
#pragma code
#pragma interrupt timer0int
void timer0int(void)
{
	unsigned char temp;

	if(INTCONbits.T0IF)//timer0中断
	{
		TMR0H 	= 0xD9;
		TMR0L	= 0x7a;//定时10ms
		INTCONbits.T0IF=0;	//清中断标志
		if((CLOCK.msec%10)==0) StateTemp.Bits.TMSEC_BIT=1; //100ms事件
		if(++CLOCK.msec>=100)
		{
			CLOCK.msec=0;
			StateTemp.Bits.TSEC_BIT=1;//秒事件
			++CLOCK.sec;
			temp=CLOCK.sec;
			if((temp&0x0f)>9) CLOCK.sec=(temp&0xf0)+0x10;
	
			if(CLOCK.sec>=0x60)
			{
				CLOCK.sec=0;
				StateTemp.Bits.TMIN_BIT=1;	  //分事件
				++CLOCK.min;
				temp=CLOCK.min;
				if((temp&0x0f)>9) CLOCK.min=(temp/16)*16+0x10;//(temp&0xf0)+0x10;
				if(CLOCK.min>=0x60)
				{
					StateTemp.Bits.THOUR_BIT=1;//小时事件
					CLOCK.min=0;
					CLOCK.hour++;
					temp=CLOCK.hour;
					if((temp&0x0f)>9) CLOCK.hour=CLOCK.hour&0xf0+0x10;
					if(CLOCK.hour==0x24) CLOCK.hour=0;
				}
				
			}
		} 
	}
}
//------------------CAN程序-----------------------------
void send_data(unsigned char FrameType, unsigned char IDbuff[4],unsigned char DataBuff[8])
{
	unsigned char temp;
	unsigned char temp1;
	unsigned char Flag;

	Flag=0x00;
	temp1=IDbuff[1]>>5;
	temp=IDbuff[0]<<3;
	TXB0SIDH=temp+temp1;
	temp1=(IDbuff[1]&0x1f)<<3;//取后5位
	temp=IDbuff[1]&0x03;//取后2位
	temp1=temp1+temp;
    if(FrameType==1) temp1=temp1|0x08;
	if(FrameType==0) temp1=temp1&0xf7;
	TXB0SIDL= temp1;
	TXB0EIDH= IDbuff[2];
    TXB0EIDL= IDbuff[3];

	TXB0DLC	= 0x08;//设置发送数据长度为8
	TXB0D0	= DataBuff[0];
	TXB0D1	= DataBuff[1];
	TXB0D2	= DataBuff[2];
	TXB0D3	= DataBuff[3];
	TXB0D4	= DataBuff[4];
	TXB0D5	= DataBuff[5];
	TXB0D6	= DataBuff[6];
	TXB0D7	= DataBuff[7];
	TXB0CONbits.TXREQ=1;//请求发送
	while(PIR3bits.TXB0IF!=1) //ClrWdt(); //等待
	{
		ClrWdt(); //等待
		if(TXB0CONbits.TXLARB)//丢失仲裁,(断路)
		{
			TXB0CONbits.TXABT=1;//中止发送
			TXB0CONbits.TXREQ=0;
			TXERRCNT= 0x00;//清除发送错误计数器
			DebugErrorCode=CAN_SEND1_ERR;
			Flag=0x01;
			break;
		}
		if(TXB0CONbits.TXERR)//总线错误(短路)
		{
			TXB0CONbits.TXABT=1;//中止发送
			TXB0CONbits.TXREQ=0;
			TXERRCNT= 0x00;//清除发送错误计数器(可能不起作用)
			DebugErrorCode=CAN_SEND2_ERR;
			Flag=0x02;
			break;
		}
		if(COMSTATbits.TXBO)//发送错误计数大于255,总线关闭
		{
			TXB0CONbits.TXABT=1;//中止发送
			TXB0CONbits.TXREQ=0;
			TXERRCNT= 0x00;//清除发送错误计数器(可能不起作用)
			DebugErrorCode=CAN_SEND3_ERR;
			Flag=0x03;
			break;
		}
	}
	if(Flag==0x00) DebugErrorCode=CAN_SENDOK;
}
void CanRecvInt(void);
#pragma code High_Vector=0x08
void InterruptVectorHigh (void)
{
	_asm 
		goto CanRecvInt
	_endasm
}
#pragma code
#pragma interrupt CanRecvInt
void CanRecvInt(void)
{
	unsigned char temp,temp1,temp2;

	//INTCONbits.GIE=0;//关总中断
	PORTAbits.RA1=0;
	//----------PIC18F258 CAN中断程序-------------
	if(PIR3bits.RXB0IF==1) //接收缓冲区0接收中断
	{
		temp=RXB0SIDH;
		temp1=RXB0SIDL;
		CanRevData.FrameID[0]=temp>>3;
		temp2=temp1&0x03;//取后2位
		temp2=temp2+((temp1&0xe0)>>3);
		temp2=((temp&0x07)<<5)+temp2;
		CanRevData.FrameID[1]=temp2;
		CanRevData.FrameID[2]=RXB0EIDH;
		CanRevData.FrameID[3]=RXB0EIDL;

		CanRevData.FrameData[0]=RXB0D0;
		CanRevData.FrameData[1]=RXB0D1;
		CanRevData.FrameData[2]=RXB0D2;
		CanRevData.FrameData[3]=RXB0D3;
		CanRevData.FrameData[4]=RXB0D4;
		CanRevData.FrameData[5]=RXB0D5;
		CanRevData.FrameData[6]=RXB0D6;
		CanRevData.FrameData[7]=RXB0D7;
		StateTemp.Bits.CANRV_BIT=1;	//置接收标志
		RXB0CONbits.RXFUL=0;//清除接收缓冲区
		PIR3bits.RXB0IF=0; //清除接收中断			
	}
	if(PIR3bits.IRXIF==1) //错误收信息中断,与监听模式联合使用确定波特率
	{
		PIR3bits.IRXIF=0;
	}
	if(PIR3bits.WAKIF==1) //总线唤醒中断,休眠模式下,退出休眠
	{
		PIR3bits.WAKIF=0;
	}
	if(PIR3bits.ERRIF==1) //总线错误中断
	{
		PORTAbits.RA1=0;
		if(COMSTATbits.RXB0OVFL)//接收缓冲区0溢出
		{
			COMSTATbits.RXB0OVFL=0;//清除溢出
			DebugErrorCode=CAN_REVBUFF0_ERR;
		}
		if(COMSTATbits.RXWARN)//接收器警告位
		{
			RXERRCNT= 0x00;//清除接收错误计数器
			DebugErrorCode=CAN_REVWAR_ERR;
		}
		if(COMSTATbits.TXBO)//发送错误计数大于255,总线关闭
		{
			TXB0CONbits.TXABT=1;//中止发送
			TXB0CONbits.TXREQ=0;
			TXERRCNT= 0x00;//清除发送错误计数器(可能不起作用)
			DebugErrorCode=CAN_SEND3_ERR;

			CANCON	= 0x00;//进入正常工作模式
			TestTryTime=20;
			while(TestTryTime--) //等待进入正常模式
			{
				ClrWdt(); 
				if((CANSTAT&0xE0)==0x00) break;
			}
		}
		PIR3bits.ERRIF=0;
	}
	//---------MCP2510 Can中断程序-------------------
	if(INTCONbits.INT0F) //外部中断,用于接收mcp2510
	{
		INTCONbits.INT0F=0;//清除中断	
		//MCP2510Rec();
		StateTemp.Bits.INT0_BIT=1;
	}
	
	//INTCONbits.GIE=1;//开总中断
}
//--------------SPI程序-------------------------
void WriteSPI(unsigned char OutData)
{
	SSPBUF	= OutData;//启动发送
	do{
		ClrWdt(); 
	}while(PIR1bits.SSPIF==0);//等待发送结束
	PIR1bits.SSPIF=0;//清除标志位
}
//从一地址读一个字节
unsigned char ReadSPI(void)
{
	unsigned char spidata;

	SSPBUF	= 0x00; //清除SSPSTAT的BF位
	TestTryTime=100;
	while(TestTryTime--)
	{
		if(SSPSTATbits.BF==1)
		{
			spidata	= SSPBUF;//读出数据
			PIR1bits.SSPIF=0;
		}
	}
    return(spidata);
}

//--------------MCP2510程序--------------------
//复位程序,复位后,自动进入配置模式
void CAN2510Reset(void)
{
	ClrWdt();
	CAN2510Enable();
	Nop();
	MCP2510REST=0;
	Delay100TCYx(2);
	MCP2510REST=1;
	Delay100TCYx(2);
	CAN2510Disable();

⌨️ 快捷键说明

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