充电站程序

充电站程序_第1张图片


program.c

/********************************************
		program8.c	
		说明:带CAN通讯功能的两路充电器程序代码
			
		主控芯片:PIC16F887
		引脚关系:
		芯片时钟:16Mhz
		CAN通讯速率:125Kb/s
		
		Author:Alex
		Date:2016/01/28 12:09
		File:
********************************************/

#include 
__CONFIG (CP_OFF &WDTE_OFF& BOREN_OFF&PWRTE_OFF &FOSC_HS&WRT_OFF&LVP_OFF&CPD_OFF);
void main()
{	
/****定义临时无符号整形变量****/	
/****定义临时整形变量****/	
	int i;		
/****定义临时浮点型整形变量****/		
	count=0;
	CAN_FLAG=0;								/*开机复位,清接收到标志*/
	canreflag=0;
				
 	Init_PWM();								/*初始化配置PWM*/
	Init_Int();								/*初始化中断*/	
	Init_Spi();								/*初始化SPI*/
	Init_Can();								/*初始化CAN通讯*/
	Usart_init();							/*初始化串口通讯*/	
	Bat_init();								/*初始化左右侧电池的状态标志位*/			
	TRISE=0X00;
	PORTE=0x00;
	ENA=1;									/*关掉2路通讯*/
	delay(500);								/*延时1秒*/	
	while(1)
	{			
		if(RD2==0)							/*左电池盒闭合状态*/																							
		{
			delay(30);						/*延时去抖*/
			if(RD2==0)						/*此时开关处于闭合状态,有电池插入电池盒*/
			{
				Bat_1.in=1;					/*将左电池进入充电站标志位置1*/
			}
		}
		else								/*左电池盒打开状态*/
		{	
			Bat_1.in=0;						/*将左电池进入充电站标志位清零*/
		}
		
		
		if(RD3==0)							/*右电池盒闭合状态*/																						
		{
			delay(30);						/*延时去抖*/
			if(RD3==0)						/*此时开关处于闭合状态,有电池插入电池盒*/
			{
				Bat_2.in=1;					/*将左电池进入充电站标志位置1*/
			}
		}
		else								/*左电池盒打开状态*/
		{	
			Bat_2.in=0;						/*将左电池进入充电站标志位清零*/
		}

		if(Bat_1.in==1)						/*左侧电池盒闭合的时候*/
		{
			if(Bat_1.init==0)				/*左侧电池盒初始化未完成*/
			{
				delay(500);					/*延时1秒*/
				LeftBattery_Init();			/*左侧电池盒初始化*/
				if(Bat_1.init==1)			/*左侧电池盒初始化完成*/
				{
					LeftBattery_Deal();		/*左侧电池盒控制电流充电*/
				}	
			}
			else							/*左侧电池盒初始化已完成*/
			{
				LeftBattery_Deal();			/*左侧电池盒控制电流充电*/
			}	
		}		
		else								/*左侧电池盒打开的时候*/
		{	
			Bat_1_Reset();					/*左侧电池状态复位*/		
		}

		if(Bat_2.in==1)						/*右侧电池盒闭合的时候*/
		{
			if(Bat_2.init==0)				/*右侧电池盒初始化未完成*/
			{
				if(Bat_1.init==0)			/*左侧电池盒初始化未完成*/
				{
					//delay(200);			/*延时1秒*/
					LeftBattery_Init();		/*左侧电池盒初始化*/
					if(Bat_1.init==1)		/*左侧电池盒初始化完成*/
					{
						LeftBattery_Deal();	/*左侧电池盒控制电流充电*/
					}			
				}		
				ENA=0;						/*打开2路通讯*/	
				delay(500);					/*延时1秒*/
				RightBattery_Init();		/*右侧电池盒初始化*/
				if(Bat_2.init==1)			/*左侧电池盒初始化完成*/
				{
					RightBattery_Deal();	/*右侧电池盒控制电流充电*/
				}									
			}
			else							/*右侧电池盒初始化已完成*/
			{
				RightBattery_Deal();		/*右侧电池盒控制电流充电*/
			}	
		}
		else								/*右侧电池盒不在里面的时候*/
		{	
			Bat_2_Reset();					/*右侧电池状态复位*/		
		}
				
		if(count%20==0)						/*采集两路的温度值,根据温度控制风扇。*/
		{
			show_temp();
		}
		count++;	
	}
}


program.h

/*****************************************************************/
#ifndef	__program8_H__
#define	__program8__

#include "pic.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define uchar unsigned char
#define uint  unsigned int
#define nop() asm("nop")

#define CS 	   	RD1			/*标签为CANCSRH4*/
#define RESET  	RD0  		/*标签为RESETCAN*/
#define FAN RC0				/*定义风扇*/
void Init_Int(void);		/*初始化中断*/
void interrupt ISR(void);	/*中断处理函数*/
#endif

can887.c

/********************************************************  
 MCP2515 CAN通讯程序,测试CAN协议   
**********************************************************/
#include 

 
/***************************
函数:void Init_Can(void)
函数描述:初始化CAN通讯
变量:无
*****************************/
void Init_Can(void)
{
	RESET=1;			/*关闭复位*/
	CS=1;				/*关闭片选*/
	CS=0;				/*打开片选,选中MCP2515*/
/**************************************
复位MCP2515 进入配置模式,以便配置寄存器。
****************************************/
	SPIReset();			/*SPI复位*/
	CS=1;				/*关闭片选*/	
	delay(20);			/*延时20ms*/

/**设置为配置模式**/
	/*配置验收屏蔽滤波器0*/	
	CAN_Write(RXM0SIDH, 0x00);					//为0时,对应的滤波位不起作用
	CAN_Write(RXM0SIDL,0x00);
	/*配置验证滤波器0*/	
	CAN_Write(RXF0SIDH,0x00);					//标准标识符高字节
	CAN_Write(RXF0SIDL,0x00);					//标准标识符低字节

/**设置通讯速率 晶振16M 波特率125Kbps**/				
	CAN_Write(CNF1,CAN_125Kbps);				//CNF1=0x07
												//set CNF1,SJW=00,长度为1TQ,BRP=49,TQ=[2*(BRP+1)]/Fsoc=2*50/8M=12.5us,16M
												//配置寄存器1,默认CAN波特率为125Kbit/s
	CAN_Write(CNF2,0x80|PHSEG1_3TQ|PRSEG_1TQ);	//3,1;6,2
												//set CNF2,SAM=0,在采样点对总线进行一次采样,PHSEG1=(2+1)TQ=3TQ,PRSEG=(0+1)TQ=1TQ
												//配置寄存器2,位时间为3TQ,同步段1TQ
												//传播段1TQ,PHSEG1=3TQ,PRSEG=1TQ												
	CAN_Write(CNF3,PHSEG2_3TQ);					//3;7	配置寄存器3,唤醒滤波器使能
											  	//set CNF3,PHSEG2=(2+1)TQ=3TQ,同时当CANCTRL.CLKEN=1时设定CLKOUT引脚为时间输出使能位
											  	
	//set TXB0,设置发送缓冲器0的标识符和发送的数据,以及发送的数据长度
	/*配置发送缓冲区0,发送标准数据帧到ID:0X00的CAN节点*/
	CAN_Write(TXB0SIDH,0x06);					//标准标识符高字节
	CAN_Write(TXB0SIDL,0x00);					//标准标识符低字节
	CAN_Write(TXB0DLC,DLC_8);					//设置发送数据的长度为8个字节,DLC_8

 	//设置接收缓冲器0的标识符和初始化数据
 	CAN_Write(RXB0SIDH,0x00);					//设置接收缓冲器0的标准标识符,待修改***
 	CAN_Write(RXB0SIDL,0x60);					//用到标准标识符
 	CAN_Write(RXB0CTRL,0x60);					//仅仅接收标准标识符的有效信息,FIILHIT0=0表示RXB0 ,采用FILHIT0
 	CAN_Write(RXB0DLC,DLC_8);					//设置接收数据的长度为8个字节,DLC_8
 	
 	/*配置验收滤波器*/
 	CAN_Write(RXF0SIDH,0xFF);					//标准标识符高字节
 	CAN_Write(RXF0SIDL,0xE0);					//标准标识符低字节
 	
	/*配置验收屏蔽滤波器0*/	 	
 	CAN_Write(RXM0SIDH,0xFF);					//标准标识符高字节
 	CAN_Write(RXM0SIDL,0xE0);					//标准标识符低字节

 	//设置接收缓冲器0中断
 	CAN_Write(CANINTF,0x00);					//清空中断标志位
 	CAN_Write(CANINTE,0x01);					//接收缓冲器0满中断使能位

	CAN_Write(CANCTRL,REQOP_NORMAL|CLKOUT_ENABLED);				//设置正常模式

 	delay(10);	
  	dummy=CAN_Read(CANSTAT);									//读取CAN状态寄存器的值
		if (OPMODE_NORMAL != (dummy && 0xE0))					//判断进入正常工作模式
	  	CAN_Write(CANCTRL,REQOP_NORMAL | CLKOUT_ENABLED);		//设置正常模式
}


/***************************
函数:void CAN_Send(unsigned char *CAN_TX_Buf)
函数描述:CAN发送数据程序 
变量:无
*****************************/
void CAN_Send(unsigned char *CAN_TX_Buf)
{
	unsigned char tempdata;
	tempdata=CAN_Read(CAN_RD_STATUS);
	CAN_Write(TXB0D0,CAN_TX_Buf[0]);
	CAN_Write(TXB0D1,CAN_TX_Buf[1]);
	CAN_Write(TXB0D2,CAN_TX_Buf[2]);
	CAN_Write(TXB0D3,CAN_TX_Buf[3]);
	CAN_Write(TXB0D4,CAN_TX_Buf[4]);
	CAN_Write(TXB0D5,CAN_TX_Buf[5]);
	CAN_Write(TXB0D6,CAN_TX_Buf[6]);
	CAN_Write(TXB0D7,CAN_TX_Buf[7]);
	if(tempdata&0x04)//判断TXREQ标志位
	{
		delay(5);
		CAN_Write(TXB0CTRL,0);//清除TXREQ标志位
		while(CAN_Read(CAN_RD_STATUS)&0x04);//等待TXREQ清零
	}
	CS=0;
	SPISendByte(CAN_RTS_TXB0);//发送缓冲器0请求发送
	CS=1;
}


/***************************
函数:void CAN_Send_onebyte(unsigned char k)
函数描述:CAN发送一个字节数据程序 
变量:无
*****************************/
void CAN_Send_onebyte(unsigned char k)
{
	unsigned char tempdata;
	tempdata=CAN_Read(CAN_RD_STATUS);
	CAN_Write(TXB0D0,k);
	if(tempdata&0x04)//判断TXREQ标志位
	{
		delay(5);
		CAN_Write(TXB0CTRL,0);//清除TXREQ标志位
		while(CAN_Read(CAN_RD_STATUS)&0x04);//等待TXREQ清零
	}
	CS=0;
	SPISendByte(CAN_RTS_TXB0);//发送缓冲器0请求发送
	CS=1;
}



/***************************
函数:void CAN_Receive(unsigned char *CAN_RX_Buf)
函数描述:CAN接收程序
变量:无
*****************************/
void CAN_Receive(unsigned char *CAN_RX_Buf)
{
//	unsigned char tempdata;
//	tempdata=CAN_Read_SS(CAN_RX_STATUS);

//	if(tempdata&0x40)//说明接收的是RXB0中的标准数据帧
//	{
//		delay(1);
//		CS=0;
//		SPISendByte(CAN_RX_Buf);//将接收的首地址定为RXB0D0
		CAN_RX_Buf[0]=CAN_Read(RXB0D0);
		CAN_RX_Buf[1]=CAN_Read(RXB0D1);
		CAN_RX_Buf[2]=CAN_Read(RXB0D2);
		CAN_RX_Buf[3]=CAN_Read(RXB0D3);
		CAN_RX_Buf[4]=CAN_Read(RXB0D4);
		CAN_RX_Buf[5]=CAN_Read(RXB0D5);
		CAN_RX_Buf[6]=CAN_Read(RXB0D6);
		CAN_RX_Buf[7]=CAN_Read(RXB0D7);
		CAN_Write(CANINTF,0);
	//	CS=1;
//	}
}

/***************************
函数:unsigned char CAN_Receive_onebyte()
函数描述:CAN接收一个字节函数
变量:tempdata
*****************************/
unsigned char CAN_Receive_onebyte()
{
	unsigned char tempdata;
	//tempdata=SPIByteRead(CAN_RX_STATUS);

	//if(tempdata&0x40)//说明接收的是RXB0中的标准数据帧
	//{
	//	delay_ms(1);
		//CS=LOW;
		//WriteSPI(CAN_RX_BUFF);//将接收的首地址定为RXB0D0
		tempdata=CAN_Read(RXB0D0);
		CAN_Write(CANINTF,0);
		return tempdata;
		//CS=HIGH;
	//}
}


/***************************
函数:void CAN_writetxb0id(unsigned int txb0id)
函数描述:位修改指令函数
变量:无
*****************************/
void CAN_writetxb0id(unsigned int txb0id)
{	
	CAN_Write(TXB0SIDH,(txb0id>>3));//设置发送缓冲器0的标准标识符,待修改***
	CAN_Write(TXB0SIDL,(0x00FF&(txb0id<<5)));//用到标准标识符	
}


/***************************
函数:void CAN_deal(void)
函数描述:CAN通讯接收处理函数
变量:无
*****************************/
void CAN_deal(void)
{	
	CAN_FLAG=0;     					/*清接收到标志*/
	canrecebuf[0]=CAN_Read(RXB0D0);
	canrecebuf[1]=CAN_Read(RXB0D1);
	canrecebuf[2]=CAN_Read(RXB0D2);
	canrecebuf[3]=CAN_Read(RXB0D3);
	canrecebuf[4]=CAN_Read(RXB0D4);
	canrecebuf[5]=CAN_Read(RXB0D5);
	canrecebuf[6]=CAN_Read(RXB0D6);		
	canrecebuf[7]=CAN_Read(RXB0D7);
	CAN_Write(CANINTF,0);
}

/***************************
函数:void CAN_0x21(int num)
函数描述:按地址0X21发送并接收数据,初始化第二步
变量:无
*****************************/
void CAN_0x21(int num)
{
	/**访问地址0X0021**/
	CAN_writetxb0id(0x0021);
	if(num==1)
	{
		cansentbuf[0]=0x01;					/*1为左侧电池盒	*/
	}
	else
	{
		cansentbuf[0]=0x02;					/*2为右侧电池盒*/
	}
	cansentbuf[1]=canrecebuf[0];
	cansentbuf[2]=canrecebuf[1];
	cansentbuf[3]=canrecebuf[2];
	cansentbuf[4]=canrecebuf[3];
	cansentbuf[5]=0x00;	
	cansentbuf[6]=0x00;
	cansentbuf[7]=0x00;	
	CAN_Send(cansentbuf);					/*发送数组,发送CAN通讯*/		
	delay(100);								/*延时等待中断接收*/
	CAN_deal();								/*接收数组*/				
	canjudgbuf[5]=canrecebuf[0];
	canjudgbuf[6]=canrecebuf[1];
	canjudgbuf[7]=canrecebuf[2];
//	canjudgbuf[8]=canrecebuf[3];
	canjudgbuf[9]=canrecebuf[7];
	if(canreflag==1)
	{
		canreflag=0;								/*清接收到标志*/		
	
		if(num==1)
		{
			for(int i=0;i<=4;i++)					/*判断初始化过程中,两次接收到的条码是否一致。间接检验通讯是否正确进行*/
			{
				if(canjudgbuf[i]!=canjudgbuf[i+5])
				{
    				Bat_1.init=0;					/*初始化执行失败*/
    				break;							/*若发现两次的的条码不对应,跳出循环,继续初始化 */
    			}
    			else
    			{
    				Bat_1.init=1;					/*初始化执行成功*/
    			} 				
 			}
		}
		else
		{
			for(int i=0;i<=4;i++)					/*判断初始化过程中,两次接收到的条码是否一致。间接检验通讯是否正确进行*/
			{
				if(canjudgbuf[i]!=canjudgbuf[i+5])
				{
    				Bat_2.init=0;					/*初始化执行失败*/
    				break;							/*若发现两次的的条码不对应,跳出循环,继续初始化 */
    			}
    			else
    			{
    				Bat_2.init=1;					/*初始化执行成功*/
    			} 				
 			}
		}
	}
	else
	{
		Bat_2.init=0;					/*初始化执行失败*/	
	}	
	for(int i=0;i<=9;i++)						/*将判断的数组进行清零*/		
	{
		canjudgbuf[i]=0;
	}
			
}


/***************************
函数:void CAN_0x25(int num)
函数描述:按地址0X25发送并接收数据,读取电池故障信息。
变量:无
*****************************/
void CAN_0x25(int num)
{			
	/**访问地址0X0025**/
	CAN_writetxb0id(0x0025);
	if(num==1)
	{
		cansentbuf[0]=0x01;												/*1为左侧电池盒	*/
	}
	else
	{
		cansentbuf[0]=0x02;												/*2为右侧电池盒*/
	}
	cansentbuf[1]=0x00;
	cansentbuf[2]=0x29;
	cansentbuf[3]=0x00;
	cansentbuf[4]=0x00;
	cansentbuf[5]=0x00;	
	cansentbuf[6]=0x00;
	cansentbuf[7]=0x00;	
	CAN_Send(cansentbuf);												/*发送数组,发送CAN通讯*/
	delay(100);															/*延时等待中断接收*/
	CAN_deal();															/*接收数组*/		
//	canrecebuf[5]=1;													/*模拟发送报文中有错误*/	
	if(canreflag==1)
	{
		canreflag=0;													/*清接收到标志*/
		if(num==1)
		{
			Bat_1.init=1;													/*左电池盒初始化标志位为1*/
		}
		else
		{
			Bat_2.init=1;													/*右电池盒初始化标志位为1*/
		}		
		
		if(num==1)
		{
			for(i=0;i<7;i++)											/*将故障数据的值按位或*/
			{								
				Bat_1.error=Bat_1.error||canrecebuf[i];		
			}
			Bat_1.error1=canrecebuf[0]||canrecebuf[2]||canrecebuf[3];	/*左电池过压、温度故障标志位*/
			Bat_1.error2=canrecebuf[4];									/*左电池过流故障标志位*/
		}
		else
		{
			for(i=0;i<7;i++)											/*将故障数据的值按位或*/
			{							
				Bat_2.error=Bat_2.error||canrecebuf[i];		
			}
			Bat_2.error1=canrecebuf[0]||canrecebuf[2]||canrecebuf[3];	/*左电池过压、温度故障标志位*/
			Bat_2.error2=canrecebuf[4];									/*左电池过流故障标志位*/
		}					
		for(i=0;i<7;i++)												/*清接收数组*/
		{							
			canrecebuf[i]=0;		
		}
		
	}
	else
	{
		if(num==1)
		{
			Bat_1.init=0;												/*左电池盒初始化未成功,需要重新初始化*/
			Bat_1_Reset();												/*左侧电池状态复位*/
		}
		else
		{
			Bat_2.init=0;												/*右电池盒初始化未成功,需要重新初始化*/
			Bat_2_Reset();												/*右侧电池状态复位*/
		}		
	}		
}

/***************************
函数:void CAN_0x26(int num)
函数描述:按地址0X26发送并接收数据,读取电池故障信息。
变量:无
*****************************/
void CAN_0x26(int num)
{			
	/**访问地址0X0026**/
	CAN_writetxb0id(0x0026);
	if(num==1)
	{
		cansentbuf[0]=0x01;					//1为左侧电池盒	
	}
	else
	{
		cansentbuf[0]=0x02;					//2为右侧电池盒
	}
	cansentbuf[1]=0x00;
	cansentbuf[2]=0x28;
	cansentbuf[3]=0x00;
	cansentbuf[4]=0x00;
	cansentbuf[5]=0x00;	
	cansentbuf[6]=0x00;
	cansentbuf[7]=0x00;	
	CAN_Send(cansentbuf);						//发送数组,发送CAN通讯
	delay(100);									//延时等待中断接收
	CAN_deal();									//接收数组
	if(num==1)
	{
		Bat_1.Soc=canrecebuf[5];
	}
	else
	{
		Bat_2.Soc=canrecebuf[5];
	}	
//	delay(100);									//延时等待中断接收		
	canreflag=0;								//清接收到标志
		for(i=0;i<7;i++)						/*清接收数组*/
		{							
			canrecebuf[i]=0;		
		}
										
}

/***************************
函数:void Bat_1_Test(void)
函数描述:发0x20指令,判断左电池是否已经完成了初始化
变量:无
*****************************/
void Bat_1_Test(void)
{
	/**访问地址0X0020**/
	CAN_writetxb0id(0x0020);
	cansentbuf[0]=0x01;	
	cansentbuf[1]=0x00;
	cansentbuf[2]=0x27;
	cansentbuf[3]=0x00;
	cansentbuf[4]=0x00;
	cansentbuf[5]=0x00;	
	cansentbuf[6]=0x00;
	cansentbuf[7]=0x00;		
	CAN_Send(cansentbuf);						/*发送数组,发送CAN通讯*/
	delay(100);									/*延时等待中断接收*/
	CAN_deal();									/*接收数组*/		
}


/***************************
函数:void Bat_2_Test(void)
函数描述:发0x20指令,判断左电池是否已经完成了初始化
变量:无
*****************************/
void Bat_2_Test(void)
{
	/**访问地址0X0020**/
	CAN_writetxb0id(0x0020);
	cansentbuf[0]=0x02;	
	cansentbuf[1]=0x00;
	cansentbuf[2]=0x27;
	cansentbuf[3]=0x00;
	cansentbuf[4]=0x00;
	cansentbuf[5]=0x00;	
	cansentbuf[6]=0x00;
	cansentbuf[7]=0x00;		
	CAN_Send(cansentbuf);						/*发送数组,发送CAN通讯*/
	delay(100);									/*延时等待中断接收*/
	CAN_deal();									/*接收数组*/	
}





can887.h
#ifndef	__CAN_H__
#define	__CAN_H__
//	write your header here

#include 
#include 
#include 
#include 
#include 
#include 
#include 
/*******************************************************************
 *                    波特率配置                                   *
 *******************************************************************/
#define  CAN_10Kbps		0x31
#define  CAN_25Kbps		0x13
#define  CAN_50Kbps		0x09
#define  CAN_100Kbps	0x04
#define  CAN_125Kbps	0x07
#define  CAN_250Kbps	0x01
#define  CAN_500Kbps	0x00


void Init_Can(void);							/*初始化CAN通讯*/
void CAN_Send(unsigned char *CAN_TX_Buf);		/*CAN发送数据程序*/ 
void CAN_Send_onebyte(unsigned char k);			/*CAN发送一个字节数据程序*/
void CAN_Receive(unsigned char *CAN_RX_Buf);	/*CAN接收程序*/
unsigned char CAN_Receive_onebyte();			/*CAN接收一个字节程序*/
void CAN_writetxb0id(unsigned int txb0id);		/*位修改指令函数*/
void CAN_deal(void);							/*CAN通讯接收处理函数*/
void CAN_0x21(int num);							/*按地址0X21发送并接收数据,初始化第二步*/
void CAN_0x25(int num);							/*按地址0X25发送并接收数据,读取电池故障信息。*/
void CAN_0x26(int num);							/*按地址0X26发送并接收数据,读取电池状态信息。*/
void Bat_1_Test(void);							/*发0x20指令,判断左电池是否已经完成了初始化*/
void Bat_2_Test(void);							/*发0x20指令,判断右电池是否已经完成了初始化*/
#endif

usart.c

#include 

/****************************
函数:void Usart_init()
函数描述:串口初始化
变量:无
*******************************/
void Usart_init()
{
	SPBRG=0X19;//SPBRG=25
	BAUDCTL=0X00;//BAUDCTL:波特率控制寄存器,BRG16=0
	TXSTA=0X20;//TXSTA:发送状态和控制寄存器,TX9=0,TXEN=1,SYNC=0,BRGH=0
	RCSTA=0X80;//RCSTA:接收状态和控制寄存器,SPEN=1	
}


/****************************
函数:void Show_array(char array[],int n)
函数描述:显示一个字符型的数组
变量:无
*******************************/
void Show_array(char array[],int n)//显示一个字符型的数组
{	
	for(j=0;j=1000))
	{
	flag_2=1;	//置标志位,若此标志位为1,则说明是四位数
	}
	a=NUM/10000;
	b=((NUM%10000)/1000);
	c=((NUM%1000)/100);
	d=((NUM%100)/10);
	e=(NUM%10);
	if(flag_1==1)
	{
		NUM1[0]=48;	//ASCII码49对应的是数值1
		NUM1[1]=48;
		NUM1[2]=46;//NUM1[2]='.';显示小数点
		NUM1[3]=(c+48);
		NUM1[4]=(d+48);
		NUM1[5]=(e+48);
		NUM1[6]=86;//NUM1[5]='V';显示单位
		for(j=1;j<7;j++){
			TXREG=NUM1[j];
			while(TRMT!=1){ // 不为一说明发送未完成,则等待        
   			}
		}
	}
	if(flag_2==1)
	{
		NUM1[0]=48;	//ASCII码49对应的是数值1
		NUM1[1]=(b+48);	//ASCII码49对应的是数值1
		NUM1[2]=46;//NUM1[2]='.';显示小数点
		NUM1[3]=(c+48);
		NUM1[4]=(d+48);
		NUM1[5]=(e+48);
		NUM1[6]=86;//NUM1[5]='V';显示单位
		for(j=1;j<7;j++){
			TXREG=NUM1[j];
			while(TRMT!=1){ // 不为一说明发送未完成,则等待        
   			}
		}
	}
	if((flag_1==0)&&(flag_2==0))
	{
		NUM1[0]=(a+48);	//ASCII码49对应的是数值1
		NUM1[1]=(b+48);	//ASCII码49对应的是数值1
		NUM1[2]=46;//NUM1[2]='.';显示小数点
		NUM1[3]=(c+48);
		NUM1[4]=(d+48);
		NUM1[5]=(e+48);
		NUM1[6]=86;//NUM1[5]='V';显示单位
		for(j=0;j<7;j++){
		TXREG=NUM1[j];
		while(TRMT!=1){ // 不为一说明发送未完成,则等待        
   			}
		}

	}
	flag_1=0;
	flag_2=0;
}

/*显示采集到的数据,*.***A*/
/*数据显示精确到小数点下两位小数*/
void Show_num_3(int NUM)
{
	int a,b,c,d,flag_1,flag_2;
	flag_1=0;flag_2=0;
/*flag_1置位,说明数值范围为0~1000*/
/*flag_1置位,说明数值范围为1000~10000*/
	char NUM1[6];//定义字符数组
	/*判断数值所处的范围*/
	if(NUM<1000){
		flag_1=1;	//置标志位,若此标志位为1,则说明是三位数
	}
	if((NUM<10000)&&(NUM>=1000)){
	flag_2=1;	//置标志位,若此标志位为1,则说明是四位数
	}
	
	a=NUM/1000;
	b=((NUM%1000)/100);
	c=((NUM%100)/10);
	d=(NUM%10);
	if(flag_1==1)	/*三位数*/
	{	
		NUM1[0]=48;
		NUM1[1]=46;//NUM1[1]='.';显示小数点
		NUM1[2]=(b+48);
		NUM1[3]=(c+48);
		NUM1[4]=(d+48);
		NUM1[5]=65;//NUM1[5]='A';显示单位
		for(j=0;j<6;j++){
			TXREG=NUM1[j];
			while(TRMT!=1){ // 不为一说明发送未完成,则等待        
   			}
		}
	}
	if(flag_2==1)	/*四位数*/
	{
		NUM1[0]=(a+48);
		NUM1[1]=46;//NUM1[2]='.';显示小数点
		NUM1[2]=(b+48);
		NUM1[3]=(c+48);
		NUM1[4]=(d+48);
		NUM1[5]=65;//NUM1[5]='A';显示单位
		for(j=0;j<6;j++){
			TXREG=NUM1[j];
			while(TRMT!=1){ // 不为一说明发送未完成,则等待        
   			}
		}
	}
	flag_1=0;
	flag_2=0;
}








usart.h

/*****************************************************************/
#ifndef __USART_H__
#define __USART__


#include "pic.h"
#include
#include




int j;
void Usart_init();
void Show_array(char array[],int n);
void Show_num_4(int NUM);
void show_CCPRXL(int a,int b);
void Show_num_1(int NUM);/*显示采集到的数据,数据显示精确到小数点下两位小数,电压*/
void Show_num_3(int NUM);/*显示采集到的数据,数据显示精确到小数点下两位小数,电流*/
#endif


delay.c

#include 

/********************************
函数名称:void delay(unsigned int n)
函数功能:毫秒延时
返回值:无
*********************************/
void delay(unsigned int n)
{
	int j;
	char k;
	for(j=0;j0;k--)
			nop();
}

delay.h

/*****************************************************************/
#ifndef	__DELAY_H__
#define	__DELAY__
#define nop() asm("nop")

#include "pic.h"

/*毫秒延时函数*/
void delay(unsigned int n);

#endif

mcp2515.h

#ifndef	_MCP2515_H_
#define	_MCP2515_H_

//	write your header here
//#pragma nolist
/*********************************************************************
 *   CAN MCP2510 C definitions file                                  *
 *********************************************************************
 *   Filename:       2515REGS.h                                      *
 *   Date:           06/17/03                                        *
 *   File Version:   1.00 (Beta)                                     *
 *********************************************************************
 *   Functions:                                                      *
 *               Header file                                         *
 *********************************************************************
 *   Revision History:                                               *
 *    06/17/03 Updated from MCP2510.inc which was for the 756 board  *
 *********************************************************************/


/*******************************************************************
 *                   Register Definitions                          *
 *                   寄存器定义                                    *
 *******************************************************************/

/* Configuration Registers */
#define CANSTAT          0x0E			//CAN状态寄存器
#define CANCTRL          0x0F			//CAN控制寄存器
#define BFPCTRL          0x0C			//接收引脚控制和状态寄存器
#define TEC              0x1C			//发送错误计数器
#define REC              0x1D			//接收错误计数器
#define CNF3             0x28			//配置寄存器3
#define CNF2             0x29			//配置寄存器2
#define CNF1             0x2A			//配置寄存器1
#define CANINTE          0x2B			//中断使能寄存器
#define CANINTF          0x2C			//中断标志寄存器,写0则清除相应的中断
#define EFLG             0x2D			//错误标志寄存器,最高两位必须由MCU复位
#define TXRTSCTRL        0x0D			//发送请求引脚配置寄存器

/*  Recieve Filters */
#define RXF0SIDH         0x00			//验收滤波器0标准标识符高字节
#define RXF0SIDL         0x01			//验收滤波器0标准标识符低字节
#define RXF0EID8         0x02			//验收滤波器0扩展标识符高字节
#define RXF0EID0         0x03			//验收滤波器0扩展标识符低字节
#define RXF1SIDH         0x04			//验收滤波器1标准标识符高字节
#define RXF1SIDL         0x05			//验收滤波器1标准标识符低字节
#define RXF1EID8         0x06			//验收滤波器1扩展标识符高字节
#define RXF1EID0         0x07			//验收滤波器1扩展标识符低字节
#define RXF2SIDH         0x08			//验收滤波器2标准标识符高字节
#define RXF2SIDL         0x09			//验收滤波器2标准标识符低字节
#define RXF2EID8         0x0A			//验收滤波器2扩展标识符高字节
#define RXF2EID0         0x0B			//验收滤波器2扩展标识符低字节
#define RXF3SIDH         0x10			//验收滤波器3标准标识符高字节
#define RXF3SIDL         0x11			//验收滤波器3标准标识符低字节
#define RXF3EID8         0x12			//验收滤波器3扩展标识符高字节
#define RXF3EID0         0x13			//验收滤波器3扩展标识符低字节
#define RXF4SIDH         0x14			//验收滤波器4标准标识符高字节
#define RXF4SIDL         0x15			//验收滤波器4标准标识符低字节
#define RXF4EID8         0x16			//验收滤波器4扩展标识符高字节
#define RXF4EID0         0x17			//验收滤波器4扩展标识符低字节
#define RXF5SIDH         0x18			//验收滤波器5标准标识符高字节
#define RXF5SIDL         0x19			//验收滤波器5标准标识符低字节
#define RXF5EID8         0x1A			//验收滤波器5扩展标识符高字节
#define RXF5EID0         0x1B			//验收滤波器5扩展标识符低字节

/* Receive Masks */
#define RXM0SIDH         0x20			//验收屏蔽寄存器0标准标识符高字节
#define RXM0SIDL         0x21			//验收屏蔽寄存器0标准标识符低字节
#define RXM0EID8         0x22			//验收屏蔽寄存器0扩展标识符高字节
#define RXM0EID0         0x23			//验收屏蔽寄存器0扩展标识符低字节
#define RXM1SIDH         0x24			//验收屏蔽寄存器1标准标识符高字节
#define RXM1SIDL         0x25			//验收屏蔽寄存器1标准标识符低字节
#define RXM1EID8         0x26			//验收屏蔽寄存器1扩展标识符高字节
#define RXM1EID0         0x27			//验收屏蔽寄存器1扩展标识符低字节

/* Tx Buffer 0 */
#define TXB0CTRL         0x30			//发送缓冲器0控制寄存器
#define TXB0SIDH         0x31			//标准标识符高字节
#define TXB0SIDL         0x32			//标准标识符低字节
#define TXB0EID8         0x33			//扩展标识符高字节
#define TXB0EID0         0x34			//扩展标识符低字节
#define TXB0DLC          0x35			//发送缓冲器0数据长度寄存器
#define TXB0D0           0x36			//发送缓冲器0数据寄存器起始地址
#define TXB0D1           0x37
#define TXB0D2           0x38
#define TXB0D3           0x39
#define TXB0D4           0x3A
#define TXB0D5           0x3B
#define TXB0D6           0x3C
#define TXB0D7           0x3D
                         
/* Tx Buffer 1 */
#define TXB1CTRL         0x40			//发送缓冲器1控制寄存器
#define TXB1SIDH         0x41			//标准标识符高字节
#define TXB1SIDL         0x42			//标准标识符低字节
#define TXB1EID8         0x43			//扩展标识符高字节
#define TXB1EID0         0x44			//扩展标识符低字节
#define TXB1DLC          0x45			//发送缓冲器1数据长度寄存器
#define TXB1D0           0x46			//发送缓冲器1数据寄存器起始地址
#define TXB1D1           0x47
#define TXB1D2           0x48
#define TXB1D3           0x49
#define TXB1D4           0x4A
#define TXB1D5           0x4B
#define TXB1D6           0x4C
#define TXB1D7           0x4D

/* Tx Buffer 2 */
#define TXB2CTRL         0x50			//发送缓冲器2控制寄存器
#define TXB2SIDH         0x51			//标准标识符高字节
#define TXB2SIDL         0x52			//标准标识符低字节
#define TXB2EID8         0x53			//扩展标识符高字节
#define TXB2EID0         0x54			//扩展标识符低字节
#define TXB2DLC          0x55			//发送缓冲器2数据长度寄存器
#define TXB2D0           0x56			//发送缓冲器2数据寄存器起始地址
#define TXB2D1           0x57
#define TXB2D2           0x58
#define TXB2D3           0x59
#define TXB2D4           0x5A
#define TXB2D5           0x5B
#define TXB2D6           0x5C
#define TXB2D7           0x5D
                         
/* Rx Buffer 0 */
#define RXB0CTRL         0x60			//接收缓冲器0控制寄存器
#define RXB0SIDH         0x61			//接收缓冲器0标准标识符高字节
#define RXB0SIDL         0x62			//接收缓冲器0标准标识符低字节
#define RXB0EID8         0x63			//接收缓冲区0扩展标识符高字节
#define RXB0EID0         0x64			//接收缓冲区0扩展标识符低字节
#define RXB0DLC          0x65			//接收缓冲区0数据码长度
#define RXB0D0           0x66			//接收缓冲区0数据寄存器起始地址
#define RXB0D1           0x67
#define RXB0D2           0x68
#define RXB0D3           0x69
#define RXB0D4           0x6A
#define RXB0D5           0x6B
#define RXB0D6           0x6C
#define RXB0D7           0x6D
                         
/* Rx Buffer 1 */
#define RXB1CTRL         0x70			//接收缓冲器1控制寄存器
#define RXB1SIDH         0x71			//接收缓冲器0标准标识符高字节
#define RXB1SIDL         0x72			//接收缓冲器0标准标识符低字节
#define RXB1EID8         0x73			//接收缓冲区0扩展标识符高字节
#define RXB1EID0         0x74			//接收缓冲区0扩展标识符低字节
#define RXB1DLC          0x75			//接收缓冲区1数据码长度
#define RXB1D0           0x76			//接收缓冲区1数据寄存器起始地址
#define RXB1D1           0x77
#define RXB1D2           0x78
#define RXB1D3           0x79
#define RXB1D4           0x7A
#define RXB1D5           0x7B
#define RXB1D6           0x7C
#define RXB1D7           0x7D
                         

/*******************************************************************
 *               Bit register masks                                 *
 *                位寄存器掩码                                      *
 定义TXBnCTRL 寄存器的命令字
 *******************************************************************/

/* TXBnCTRL */
#define TXREQ            0x08			
#define TXP              0x03			    

/* RXBnCTRL */
#define RXM              0x60
#define BUKT             0x04

/* CANCTRL */
#define REQOP            0xE0
#define ABAT             0x10
#define	OSM         	 0x08
#define CLKEN            0x04
#define CLKPRE           0x03

/* CANSTAT */
#define REQOP            0xE0
#define ICOD             0x0E

/* CANINTE */  
#define RX0IE            0x01
#define RX1IE            0x02
#define TX0IEE           0x04
#define TX1IEE           0x80
#define TX2IEE           0x10
#define ERRIE            0x20
#define WAKIE            0x40
#define MERRE            0x80


/*******************************************************************
 *                    CANINTF                                      *
 *                    定义MCP2515的中断使能寄存器命令字            *
 *******************************************************************/
 
#define RX0IF            0x01			//接收缓冲器0满中断使能位
#define RX1IF            0x02			//接收缓冲器1满中断使能位
#define TX0IFF           0x04			//发送缓冲器0空中断使能位
#define TX1IFF           0x80			//发送缓冲器1空中断使能位
#define TX2IFF           0x10			//发送缓冲器2空中断使能位
#define ERRIF            0x20			//错误中断使能位
#define WAKIF            0x40			//唤醒中断使能位
#define MERRF            0x80			//报文错误中断使能位

/* BFPCTRL */
#define B1BFS            0x20
#define B0BFS            0x10
#define B1BFE            0x08
#define B0BFE            0x04
#define B1BFM            0x02
#define B0BFM            0x01

/* CNF1 Masks */
#define SJW              0xC0
#define BRP              0x3F

/* CNF2 Masks */
#define BTLMODE          0x80
#define SAM              0x40
#define PHSEG1           0x38
#define PRSEG            0x07

/* CNF3 Masks */
#define WAKFIL           0x40
#define PHSEG2           0x07

/* TXRTSCTRL Masks */
#define TXB2RTS          0x04
#define TXB1RTS          0x02
#define TXB0RTS          0x01


/*******************************************************************
 *                    Bit Timing Configuration                     *
 *                    位定时配置                                   *
 *******************************************************************/
 
/* CNF1 */
#define SJW_1TQ          0x40
#define SJW_2TQ          0x80
#define SJW_3TQ          0x90
#define SJW_4TQ          0xC0

/* CNF2 */
#define BTLMODE_CNF3     0x80
#define BTLMODE_PH1_IPT  0x00

#define SMPL_3X          0x40
#define SMPL_1X          0x00

#define PHSEG1_8TQ       0x38
#define PHSEG1_7TQ       0x30
#define PHSEG1_6TQ       0x28
#define PHSEG1_5TQ       0x20
#define PHSEG1_4TQ       0x18
#define PHSEG1_3TQ       0x10
#define PHSEG1_2TQ       0x08
#define PHSEG1_1TQ       0x00

#define PRSEG_8TQ        0x07
#define PRSEG_7TQ        0x06
#define PRSEG_6TQ        0x05
#define PRSEG_5TQ        0x04
#define PRSEG_4TQ        0x03
#define PRSEG_3TQ        0x02
#define PRSEG_2TQ        0x01
#define PRSEG_1TQ        0x00

/* CNF3 */
#define PHSEG2_8TQ       0x07
#define PHSEG2_7TQ       0x06
#define PHSEG2_6TQ       0x05
#define PHSEG2_5TQ       0x04
#define PHSEG2_4TQ       0x03
#define PHSEG2_3TQ       0x02
#define PHSEG2_2TQ       0x01
#define PHSEG2_1TQ       0x00

#define SOF_ENABLED      0x80
#define WAKFIL_ENABLED   0x40
#define WAKFIL_DISABLED  0x00    


/*******************************************************************
 *                  Control/Configuration Registers                *
 *                   控制/配置寄存器                               *
 *******************************************************************/

/* CANINTE */
#define RX0IE_ENABLED    0x01
#define RX0IE_DISABLED   0x00
#define RX1IE_ENABLED    0x02
#define RX1IE_DISABLED   0x00
#define G_RXIE_ENABLED   0x03
#define G_RXIE_DISABLED  0x00

#define TX0IE_ENABLED    0x04
#define TX0IE_DISABLED   0x00
#define TX1IE_ENABLED    0x08
#define TX2IE_DISABLED   0x00
#define TX2IE_ENABLED    0x10
#define TX2IE_DISABLED   0x00
#define G_TXIE_ENABLED   0x1C
#define G_TXIE_DISABLED  0x00

#define ERRIE_ENABLED    0x20
#define ERRIE_DISABLED   0x00
#define WAKIE_ENABLED    0x40
#define WAKIE_DISABLED   0x00
#define IVRE_ENABLED     0x80
#define IVRE_DISABLED    0x00

/* CANINTF */
#define RX0IF_SET        0x01
#define RX0IF_RESET      0x00
#define RX1IF_SET        0x02
#define RX1IF_RESET      0x00
#define TX0IF_SET        0x04
#define TX0IF_RESET      0x00
#define TX1IF_SET        0x08
#define TX2IF_RESET      0x00
#define TX2IF_SET        0x10
#define TX2IF_RESET      0x00
#define ERRIF_SET        0x20
#define ERRIF_RESET      0x00
#define WAKIF_SET        0x40
#define WAKIF_RESET      0x00
#define IVRF_SET         0x80
#define IVRF_RESET       0x00

/* CANCTRL */ 
#define REQOP_CONFIG     0x80
#define REQOP_LISTEN     0x60
#define REQOP_LOOPBACK   0x40
#define REQOP_SLEEP      0x20
#define REQOP_NORMAL     0x00

#define ABORT            0x10

#define OSM_ENABLED      0x08

#define CLKOUT_ENABLED   0x04
#define CLKOUT_DISABLED  0x00
#define CLKOUT_PRE_8     0x03
#define CLKOUT_PRE_4     0x02
#define CLKOUT_PRE_2     0x01
#define CLKOUT_PRE_1     0x00

/* CANSTAT */
/* 定义MCP255的CAN工作模式 */
#define OPMODE_CONFIG    0x80			//配置模式     
#define OPMODE_LISTEN    0x60			//仅监听模式
#define OPMODE_LOOPBACK  0x40			//环回模式
#define OPMODE_SLEEP     0x20			//休眠模式
#define OPMODE_NORMAL    0x00			//正常工作模式


/* RXBnCTRL */
#define RXM_RCV_ALL      0x60
#define RXM_VALID_EXT    0x40
#define RXM_VALID_STD    0x20
#define RXM_VALID_ALL    0x00

#define RXRTR_REMOTE     0x08
#define RXRTR_NO_REMOTE  0x00

#define BUKT_ROLLOVER    0x04
#define BUKT_NO_ROLLOVER 0x00

#define FILHIT0_FLTR_1   0x01
#define FILHIT0_FLTR_0   0x00

#define FILHIT1_FLTR_5   0x05
#define FILHIT1_FLTR_4   0x04
#define FILHIT1_FLTR_3   0x03
#define FILHIT1_FLTR_2   0x02
#define FILHIT1_FLTR_1   0x01
#define FILHIT1_FLTR_0   0x00


/* TXBnCTRL */
#define TXREQ_SET        0x08			//报文发送请求位
#define TXREQ_CLEAR      0x00

#define TXP_HIGHEST      0x03
#define TXP_INTER_HIGH   0x02
#define TXP_INTER_LOW    0x01
#define TXP_LOWEST       0x00
    

/*******************************************************************
 *                  Register Bit Masks        寄存器位掩码         *
 *******************************************************************/
 
#define DLC_0            0x00
#define DLC_1            0x01
#define DLC_2            0x02
#define DLC_3            0x03
#define DLC_4            0x04
#define DLC_5            0x05
#define DLC_6            0x06
#define DLC_7            0x07    
#define DLC_8            0x08
 

/*******************************************************************
 *                  CAN SPI commands                               *
 *                  定义MCP2515的SPI操作的CAN指令                  *
 *******************************************************************/

#define CAN_RESET        0xC0			//复位
#define CAN_READ         0x03			//从寄存器中读出数据
#define CAN_WRITE        0x02			//向寄存器中写入数据
#define CAN_RTS          0x80			//发送请求
#define CAN_RTS_TXB0     0x81
#define CAN_RTS_TXB1     0x82
#define CAN_RTS_TXB2     0x84
#define CAN_RD_STATUS    0xA0			//读取寄存器状态
#define CAN_BIT_MODIFY   0x05			//位修改指令
#define CAN_RX_STATUS    0xB0			//快速确定与报文和报文类型相匹配的滤波器
#define CAN_RD_RX_BUFF   0x90			//读RX缓冲器指令
										//
#define CAN_LOAD_TX      0X40			//装载TX缓冲器指令
									

/*******************************************************************
 *                  Miscellaneous 杂项                             *
 *******************************************************************/

#define DUMMY_BYTE       0x00
#define TXB0             0x31
#define TXB1             0x41
#define TXB2             0x51
#define RXB0             0x61
#define RXB1             0x71
#define EXIDE_SET        0x08
#define EXIDE_RESET      0x00
#endif

spi_887.c
#include 

/****************************
函数:void Init_Spi(void)
函数描述:初始化SPI
变量:无
*******************************/
void Init_Spi(void)
{
	TRISC=0b00010000;//RC5/SDO为输出,RC4/SDI为输入,RC3/SCK为输出

/*
SSPSTAT_SMP=0;//在数据输出时间的中间采样输入数据
CKE:SPI 时钟边沿选择位   CKP = 0: STAT_CKE=1 在SCK 引脚的上升沿发送数据
*/
	SSPSTAT=0X40;//在数据输出时间的中间采样输入数据  bit 7,SMP=0,采样位

/*
SSPEN=1;使能串行端口并将SCK、SDO、SDI 和SS 配置为串行端口引脚
CKP=0;空闲时钟为低电平
SSPM<3:0>=0001,SPI 主控模式,时钟 = FOSC/16
*/
	SSPCON=0x21;//bit 4,CKP:时钟极性选择位,0 = 时钟空闲状态为低电平

	TRISD=0b00001100;//RD0输出,RD1输出;RD2输入,RD3输入;
	PORTD=0b00000000;//输出为低,输入高阻态;
}


/****************************
函数:char SPIRecvByte(void)
函数描述:从SPI总线上读取一个字节数据
变量:BUF
*******************************/
char SPIRecvByte(void)
{
	char BUF;	
	SSPBUF=0x00;
	delay(2);	
	BUF=SSPBUF;
	delay(20);	
	return BUF;
}


/****************************
函数:void SPISendByte(unsigned char dat)
函数描述:向SPI总线上发送一个字节数据
变量:无
*******************************/
void SPISendByte(unsigned char dat)
{
	SSPBUF=dat;//往缓冲里面写入dat
//	while(!SSPIF)//等待写入成功
//	SSPIF=0;//SSPIF清零
	delay(20);
}


/****************************
函数:void CAN_Write(uchar address ,uchar Value)
函数描述:往MCP2515指定地址addr写一个字节数据value
变量:无
*******************************/
void CAN_Write(uchar address ,uchar Value)
{	
	CS=0;
	SPISendByte(0x02);//写命令
	SPISendByte(address);//写地址
	SPISendByte(Value);//写数据	
	CS=1;
}


/****************************
函数:char CAN_Read(uchar address)
函数描述:从MCP2515指定地址addr读取一个字节数据value
变量:BUF
*******************************/
char CAN_Read(uchar address)
{
	char BUF;
	CS=0;	
	SPISendByte(0x03);//读命令
	SPISendByte(address);//读地址
	BUF=SPIRecvByte();//读一个字节数据	
	CS=1;
	return BUF;
}


/****************************
函数:void SPIReset(void)
函数描述:SPI复位
变量:无
*******************************/
void SPIReset(void)
{	
	SSPBUF=0XC0;//CAN_RESET=0XC0
	delay(20);		
}


/****************************
函数:void CAN_Set_Var(uchar address,uchar mask,uchar dat)
函数描述:修改寄存器的值,mask为掩码
变量:无
*******************************/
void CAN_Set_Var(uchar address,uchar mask,uchar dat)
{
	CS=0;
	delay(10);
	SPISendByte(0x05);//位修改命令 CAN_BIT_MODIFY
//CANCTRL——CAN 控制寄存器(地址:XFh)	
	SPISendByte(address);//地址为0fH
	SPISendByte(mask);//掩码为E0H,修改CANCTRL的高三位
	SPISendByte(dat);
	CS=1;//片选
}

spi_887.h

/*****************************************************************/
#ifndef	__SPI_h__
#define	__SPI_h__

#include 
#include 

#define uchar unsigned char
#define uint  unsigned int

#define CS 	   RD1	//标签为CANCSRH4
#define RESET  RD0  //标签为RESETCAN

/************************************************************/
void Init_Spi(void);
char SPIRecvByte(void);
void SPISendByte(uchar dat);
void CAN_Write(uchar address ,uchar Value);			//向寄存器地址写入数据
char CAN_Read(uchar address);						//从寄存器地址读取数据
void SPIReset(void);
void CAN_Set_Var(uchar address,uchar mask,uchar dat);

#endif

adc.c

#include 


/****************************
函数:unsigned int get_ad()
函数描述:调用AD子程序,获取ADC转换后的值
变量:adval
*******************************/
unsigned int get_ad(){
	unsigned int adval,ad;
	GO=1;//启动AD转换
//	delay(1);
	for(i=1;i<10;i++) nop();		/*延时20us*/
	while(GO);
	adval=ADRESH<<8|ADRESL;
	return(adval);
}


/*左侧电池盒电压*/
/*ADC采集端口初始化函数,初始化片内ADC1,采集右路电压*/
/*ADCON0,A/D控制寄存器0,A/D转换时钟选择为八分之一频率,采集端口为RA0,模拟通道选择AN0*/
/*A/D转换完成/或不在进行中,使能ADC.*/
void init_ADC1(void)
{
	TRISA=0XFF;//RA0设置为AN0(AD采集端口),端口配置为输入。
	ADCON0=0b01000001;//AD时钟选择(与ADCON1的位6一起)
	ADCON1=0b10000000;//通道选择,AD模块使能
}

/*左侧电池盒电流*/
/*ADC采集端口初始化函数,初始化片内ADC5,采集R7两端电压*/
/*采集端口为RA5,模拟通道选择AN4.*/
void init_ADC5(void)
{
	TRISA=0XFF;//RA5设置为AN4(AD采集端口),端口配置为输入。
	ADCON0=0b01010001;//AD时钟选择(与ADCON1的位6一起)
	ADCON1=0b10000000;//通道选择,AD模块使能
}


/*右侧电池盒电压*/
/*ADC采集端口初始化函数,初始化片内ADC2,采集左路电压*/
/*ADCON0,A/D控制寄存器0,A/D转换时钟选择为八分之一频率,采集端口为RA1,模拟通道选择AN1*/
/*A/D转换完成/或不在进行中,使能ADC.*/
void init_ADC2(void)
{
	TRISA=0XFF;//RA1设置为AN1(AD采集端口),端口配置为输入。
	ADCON0=0b01000101;//AD时钟选择(与ADCON1的位6一起)
	ADCON1=0b10000000;//通道选择,AD模块使能
}


/*右侧电池盒电流*/
/*ADC采集端口初始化函数,初始化片内ADC6,采集R14两端电压.*/
/*采集端口为RE0,模拟通道选择AN5.*/
void init_ADC6(void)
{
	TRISE=0XFF;//RE0设置为AN5(AD采集端口),端口配置为输入。
	ADCON0=0b01010101;//AD时钟选择(与ADCON1的位6一起)
	ADCON1=0b10000000;//通道选择,AD模块使能
}


/*ADC采集端口初始化函数,初始化片内ADC3,采集R69两端电压*/
/*ADCON0,A/D控制寄存器0,A/D转换时钟选择为八分之一频率,采集端口为RA2,模拟通道选择AN2*/
/*A/D转换完成/或不在进行中,使能ADC.*/
void init_ADC3(void)
{
	TRISA=0XFF;//配置PORTA的引脚全为输入。
	ADCON0=0b01001001;
	ADCON1=0b10000000;	/*A/D控制寄存器1,A/D转换结果格式为右对齐*/
}


/*ADC采集端口初始化函数,初始化片内ADC4,采集R70两端电压*/
/*ADCON0,A/D控制寄存器0,A/D转换时钟选择为八分之一频率,采集端口为RA3,模拟通道选择AN3*/
/*A/D转换完成/或不在进行中,使能ADC.*/
void init_ADC4(void)
{
	TRISA=0XFF;//配置PORTA的引脚全为输入。
	ADCON0=0b01001101;
	ADCON1=0b10000000;	/*A/D控制寄存器1,A/D转换结果格式为右对齐*/
}


/****************************************
A、名称:递推平均滤波法(又称滑动平均滤波法)
B、方法:
把连续取得的N个采样值看成一个队列,队列的长度固定为N,
每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据(先进先出原则),
把队列中的N个数据进行算术平均运算,获得新的滤波结果。
N值的选取:流量,N=12;压力,N=4;液面,N=4-12;温度,N=1-4。
C、优点:
对周期性干扰有良好的抑制作用,平滑度高;
适用于高频振荡的系统。
D、缺点:
灵敏度低,对偶然出现的脉冲性干扰的抑制作用较差;
不易消除由于脉冲干扰所引起的采样值偏差;
不适用于脉冲干扰比较严重的场合;
比较浪费RAM。
E、整理:Alex
*********************************/
int filter()
{
	int i;
	int filter_sum = 0;
	for(i = 0; i < FILTER_N; i++) 
	{
		filter_buf[i] = get_ad();	//AD转换的值赋给数组最后一个值
		filter_sum += filter_buf[i];
		delay(1);	
	}
	filter_sum=filter_sum/100;
	filter_sum=filter_sum*102;
	return (int)(filter_sum/FILTER_N);
}


/****************************
函数:void show_temp(void)
函数描述:采集两路的温度值,串口打印输出,根据温度控制风扇。。
变量:无
*******************************/
void show_temp(void)
{
	/*ADCOUTV3,ADCOUTV4,R69端电压采集点,R70端电压采集点*/
	int ADCOUTV3;
	int ADCOUTV4;	
/*测量整个电路中的温度,串口打印出输出*/
/*采集1路温度传感器的值*/
	init_ADC3();			//ADC采集端口初始化	
	ADCOUTV3=filter();		//调用AD子程序		
/*采集2路温度传感器的值*/
	init_ADC4();			//ADC采集端口初始化	
	ADCOUTV4=filter();		//调用AD子程序		
/*风扇的运行,完全靠检测到的温度来控制*/	
/*设定控制风扇转动的温度点,45度风扇转。40.4左右。*/
	if(((ADCOUTV3<450)||(ADCOUTV4<450))&&(ADCOUTV3!=0)&&(ADCOUTV4!=0)){	
		FAN=1;//风扇打开				
	}
/*设定控制风扇转动的温度点,35度风扇停。*/		
	if((ADCOUTV3>560)&&(ADCOUTV4>560)){					
		FAN=0;//风扇关闭
	}				
/*当整个充电电路温度升高到例如60度时,控制充电过程截止。*/
	if(((ADCOUTV3<350)||(ADCOUTV4<350))&&(ADCOUTV3!=0)&&(ADCOUTV4!=0)){			
		CCPR1L=160;//关断充电	
		CCPR2L=160;//关断充电		
	}	
/*由于采用递推平均滤波法的原因,刚才是数值从0开始增加到稳定值*/
/*会造成刚开机时,风扇的误动作,待稳定输出后,动作无误*/
}


/****************************
函数:void Bat1_Volt(void)
函数描述:检测1路的电压值
变量:无
*******************************/
void Bat1_Volt(void)
{	
/*采集和显示部分*/
	/*ADCOUTV1,U1路输出从ADC采集的电压;ADC5IV1,R7两端从ADC采集的电压*/
	int ADCOUTV1;
	/*ADCOUTV1,U1路输出电压用于中间转换的浮点型值;ADC5IV1,R7两端电压用于中间转换的浮点型值*/
	float num1;	
	/*NUM1,U1路输出电压用于串口显示和判断的整型值;NUM2,R7两端的电压用于串口显示和判断的整型值*/
	int NUM1;	
/**上电后,第一次采集OUTV1的电压,继而判断此时是否有电池接入**/
/*第一路,即电路板右侧,JP1部分充电电路*/
/*采集U1路输出电压,OUTV1,单位为V*/
	init_ADC1();			//ADC采集2路电压值	
	/****调用AD子程序****/
	ADCOUTV1=filter();		//调用AD子程序			
/*换算出OUTV1的电压值*/	
/*对ADCOUTV1进行运算,得到浮点型数num1*/
	num1=ADCOUTV1*34.6752;	//理论值为34.47561553030303,实测值34.67529820407434
/*将浮点型数num1转换成整形数NUM1*/
	Bat_1.volt=(int)num1;										//左电池充电电路中的电压		
}


/****************************
函数:void Bat1_Curr(void)
函数描述:检测1路的电流值
变量:无
*******************************/
void Bat1_Curr(void)
{	
/*采集和显示部分*/
	/*ADC5IV1,R7两端从ADC采集的电压*/
	int ADC5IV1;
	/*ADC5IV1,R7两端电压用于中间转换的浮点型值*/
	float num2;		
/*采集R7两端的电压,ADC5IV1,单位为V*/
/*首先采集的是与单片机直接相连的ADC5IV1*/
	init_ADC5();			//ADC采集ADC5IV1的电压值	
	/****调用AD子程序****/
	ADC5IV1=filter();		//调用AD子程序					
/*换算出流经R8电流的值*/
/*对ADCOUTV5进行运算,得到浮点型数num2*/
	num2=ADC5IV1*4.883;		
/*换算出流经R8电流的值*/
	Bat_1.cur=(int)num2;	//左电池充电电路中的电流	
}


/****************************
函数:void Bat2_Volt(void)
函数描述:检测2路的电压值
变量:无
*******************************/
void Bat2_Volt(void)
{	
/*采集和显示部分*/
	/*ADCOUTV2,U2路输出从ADC采集的电压;ADC6IV1,R14两端从ADC采集的电压*/
	int ADCOUTV2;
	/*ADCOUTV2,U2路输出电压用于中间转换的浮点型值;ADC6IV1,R14两端电压用于中间转换的浮点型值*/
	float num1;		
/**上电后,第一次采集OUTV1的电压,继而判断此时是否有电池接入**/
/*第一路,即电路板右侧,JP1部分充电电路*/
/*采集U1路输出电压,OUTV1,单位为V*/
	init_ADC2();			//ADC采集2路电压值	
	/****调用AD子程序****/
	ADCOUTV2=filter();		//调用AD子程序			
/*换算出OUTV1的电压值*/	
/*对ADCOUTV1进行运算,得到浮点型数num1*/
	num1=ADCOUTV2*34.6752;	//理论值为34.47561553030303,实测值34.67529820407434	
/*将浮点型数num1转换成整形数NUM1*/	
	Bat_2.volt=(int)num1;										//左电池充电电路中的电压	
}


/****************************
函数:void Bat2_Curr(void)
函数描述:检测2路的电流值
变量:无
*******************************/
void Bat2_Curr(void)
{	
/*采集和显示部分*/
	/*ADC6IV1,R14两端从ADC采集的电压*/
	int ADC6IV1;
	/*ADC6IV1,R14两端电压用于中间转换的浮点型值*/
	float num2;		
/*采集R7两端的电压,ADC5IV1,单位为V*/
/*首先采集的是与单片机直接相连的ADC5IV1*/
	init_ADC6();			//ADC采集ADC5IV1的电压值	
	/****调用AD子程序****/
	ADC6IV1=filter();		//调用AD子程序					
/*换算出流经R8电流的值*/
/*对ADCOUTV5进行运算,得到浮点型数num2*/
	num2=ADC6IV1*4.883;		
/*换算出流经R8电流的值*/
	Bat_2.cur=(int)num2;	//左电池充电电路中的电流	
}

adc.h
/*****************************************************************/
#ifndef	__ADC_h__
#define	__ADC_h__

#include 
#include 
#include 
#include 
#include 

#define FILTER_N 4				/* N值可根据实际情况调整 排序采用冒泡法*/  
int filter_buf[FILTER_N + 1];
unsigned int get_ad();			/*调用AD子程序,获取ADC转换后的值*/
int filter();					/*使用递推平均滤波法的滤波函数*/
void init_ADC1(void);			/*ADC采集端口初始化函数,初始化片内ADC1,采集左侧1路电池盒输出电压、电路板右边电路*/
void init_ADC2(void);			/*ADC采集端口初始化函数,初始化片内ADC2,采集右侧2路电池盒输出电压、电路板左边电路*/
void init_ADC3(void);			/*ADC采集端口初始化函数,初始化片内ADC3,采集R69两端电压*/
void init_ADC4(void);			/*ADC采集端口初始化函数,初始化片内ADC4,采集R70两端电压*/
void init_ADC5(void);			/*ADC采集端口初始化函数,初始化片内ADC5,采集左侧1路电池盒输出电流、电路板右边电路*/
void init_ADC6(void);			/*ADC采集端口初始化函数,初始化片内ADC6,采集右侧2路电池盒输出电流、电路板左边电路*/
void show_temp(void);			/*采集两路的温度值,串口打印输出,根据温度控制风扇*/
void Bat1_Volt(void);			/*检测1路的电压值*/
void Bat1_Curr(void);			/*检测1路的电流值*/
void Bat2_Volt(void);			/*检测2路的电压值*/
void Bat2_Curr(void);			/*检测2路的电流值*/
#endif

pwm.c

#include 

/****************************
函数:void Init_PWM(void)
函数描述:初始化配置PWM
变量:无
*******************************/
void Init_PWM(void)
{
/****定义PORTC****/
/*控制PWM脉冲输出部分*/
/*频率25MHZ,晶振选择为16MHZ*/
	TRISC=0X00;
	PORTC=0x00;
	CCP1CON=0;//clear CCP1CON reg
	CCP2CON=0;//clear CCP2CON reg
	PR2=159;//周期为40us
/*
	CCPR1L赋值160;CCP1CON的5、4两位赋值0b00时,占空比为100%;
	CCPR1L赋值  0;CCP1CON的5、4两位赋值0b00时,占空比为  0%;
*/
	CCPR1L=160;	
	CCPR2L=160;		//此时输出电压OUTV最小为19V左右。
	/*将RC1、RC2引脚配置为输出*/
	TRISCbits.TRISC1=0;	//make PWM pin an output
	TRISCbits.TRISC2=0;	//make PWM pin an output
	
	T2CON=0X00;	//Timer2,1 prescale,no postscaler  0 = 禁止Timer2   Timer2 时钟预分频比 00 = 预分频值为1
	CCP1CON=0X0C;	//PWM mode, 00 for DC1B1:B0  1100 = PWM 模式; P1A 和P1C 为高电平有效; P1B 和P1D 也为高电平有效
	CCP2CON=0X0C;	//PWM mode, 00 for DC1B1:B0  1100 = PWM 模式; P1A 和P1C 为高电平有效; P1B 和P1D 也为高电平有效2
	TMR2=0;	//clear Timer2   Timer2 模块寄存器  8 位定时器寄存器
	T2CONbits.TMR2ON=1;	//turn on Timer2 使能Timer2
}		








pwm.h

/*****************************************************************/
#ifndef	__PWM_h__
#define	__PWM_h__

#include 
#include 

void Init_PWM(void);						/*初始化PWM*/

#endif

int.c

#include 

/****************************
函数:void Init_Int(void)
函数描述:初始化中断
变量:无
*******************************/
void Init_Int(void)
{
	TRISB=0X01; //RB0为输入,其余为输出       
	PORTB=0x19; //RB0高阻态, RB3置1,RB4置1   
  
	ANSELH=0x00;  //将RB0(AN12)引脚被分配给端口或特殊功能。  
//必须初始化ANSELH 寄存器以将模拟通道配置为数字输入。配置为模拟输入的引脚将读为0。   
/* 
GIE = 1;  //GIE:  全局中断允许位   1 = 允许所有未被屏蔽的中断 
PEIE = 1; //PEIE: 外设中断允许位  1 = 允许所有未被屏蔽的外设中断 
INTE = 1; //INTE:INT 外部中断允许位 1 = 允许INT 外部中断 
RBIE = 1; //RBIE:PORTB 电平变化中断允许位 1 = 允许PORTB 电平变化中断 
INTF=0;   //INTF:INT 外部中断标志位 0 = 未发生INT 外部中断  
*/  
	INTCON=0XD8;    /*正确的*/ 

//	INTCON=0b11111000;    /*测试的*/ 
	WPUB = 0X01;//使能上拉    
/* 
INTEDG=0; //触发中断的边沿选择位   0 = INT 引脚下降沿触发中断 
*/  

 
	OPTION_REG=0x00;/*正确的*/



}

//中断服务程序
void interrupt ISR(void)
{
	if(INTF==1)//如果是INT中断才执行以下程序
	{
	INTF=0; 	
	canreflag=1;
	}
}

int.h

/*****************************************************************/
#ifndef	__INT_h__
#define	__INT_h__

#include 
void Init_Int(void);	/*初始化中断*/
char canreflag;
#endif

var.c

#include 
unsigned char cansentbuf[8];		/*用来存放发送数据的数组*/
unsigned char canrecebuf[8];		/*用来存放接收数据的数组*/
unsigned char canjudgbuf[10];		/*用来存放判断电池初始化是否成功数据的数组*/
char canreflag;
int i;
int count;
unsigned char dummy;
char CAN_FLAG;				/*CAN接收标志位*/
struct Bat_stat1 Bat_1; 	/* 不加extern ,默认认为extern */
struct Bat_stat2 Bat_2; 	/* 不加extern ,默认认为extern */



var.h

/*****************************************************************/
#ifndef	__VAR_h__
#define	__VAR_h__

#define LEDA  RB3  //定义灯1
#define LEDB  RB4  //定义灯2
#define ENA   RE2  //定义灯2

extern unsigned char cansentbuf[8];
extern unsigned char canrecebuf[8];
extern unsigned char canjudgbuf[10];
extern char canreflag;
extern int i;
extern int count;
extern unsigned char dummy;
extern char CAN_FLAG;//开机复位

/*左侧电池状态*/
// ------------------ 左侧电池状态数据的结构定义 ------------------------ //
extern struct Bat_stat1
{
unsigned int in;				//左电池进入充电站标志位
unsigned int init;			//左电池初始化完成标志位
unsigned int volt;			//左电池充电电路中的电压
unsigned int cur;			//左电池充电电路中的电流
unsigned int chg_full;		//充电完成标志位
unsigned int Soc;			//左电池电量Soc
unsigned int error;			//左电池故障标志位	
unsigned int error1;			//左电池过压、温度故障标志位	
unsigned int error2;			//左电池过流故障标志位	
}Bat_1;

/*右侧电池状态*/
// ------------------ 右侧电池状态数据的结构定义 ------------------------ //
extern struct Bat_stat2
{
unsigned int in;					//右电池进入充电站标志位
unsigned int init;				//右电池初始化完成标志位
unsigned int volt;				//右电池充电电路中的电压
unsigned int cur;				//右电池充电电路中的电流	
unsigned int chg_full;			//右电池充电完成标志位
unsigned int Soc;				//右电池电量Soc	
unsigned int error;				//右电池错误标志位
unsigned int error1;				//右电池过压、温度故障标志位	
unsigned int error2;				//右电池过流故障标志位	
}Bat_2;

#endif

bat.c

#include 

/****************************
函数:void Bat_init(void)
函数描述:初始化左右侧电池的状态标志位
变量:无
*******************************/			
void Bat_init(void)
{
/*对左右电池进入标志位清零*/
	
/*对左电池进入标志位清零*/	
	Bat_1.in=0;											/*左电池进入充电站标志位*/
	Bat_1.init=0;										/*左电池初始化完成标志位*/
	Bat_1.error=0;										/*左电池错误标志位*/
	Bat_1.volt=0;										/*左电池充电电路中的电压*/
	Bat_1.cur=0;										/*左电池充电电路中的电流*/
	Bat_1.chg_full=0;									/*左电池充电完成标志位*/
	Bat_1.Soc=0;										/*左电池电池容量*/
	Bat_1.error1=0;										/*左电池过压、温度故障标志位*/
	Bat_1.error2=0;										/*左电池过流故障标志位*/

/*对右电池进入标志位清零*/	
	Bat_2.in=0;											/*右电池进入充电站标志位*/
	Bat_2.init=0;										/*右电池初始化完成标志位*/
	Bat_2.error=0;										/*右电池错误标志位*/
	Bat_2.volt=0;										/*右电池充电电路中的电压*/
	Bat_2.cur=0;										/*右电池充电电路中的电流*/
	Bat_2.chg_full=0;									/*右电池充电完成标志位*/
	Bat_2.Soc=0;										/*右电池电池容量*/
	Bat_2.error1=0;										/*右电池过压、温度故障标志位*/
	Bat_2.error2=0;										/*右电池过流故障标志位*/
	
			
/*对cansentbuf、cansentbuf数组进行初始化*/
	for(i=0;i<8;i++)
	{
		cansentbuf[i]=0;
		canrecebuf[i]=0;
	}	
	for(i=0;i<8;i++)
	{
		canjudgbuf[i]=0;
	}	
}


/***************************
函数:void Bat_1_Reset(void)
函数描述:左侧电池状态复位
变量:无
*****************************/
void Bat_1_Reset(void)
{
	Bat_1.in=0;											/*将左电池进入充电站标志位清零*/
	Bat_1.init=0;										/*电池初始化未完成*/
	Bat_1.error=0;										/*电池无故障*/
	Bat_1.chg_full=0;									/*拔出电池盒,该电池充满位清零*/
	Bat_1.Soc=0;										/*拔出电池盒,该电量SOC位清零*/	
	Bat_1.error1=0;										/*左电池过压、温度故障标志位*/
	Bat_1.error2=0;										/*左电池过流故障标志位*/
	CCPR1L=160;											/*占空比的值为满*/
	LEDA=1;												/*亮绿灯*/
}


/***************************
函数:void Bat_2_Reset(void)
函数描述:右侧电池状态复位
变量:无
*****************************/
void Bat_2_Reset(void)
{
	Bat_2.in=0;											/*将右电池进入充电站标志位清零*/
	Bat_2.init=0;										/*右电池初始化未完成*/
	Bat_2.error=0;										/*右电池无故障*/
	Bat_2.chg_full=0;									/*拔出电池盒,右电池充满位清零*/
	Bat_2.Soc=0;										/*拔出电池盒,右电池电量SOC位清零*/	
	Bat_2.error1=0;										/*右电池过压、温度故障标志位*/
	Bat_2.error2=0;										/*右电池过流故障标志位*/
	CCPR2L=160;											/*占空比的值为满*/
	LEDB=1;												/*亮绿灯*/
	TRISE2=0;											/*定义RE2输出*/
	ENA=1;												/*关掉2路通讯*/
}


/*当左电池插入到电池盒中后,执行左侧电池处理函数*/
/*此时电池插入充电站中,开关闭合状态,RD2为左侧JP1接插件*/
void LeftBattery_Init(void)
{
	Bat_1_Test();										/*发送0X20命令,得到电池初始化完成标志位Bat_1.init。为1初始化完成;为0初始化未完成*/
	/*若0x20数据发送完后,有返回值,方可继续执行0x21数据的发送*/
	/*判断返回数据的格式,符合标准通讯格式,设备分配符0X01、0X20。*/
	if((canreflag==1)&&(canrecebuf[7]==0x01))	/*如果有回复*/
	{
		canreflag=0;									/*清通讯接收到标志*/
		canjudgbuf[0]=canrecebuf[0];					/*将数据转存到数组中,用于判断*/	
		canjudgbuf[1]=canrecebuf[1];
		canjudgbuf[2]=canrecebuf[2];
//		canjudgbuf[3]=canrecebuf[3];
		canjudgbuf[4]=canrecebuf[7];
		CAN_0x21(1);									/*发送0x21命令,左侧电池盒初始化第二步,1代表左侧。*/	
	}
	else
	{
		CAN_0x25(1);									/*当发0X20没有回复,可能存在着电池未关掉,已经完成初始化的情况*/
	
	}			
}


/*当右电池插入到电池盒中后,执行右侧电池处理函数*/
/*此时电池插入充电站中,开关闭合状态,RD2为右侧JP3接插件*/
void RightBattery_Init(void)	
{
	Bat_2_Test();										/*发送0X20命令,得到电池初始化完成标志位Bat_1.init。为1初始化完成;为0初始化未完成*/
	/*若0x20数据发送完后,有返回值,方可继续执行0x21数据的发送*/
	/*判断返回数据的格式,符合标准通讯格式,设备分配符0X01、0X20。*/
	if((canreflag==1)&&(canrecebuf[7]==0x02))	/*如果有回复*/
	{
		canjudgbuf[0]=canrecebuf[0];					/*将数据转存到数组中,用于判断*/	
		canjudgbuf[1]=canrecebuf[1];
		canjudgbuf[2]=canrecebuf[2];
//		canjudgbuf[3]=canrecebuf[3];
		canjudgbuf[4]=canrecebuf[7];
		canreflag=0;									/*清通讯接收到标志*/
		delay(500);										/*延时1秒*/			
		CAN_0x21(2);									/*发送0x21命令,左侧电池盒初始化第二步,2代表右侧。*/			
	}
	else
	{
		delay(500);										/*延时1秒*/
		CAN_0x25(2);									/*当发0X20没有回复,可能存在着电池未关掉,已经完成初始化的情况*/
	
	}			
}


/*当左电池插入到电池盒中后,执行左侧电池处理函数*/
/*此时电池插入充电站中,开关闭合状态,RD2为左侧JP1接插件*/
void LeftBattery_Deal(void)
{			
	if(Bat_1.chg_full==0)								/*电池未充满电时*/
	{	
		CAN_0x25(1);									/*发送0x25命令,读取电池故障信息*/	
		if((Bat_1.error1==0)&&(Bat_1.error2==0))		/*无故障时*/
		{	
			Bat1_Volt();								/*检测1路的电压值*/
			Bat1_Curr();								/*检测1路的电流值*/	
			if(Bat_1.volt<=24000)	
			{														
				while(Bat_1.cur<500)	
				{							
					CCPR1L--;							/*duty cycle decrease,减小占空比*/								
					Bat1_Volt();						/*检测1路的电压值*/												
					Bat1_Curr();						/*检测1路的电流值*/
					if((RD2==1)||(CCPR1L==0)||(Bat_1.volt>24000)) 
					{
						break;	
					}	
					Show_num_4(CCPR1L);
					Show_num_1(Bat_1.volt);
					Show_num_3(Bat_1.cur);																																		
				}
				if(RD2==1)	
				{
					Bat_1_Reset();						/*左侧电池状态复位*/
				}	
				Show_num_4(301);
				Show_num_4(CCPR1L);
				Show_num_1(Bat_1.volt);
				Show_num_3(Bat_1.cur);			
			}
			else if (Bat_1.volt<=28800)		
			{					
				while((Bat_1.cur<=3000)||(Bat_1.cur>=3200))	
				{				
					if(Bat_1.cur<=3200)	
					{
						CCPR1L--;						/*duty cycle decrease,减小占空比*/
					}	
					else if (Bat_1.cur<=3200)
					{
						CCPR1L=CCPR1L;					/*duty cycle unchanged.,占空比不变*/
					}
					else
					{
						CCPR1L++;						/*duty cycle increase,增加占空比*/
					}		
					Bat1_Volt();						/*检测1路的电压值*/												
					Bat1_Curr();						/*检测1路的电流值*/
					if((RD2==1)||(CCPR1L==0)||(Bat_1.volt>28800)) 
					{
						break;	
					}
					Show_num_4(CCPR1L);
					Show_num_1(Bat_1.volt);
					Show_num_3(Bat_1.cur);																										
				}
				if(RD2==1)	
				{
					Bat_1_Reset();						/*左侧电池状态复位*/
				}
				Show_num_4(302);
				Show_num_4(CCPR1L);
				Show_num_1(Bat_1.volt);
				Show_num_3(Bat_1.cur);																					
			}
			else	
			{	
				Bat1_Curr();							/*检测1路的电流值*/			
				if(Bat_1.cur<=300)
				{
					Bat_1.chg_full=1;
					CCPR1L=160;							/*切断电池输出,等待拔出电池*/
					LEDA=1;								/*亮绿灯,指示此时已经充满电*/													
				}
				if(RD2==1)	
				{
					Bat_1_Reset();						/*左侧电池状态复位*/
				}
				Show_num_4(303);
				Show_num_4(CCPR1L);
				Show_num_1(Bat_1.volt);
				Show_num_3(Bat_1.cur);		
			}
			if(Bat_1.cur>=10)							/*当电流大于10mA时*/
			{
				LEDA=0;									/*显示红灯*/
			}
			CAN_0x26(1);								/*发送0x26命令,读取电池状态信息*/																										
		}
		else
		{
			Bat1_Error_Deal();							/*执行错误处理程序*/	
		}			
	}
	else												/*当电池充满电时*/
	{
		CCPR1L=160;										/*切断电池输出,等待拔出电池*/
		LEDA=1;											/*亮绿灯,指示此时已经充满电*/
	}					
}

/*右侧电池处理函数*/
/*此时电池插入充电站中,开关闭合状态,RD3为右侧JP3接插件*/
void RightBattery_Deal(void)
{	
	if(Bat_2.chg_full==0)								/*电池未充满电时*/
	{	
		CAN_0x25(2);									/*发送0x25命令,读取电池故障信息*/	
		if((Bat_2.error1==0)&&(Bat_2.error2==0))		/*无故障时*/
		{	
			Bat2_Volt();								/*检测1路的电压值*/
			Bat2_Curr();								/*检测1路的电流值*/	
			if(Bat_2.volt<=24000)	
			{													
				while(Bat_2.cur<500)	
				{							
					CCPR2L--;							/*duty cycle decrease,减小占空比*/								
					Bat2_Volt();						/*检测1路的电压值*/												
					Bat2_Curr();						/*检测1路的电流值*/
					if((RD3==1)||(CCPR2L==0)||(Bat_2.volt>24000)) 
					{
						break;	
					}
					Show_num_4(CCPR2L);
					Show_num_1(Bat_2.volt);
					Show_num_3(Bat_2.cur);																															
				}

				if(RD3==1)	
				{
					Bat_2_Reset();						/*左侧电池状态复位*/
				}
				Show_num_4(301);
				Show_num_4(CCPR2L);
				Show_num_1(Bat_2.volt);
				Show_num_3(Bat_2.cur);			
			}
			else if (Bat_2.volt<=28800)		
			{					
				while((Bat_2.cur<=3000)||(Bat_2.cur>=3200))	
				{				
					if(Bat_2.cur<=3000)	
					{
						CCPR2L--;						/*duty cycle decrease,减小占空比*/
					}	
					else if (Bat_2.cur<=3200)
					{
						CCPR2L=CCPR2L;					/*duty cycle unchanged.,占空比不变*/
					}
					else
					{
						CCPR2L++;						/*duty cycle increase,增加占空比*/
					}		
					Bat2_Volt();						/*检测1路的电压值*/												
					Bat2_Curr();						/*检测1路的电流值*/
					if((RD3==1)||(CCPR2L==0)||(Bat_2.volt>28800)) 
					{
						break;	
					}	
					Show_num_4(CCPR2L);
					Show_num_1(Bat_2.volt);
					Show_num_3(Bat_2.cur);																										
				}
				if(RD3==1)	
				{
					Bat_2_Reset();						/*左侧电池状态复位*/
				}				
				Show_num_4(302);
				Show_num_4(CCPR2L);
				Show_num_1(Bat_2.volt);
				Show_num_3(Bat_2.cur);																			
			}
			else	
			{	
				Bat2_Curr();							/*检测2路的电流值*/			
				if(Bat_2.cur<=300)
				{
					Bat_2.chg_full=1;
					CCPR2L=160;							/*切断电池输出,等待拔出电池*/
					LEDB=1;								/*亮绿灯,指示此时已经充满电*/													
				}
				if(RD3==1)	
				{
					Bat_2_Reset();						/*右侧电池状态复位*/
				}
				Show_num_4(303);
				Show_num_4(CCPR2L);
				Show_num_1(Bat_2.volt);
				Show_num_3(Bat_2.cur);	
			}
			if(Bat_2.cur>=10)							/*当电流大于10mA时*/
			{
				LEDB=0;									/*显示红灯*/
			}				
			CAN_0x26(2);								/*发送0x26命令,读取电池状态信息*/																										
		}
		else
		{
			Bat2_Error_Deal();							/*执行错误处理程序*/	
		}			
	}
	else												/*当电池充满电时*/
	{		
		CCPR2L=160;										/*切断电池输出,等待拔出电池*/
		LEDB=1;											/*亮绿灯,指示此时已经充满电*/
	}					
}


/***************************
函数:void Bat1_Error_Deal(void)
函数描述:左侧电池故障处理函数
变量:无
*****************************/	
void Bat1_Error_Deal(void)				
{	
	if(Bat_1.error1==1)
	{
		delay(1000);									/*延时2S*/	
		CAN_0x25(1);									/*再次检测故障*/
		if(Bat_1.error1==1)
		{
			CAN_0x26(1);								/*发送0x26命令,读取电池状态信息*/
			if(Bat_1.Soc>=95)							/*电量达到100%时,不处理故障,切断输出,停止充电*/
			{
				CCPR1L=160;								/*切断输出*/
				Bat_1.chg_full=1;
				LEDA=1;									/*亮绿灯,指示此时已经充满电*/								
			}
			else
			{
				Bat_1_Reset();							/*左侧电池状态复位*/				
				/*故障灯光提示*/
				LEDA=~LEDA;								/*闪灯*/
				delay(500);								/*延时0.5S*/
				LEDA=~LEDA;								/*闪灯*/
				delay(500);								/*延时0.5S*/
				LEDA=~LEDA;								/*闪灯*/
				delay(500);								/*延时0.5S*/
				LEDA=~LEDA;								/*闪灯*/
				delay(500);								/*延时0.5S*/
			}
		}
	}	
	if(Bat_1.error2==1)									/*充电过流故障*/
	{
		Bat_1_Reset();									/*左侧电池状态复位*/
		/*故障灯光提示*/
		LEDA=~LEDA;										/*闪灯*/
		delay(500);										/*延时0.5S*/
		LEDA=~LEDA;										/*闪灯*/
		delay(500);										/*延时0.5S*/
		LEDA=~LEDA;										/*闪灯*/
		delay(500);										/*延时0.5S*/
		LEDA=~LEDA;										/*闪灯*/
		delay(500);										/*延时0.5S*/
	}
/*其他情况,充电器端忽略故障,电池段会自行处理*/	
}


/***************************
函数:void Bat2_Error_Deal(void)
函数描述:右侧电池故障处理函数
变量:无
*****************************/
void Bat2_Error_Deal(void)				
{	
	if(Bat_2.error1==1)
	{
		delay(1000);									/*延时2S*/	
		CAN_0x25(2);									/*再次检测故障*/
		if(Bat_2.error1==1)
		{
			CAN_0x26(2);								/*发送0x26命令,读取电池状态信息*/
			if(Bat_2.Soc>=95)							/*电量达到100%时,不处理故障,切断输出,停止充电*/
			{
				CCPR2L=160;								/*切断输出*/
				Bat_2.chg_full=1;
				LEDB=1;									/*亮绿灯,指示此时已经充满电*/
			}
			else
			{
				Bat_2_Reset();							/*左侧电池状态复位*/
				/*故障灯光提示*/
				LEDB=~LEDB;								/*闪灯*/
				delay(500);								/*延时0.5S*/
				LEDB=~LEDB;								/*闪灯*/
				delay(500);								/*延时0.5S*/
				LEDB=~LEDB;								/*闪灯*/
				delay(500);								/*延时0.5S*/
				LEDB=~LEDB;								/*闪灯*/
				delay(500);								/*延时0.5S*/
			}
		}
	}	
	if(Bat_2.error2==1)									/*充电过流故障*/
	{
		Bat_2_Reset();									/*左侧电池状态复位*/
		/*故障灯光提示*/
		LEDB=~LEDB;										/*闪灯*/
		delay(500);										/*延时0.5S*/
		LEDB=~LEDB;										/*闪灯*/
		delay(500);										/*延时0.5S*/
		LEDB=~LEDB;										/*闪灯*/
		delay(500);										/*延时0.5S*/
		LEDB=~LEDB;										/*闪灯*/
		delay(500);										/*延时0.5S*/
	}
/*其他情况,充电器端忽略故障,电池段会自行处理*/	
}


bat.h
/*****************************************************************/
#ifndef	__BAT_h__
#define	__BAT_h__

#include "pic.h"
#include 
#include 
#include 
#include 
#include 

void Bat_init(void);			/*初始化左右侧电池的状态标志位*/
void Bat_1_Reset(void);			/*左侧电池状态复位*/
void LeftBattery_Init(void);	/*左侧电池初始化*/
void LeftBattery_Deal(void);	/*左侧电池处理函数*/
void Bat1_Error_Deal(void);		/*左侧电池故障处理函数*/
void Bat_2_Reset(void);			/*右侧电池状态复位*/
void RightBattery_Init(void);	/*右侧电池初始化*/
void RightBattery_Deal(void);	/*右侧电池处理函数*/
void Bat2_Error_Deal(void);		/*右侧电池故障处理函数*/

#endif

 
  

你可能感兴趣的:(电池管理)