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

📄 temperature_control.c

📁 基于51单片机的pid算法实现水温的自动控制
💻 C
字号:
#include <AT89X51.H>

unsigned char display_code[10]={~0x3f,~0x06,~0x5b,~0x4f,~0x66,~0x6d,~0x7d,~0x07,~0x7f,~0x67};
unsigned char display_buffer[4];
bit set=0;
bit pid_allow=0;


sbit eoc=P3^3;
sbit oe=P3^2;
sbit st=P3^4;
sbit k1=P2^4;
sbit k2=P2^5;
sbit k3=P2^6;
sbit k4=P2^7;
sbit light=P3^6;
sbit heal=P3^7;


unsigned char i=0;
float t,t_now,tout=100,t_diff=0,t_target=60,temp=0;

unsigned int k=5000;
int ttemp1=0;
unsigned char ttemp2=0,ttemp3=1;

float KP=28,KI=2.5;
void display(void);		//数码管显示
void adc0809(void);		//AD转换
void pid(void);			//pid控制量计算
void p_out(void);		//输出控制


void main()
{
	
    TMOD=0x11;
 	TL0=(65536-3000)%256;
 	TH0=(65536-3000)/256;
	TL1=(65536-40000)%256;
 	TH1=(65536-40000)/256;
	EA=1;
	ET0=1;
	ET1=1;
	TR0=1;
	TR1=1;
	light=0;
	heal=1;
	while(1)
	{
		display_buffer[0]=(unsigned char)t_now/10;			//刷新显示
		display_buffer[1]=(unsigned char)t_now%10;
		display_buffer[2]=(unsigned char)t_target/10;
		display_buffer[3]=(unsigned char)t_target%10;
		if(set==0)											//按键扫描
		{
			if(k1==0)				//复位
			{
				while(k--);
				if(k1==0){t_target=40;}		
			}
			if(k2==0)				//目标温度+1
			{
				while(k--);
				if(k2==0){if((t_target++)>=90)t_target=90;}
			}
			if(k3==0)				//目标温度-1
			{
				while(k--);
				if(k3==0){if((t_target--)<=40)t_target=40;}
			}
			if(k4==0)				//开始工作
			{
				while(k--);
				if(k4==0){pid_allow=1;set=1;light=1;}
	
			}
		}
		else if(set==1)
		{
			if(k1==0)				//停止,复位
			{
				while(k--);
				if(k1==0){t_target=40;light=0;set=0;heal=1;tout=0;temp=0;tout=100;t_diff=0;}
			}
		
		}
	}
}
	
/****************************************************
 函数:定时器0中断程序
 功能:3000uS中断一回,对数码管进行显示
*****************************************************/
void time0() interrupt 1 using 0
{
	TL0=(65536-3000)%256;
	TH0=(65536-3000)/256;
	display();

}

/****************************************************
 函数:定时器1中断程序
 功能:40000uS中断一回,进行AD转换,控制输出量
*****************************************************/
void time1() interrupt 3 using 0
{
	TL1=(65536-40000)%256;
 	TH1=(65536-40000)/256;

	adc0809();
//	if(pid_allow==1)
	if((pid_allow==1)&&(t_target-t_now<=5))	
	{
		pid_allow=0;
		pid();
	}
	if(set==1)
	{		
		if((ttemp1++)==500)
		{
			ttemp1=0;
			pid_allow=1;
		}
		p_out();
	  
	}
}

/****************************************************
 函数:中断中对动态扫描刷新函数
*****************************************************/
void display(void)
{
	if(i==0)P2=0xfe;
	if(i==1)P2=0xfd;
	if(i==2)P2=0xfb;
	if(i==3)P2=0xf7;
	P0=display_code[(display_buffer[i])];
	i++ ;
	if( i>3) i=0;
}


/****************************************************
 函数:中断中AD转换函数
*****************************************************/
void adc0809(void)
{
	oe=0;
	st=0;
	st=1;
	st=0;
	while(!eoc);
	oe=1;
	t=P1;
	t_now=100*t/256;
	oe=0;
}

/****************************************************
 函数:中断中控制输出函数
*****************************************************/
void p_out(void)
{	
	int j;
	j=(int)tout;
	if(ttemp3<=j)heal=0;
	else heal=1;
	if((ttemp2++)==5)
	{
		ttemp2=0;
		ttemp3++;
	}
	if(ttemp3>100)ttemp3=1;
}

/****************************************************
 函数:进行pid计算,得出控制量函数
*****************************************************/
void pid()
{
	temp=t_diff;
	adc0809();
	t_diff=t_target-t_now;
	tout+=KP*(t_diff-temp)+KI*t_diff;
	if(tout<0)tout=0;
	else if(tout>=100)tout=100;
}



⌨️ 快捷键说明

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