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

📄 control.c

📁 一个充电控制器的完整单片机程序
💻 C
字号:

/*
*/
#include <absacc.h> 
#include <stdlib.h>
#include <AT89X52.H>
#include <INTRINS.h>

#include "charger.h"
/*
//init_system_work_point 
*/

#define BENCHMARK 4.5
#define AMPLIFICATORY 10//predefine 0.1 proccess, amplificatory 10
#define ADMAX 4096

#define system_volatage sys[7]
#define discharge_model sys[8]
#define charge_model    sys[9]
#define float_revise    sys[10]
#define test_temp   		sys[11]
#define desinged_rate   sys[12]
//alarm overload
#define overload         sys[6]

//static array daydata   change to loop link
//sizeof(daydata)=0x2B
extern daydata xdata looplink[BUFFSIZE];

void init_history_buffer(void)
{
  unsigned char data i;
	//Init DoubleLoopLink
	for(i=0;i<BUFFSIZE-1;i++)
	{
		looplink[i].next=&looplink[i+1];
		looplink[i+1].up=&looplink[i];
	  RESET_DOG;
  }
	looplink[BUFFSIZE-1].next=&looplink[0];
	looplink[0].up=&looplink[BUFFSIZE-1];

  today.next=&looplink[0];
  today.up=&looplink[BUFFSIZE-1]; //is head->up;
	today.up->date[0]=0;//break looplink
	today.up->date[1]=0;//break looplink
	today.up->date[2]=0;//break looplink
  RESET_DOG;
}

void init_rate_workpoint(unsigned char n)
{
	unsigned char data i;
//2005/4
	n=DEFSYSV;
//2005/4
  if(n<4)//system volatage changed
  for(i=0;i<12;i++)//Init default seting
  {
		if(i<7)
		{//work point
    	sys[i]=dtab[n][i];
		}
		else
		{
			if(i==11)//sys[11] is test temp.
				sys[12]=stab[4][n];//desinged_rate
			else sys[i]=stab[i-7][n];
		}
	}

	i=45;//BENCHMARK*AMPLIFICATORY=45;
	crate.temperature = i*100;
	crate.volatage = i*desinged_rate;//battery volatage
	crate.discharge = i*discharge_model/4;
	crate.charge = i*charge_model/4;
	//check overload <= discharger model
	if(overload>discharge_model)overload=discharge_model;
  RESET_DOG;
}

//intput data from tlc1543,changed and saved
const adintimes =0xDB24;
const adinadd   =0xDB28;
const tmpAh			=0xDB44;
//today at 

#define ADCOUNT 	10
void getadin(void)
{
  unsigned char data i;
	unsigned long data tmp;
	unsigned long xdata *s;//adinadd
	unsigned int xdata *t;
	
	for(i=0;i<10;i++)//9 way, the 8 way is no use
	if(i!=7)
	{
		unsigned char data c; 

		tmp=0;

		for(c=0;c<ADCOUNT;c++)tmp+=tlc1543(i);

	  RESET_DOG;
	
		tmp /= ADCOUNT;

		if(i<6)
		{
			tmp *= crate.charge;
			tmp /= ADMAX;	adin[i]=(unsigned int)tmp;	
		}
		if(i==6)
		{
			tmp *= crate.discharge;
			tmp /= ADMAX;	adin[6]=(unsigned int)tmp;
		}
		if(i==8)
		{
			tmp *= crate.temperature;
			tmp /= ADMAX;	adin[7]=(unsigned int)tmp;

			if(adin[7]<2730)adin[7]=2730;
			if(adin[7]>3080)adin[7]=3080;
			adtemp=adin[7];//save no just temperature

			/*2005/4
			if(test_temp<3230&&test_temp>2230)adin[7]+=just;//+/-50d
			2005/4*/
		}
		if(i==9)
		{
			tmp *= crate.volatage;
			tmp /= ADMAX;	adin[8]=(unsigned int)tmp;	
		}
	}
	
	for(i=0;i<9;i++)
	{
		if(i>6)//save min value of battery vola.&temperature
		if(adin[i]<today.work[2*i+1]||today.work[2*i+1]==0)
			today.work[i*2+1]=adin[i];
			//only save max value
		if(adin[i]>today.work[2*i])today.work[i*2]=adin[i];
	}
	//counter times and add to add current
		s=adinadd;
		for(i=0;i<7;i++)*s+++=(unsigned long)adin[i];
		t=adintimes;
		(*t)++;
	  RESET_DOG;
}
//-----------------------------
//check error
void syserror(void)
{
//系统设置检错
		unsigned char data i;
		for(i=0;i<7;i++)
			if(sys[i]>400||sys[i]<30)
			{init_rate_workpoint(DEFSYSV);return;}
		if(!(sys[7]==48||sys[7]==110||sys[7]==220||sys[7]==300))
		{
			init_rate_workpoint(DEFSYSV);
			//控制器失效,需要重新设置或者重新上电
		}
}

/*
//count today working result
*/
void account(void)
{
static bit bdata cc;
if(tlong%60>50)//50s
{
	if(!cc)
	{
		char data i;
		unsigned long xdata *s;
		unsigned long xdata *Ah;//adinadd
		unsigned int xdata *t;
		t=adintimes;
		s=adinadd;
		Ah=tmpAh;
		for(i=0;i<7;i++)
		{ //save current integral value (Ah)
			unsigned long data taa;
			if(*t!=0)*Ah+=*s/(unsigned long)(*t);//保证精度不损失
				else return;
			taa=(unsigned long)(*Ah/60);
			today.work[i*2+1]=(unsigned int)taa;
			*s++=0;
			Ah++;
		  RESET_DOG;
		}
		cc=1;	*t=0;
	}
}
else cc=0;
}

/*
//output control,switch operation
*/

#define boostvolatage    sys[0]
#define booststart       sys[1]
#define floatstop    		 sys[2]
#define floatstart     	 sys[3]
#define moterstart       sys[4]
#define lowlevel         sys[5]
#define dischargecurrent adin[6]
#define BatteryVolatage  adin[8]

//-----------------------------
//System flag,char of control;
//-----------------------------
//control state character 
#define fstopc  0x17
#define fstarc  0x12
#define bstopc  0x15
#define bstarc  0x18
#define lowerc  0x2
#define overc   0x13
#define motorc  0xf
#define loadoverswitch P3_3

bit bdata boostflag;

#pragma DISABLE

void control(void)
{
	static bit bdata motoropen,exe,ffo;
	static unsigned char idata switchchar=0xff; //all close

	unsigned int data ofv,cfv;
	unsigned char data fk;
	unsigned int data temp_flr;
	temp_flr=float_revise/10;//100*10=1000
	if(t50ms%40>20)//2s
		{if(exe)return;}
	else {exe=0; return;}

	exe=1;
	syserror();//check sys rightly

	//float charge Temperature revise
	if(adin[7]>2980)//25^C
	{
		cfv=floatstop*AMPLIFICATORY-((adin[7]-2980)*temp_flr)/100;// /1000;
		ofv=floatstart*AMPLIFICATORY-((adin[7]-2980)*temp_flr)/100;
	}
	else
	{
		cfv=floatstop*AMPLIFICATORY+((2980-adin[7])*temp_flr)/100;
		ofv=floatstart*AMPLIFICATORY+((2980-adin[7])*temp_flr)/100;
	}

	if(controlstate==fstopc)fk=0;

	if(BatteryVolatage > boostvolatage*AMPLIFICATORY)
	{
		boostflag=0;	controlstate=bstopc;
		if(switchchar!=0xff)
		{
			fk=1;
			while(switchchar==(switchchar|fk))fk<<=1;
			switchchar|=fk;	switchchar|=0xC0;
		}else controlstate=fstopc;
	}
	else
	{
		if(boostflag)
		{
			controlstate=bstarc;//boost charge start
			switchchar|=0xC0;
			if((switchchar&0x3F) !=0x00)
			{
				fk=1;
				while(switchchar==(switchchar&~fk))fk<<=1;
				switchchar&=~fk;
			}
			if(BatteryVolatage< moterstart*AMPLIFICATORY)
			{
				motoropen=1;//and motor start
				if(BatteryVolatage<lowlevel*AMPLIFICATORY)
				{//controlstate=lowerc;
				switchchar&=0x7F;}//not enough volatage alarm,6 way start 
			}
		}
		else	//float controll
		{
			if(BatteryVolatage >cfv)//float stop
			{
				ffo=0;
				motoropen=0;		controlstate=fstopc;
				if(switchchar!=0xff)
				{
					fk=1;	controlstate=fstarc;
					while(switchchar==(switchchar|fk))fk<<=1;
					switchchar|=fk;	switchchar|=0xC0;
				}
	  	}//stop motor,close 1 way
			else
			{
				if(switchchar==0xff)controlstate=fstopc;
				else controlstate=fstarc;
				if(ffo)
					if((switchchar&0x3F) !=0x00)
					{
						fk=1;
						while(switchchar==(switchchar&~fk))fk<<=1;
						switchchar&=~fk;	switchchar|=0xC0;
					}
				if(BatteryVolatage < ofv)//float start
				{
					ffo=1;
					if(BatteryVolatage < booststart*AMPLIFICATORY)
					{
						boostflag=1;	controlstate=bstarc;//boost charge start
					}
				}
			}
		}
	}

	if(motoropen)
		if(BatteryVolatage <cfv)//float stop,stop motor
			{	if(t50ms%15<7)controlstate=motorc;	switchchar &=0xBF;}//motor mask
		else {switchchar |=0x40;motoropen=0;}
	//Send control to port
	P8255B=switchchar;

  RESET_DOG;
}
void overloadctl(void)
{
//OverLoad alarm
	if(dischargecurrent>(overload*AMPLIFICATORY))
	{
		if(loadoverswitch)//P3_3
			{controlstate=overc;loadoverswitch=0;_nop_();_nop_();}
		else loadoverswitch=1;
	}
//Lower volotage alarm
	if(BatteryVolatage<lowlevel*AMPLIFICATORY)
	{static data unsigned char i;i++;
		if(i&1)return;
		if(loadoverswitch)//P3_3
			{controlstate=lowerc;loadoverswitch=0;_nop_();_nop_();}
		else loadoverswitch=1;
	}

	if(dischargecurrent<(overload*AMPLIFICATORY)&&(BatteryVolatage>lowlevel*AMPLIFICATORY))
	loadoverswitch=1;

_nop_();_nop_();
}
//----------------------------------------
///save tab to xdata at the one day
//-----Xsave the first value---------
static unsigned char xdata day[3] _at_ 0xD580;

void save(void)
{
  if(today.date[2]==day[2])return;

	if(day[2]==0||day[2]>31)
	{
		day[2]=today.date[2];
		day[1]=today.date[1];
		day[0]=today.date[0];
		return;
	}

	{
		unsigned long xdata *Ah;
  	unsigned char data i;
  	link p;
    p=today.next;
    //save data to dubluelooplinktable
    for(i=0;i<18;i++)//copy today to today.next
    {
     	if(i<3)
			{
				p->date[i]=day[i];
				day[i]=today.date[i];
			};
     	p->work[i]=today.work[i];
			today.work[i]=0;//clear buffer
    }

		Ah=tmpAh;
		for(i=0;i<7;i++)*Ah++=0;//clear Ahtmp

    today.next=p->next;//OR today.next->next
    today.up=p;
		p=today.next;
		p->date[0]=0;
		p->date[1]=0;
		p->date[2]=0;//break looplink
	}
  RESET_DOG;
}


⌨️ 快捷键说明

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