充电站程序

这个博客介绍了一个充电站程序,其中包含了多个功能函数,如USART初始化、数组显示、数字显示以及PWM相关操作。程序涉及了延迟、SPI通信和PWM调制等技术,用于处理和显示采集到的电压和电流数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



program.c

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

#include <program8.h>
__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 <PWM.h>
#include <INT.h>
#include <SPI_887.h>
#include <CAN_887.h>
#include <usart.h>
#include <DELAY.h>
#include <ADC.h>
#include <VAR.h>
#include <mcp2515.h>
#include <bat.h>

#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 <CAN_887.h>

 
/***************************
函数: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;												/*右电池盒初始化未成功,需要重新初始化*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值