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

📄 pid.c51

📁 单片机PID控制
💻 C51
字号:
#include <reg51.h>
#include<math.h>
#include<intrins.h>
#include<absacc.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong  unsigned long
/*MAX7219寄存器功能说明**********************************/
#define shutdown 0x0c //0  关闭  1  开启
#define decodemode 0x09 //0  ndecode all
       //1  decode 0
          //0f decode 0-3
       //ff decode all
#define intensity 0x0a //亮度控制寄存器 0-f
/*显示位控制寄存器***************************************/
/*0-第一位  1-第一、二位  ......7-全显示*****************/
#define scanlimit 0x0b 

#define testreg  0x0f //测试模式 0 普通模式  1显示测试模式
#define dataaddr 0x01 //显示基址
 
/********************************************************/
#define set_0(X) X=0
#define set_1(X) X=1

/***************************PID参数**********************/
#define Kp 32          //定义PID三个参数  放大16倍
#define Ki 8
#define Kd 6

sbit clk=P2^1;
sbit load_cs=P2^2;
sbit din=P2^0;
sbit ready=P3^2;

sbit P1_0=P1^0;
sbit P1_1=P1^1;
sbit P1_2=P1^2;
sbit P1_3=P1^3;
sbit P1_4=P1^4;
sbit P1_5=P1^5;
sbit P1_6=P1^6;
sbit P2_6=P2^6;

#define power_on P2_6=1
#define power_off P2_6=0
#define set_tem 10
#define ok  11
#define no_key 12

unsigned char xdata start _at_ 0xfff8;
unsigned char xdata read_h _at_ 0xfffc;
unsigned char xdata read_l _at_ 0xfffe;

/***********************全局变量*************************/
signed int tem_data=0;                                 //炉子温度测量值                   
signed int tem_data_set=0;                             //温度设定值
signed int E_n,E_nSUB1,E_nSUB2;
signed char U_n=0;                                            //PID调节输出






/************************AD转换子程序********************/
long AD574(void) 
{ uchar data_h=0,data_l=0;
  int result_12=0;
  XBYTE[0xfff8]=0;
  while(ready==1);                                       //等待转换结束 
   data_h=XBYTE[0xfffc];
   data_l=read_l;
   data_l=data_l>>4;
   result_12=data_h<<4;
   result_12=result_12+(data_l&0x0F); 
   return (result_12);                                   //返回12位A/D转换结果 
}




/***********************线性化处理子程序*****************/
int LinearProcessing(long result)                        //线性化处理子程序
   {int tem_data;
    tem_data=(long)result*10000/4095;
	return(tem_data);

   }



/***********************数字滤波处理子程序*****************/
int filtering(int tem_data_8[])
   {unsigned char i,j,k;
    int con_data=0;
	int temp;
    i=0;
	j=0;
	temp=tem_data_8[0];                      //找最小值
    for(k=1;k<8;k++)
	   {if(temp>tem_data_8[k])
	        {temp=tem_data_8[k];
			 i=k;
			}

	   }

    temp=tem_data_8[0];                      //找最小值
    for(k=1;k<8;k++)
	   {if(temp<tem_data_8[k])
	        {temp=tem_data_8[k];
			 j=k;
			}

	   }

    tem_data_8[i]=0;                         //求平均值
	tem_data_8[j]=0;
	for(k=0;k<8;k++)
	   {con_data+=tem_data_8[k];

	   }

	con_data=con_data/6;
	return(con_data);

   }

/************************温度显示刷新子程序**************/
void tem_refresh(int TEM_data)                            //温度显示刷新子程序
 {void max7219_data_send(uchar ,uchar );
  uchar i;
  TEM_data=TEM_data/10;
  i=TEM_data%10;
  max7219_data_send(dataaddr+3,i);                        //刷新个位

  TEM_data=TEM_data/10;
  i=TEM_data%10;
  max7219_data_send(dataaddr+2,i);                        //刷新十位

  TEM_data=TEM_data/10;
  i=TEM_data%10;
  max7219_data_send(dataaddr+1,i);                        //刷新百位

  TEM_data=TEM_data/10;
  i=TEM_data%10;
  max7219_data_send(dataaddr+0,i);                        //刷新千位
 }



/*******************PID调节子程序************************/
void PID(void)
  {signed int U_add=0;
   U_add=Kp*(E_n-E_nSUB1)+Ki*E_n+Kd*(E_n-2*E_nSUB1+E_nSUB2);
   U_add=U_add/10;                                       //缩小10倍
   U_add=U_add>>4;                                       //缩小16倍
   U_n=U_n+U_add;
   if(U_n<0)                                             //错误处理
	 U_n=0;
   else if(U_n>100)
     U_n=100;
   else ;
   return;
  }





/********************对MAX7219通信总线初始化*******************/
void initial()
{
 set_0(clk);
 set_0(load_cs);
 set_0(din);
}



/*****************向MAX7219发送一个16位数据*******************/
void max7219_data_send(uchar addr,uchar data_send)        //向MAX7219发送一个16位数据
{
 uchar i,a;
 set_0(load_cs);
 for(i=0;i<4;i++)
 { 
  set_0(clk);
  set_1(clk);  
 }

 addr=addr<<4;
 for(i=0;i<4;i++)
 {
  set_0(clk);
  a=addr&0x80;
  if(a) set_1(din);
  else set_0(din);
  addr=addr<<1;
  set_1(clk);
  
 }
 for(i=0;i<8;i++)
 {
  set_0(clk);
  a=data_send&0x80;
  if(a) set_1(din);
  else set_0(din);
  data_send=data_send<<1;
  set_1(clk); 
 }
 set_1(load_cs);
}



/*******************主函数******************************/
void main()
{
 initial();                                              //MAX7219初始化设置
 max7219_data_send(decodemode,0x0ff);
 max7219_data_send(intensity,0x01);
 max7219_data_send(scanlimit,0x03);
 max7219_data_send(shutdown,0x01); 
 max7219_data_send(testreg,0x00);
 
 E_n=0;
 E_nSUB1=0;
 E_nSUB2=0;
 TMOD=0x56;
 TH0=256-100;
 TL0=256-100;
 TH1=0;
 TL1=0;
 IT1=1;
 EX1=1;
 ET0=1;
 ET1=1;
 EA=1;
 TR0=1;
 TR1=1;
 P1=0xF0;

 while(1);


}

/****************************外部中断1中断服务程序****************************/
void key() interrupt 2
    {unsigned char  KeyScan();
	 unsigned char key_value;
	 char i,j,k;
	 unsigned char key_value_3[3]={0,0,0};
	 TR0=0;
	 TR1=0;
	 EA=0;
     key_value=KeyScan();
	 if(key_value==set_tem)
	     { for(i=0;i<4;i++)
		      {max7219_data_send(dataaddr+i,0); 
			  }
		  i=0;
          while(i<3)
		      {  while(1)
			      {key_value=KeyScan();
				   if(key_value==no_key)
				       continue;
				   else
				      {key_value_3[i]=key_value;
					   j=i;
                       k=0;
					   for(;j>=0;j--)
					       {max7219_data_send(dataaddr+3-j,key_value_3[k]);
                            k++;
                           }
					      
					   i++;
					   break;

					  }
				  }
			  }
          while(1)
		     {key_value=KeyScan();
			  if(key_value!=ok)continue;
			  else
			     {tem_data_set=1000*key_value_3[0]+100*key_value_3[1]+10*key_value_3[2];
				  TR0=1;
				  TR1=1;
				  EA=1;
				  break;
				 }
			 }
		 }
    else 
	  {TR0=1;
	   TR1=1;
	   EA=1;
	   return;
	   }

	}




/****************************计数器0中断服务程序****************************/
void count0() interrupt 1
    {int con_data_8[8];
	 int con_data=0;
	 uchar i;
	 TR0=0;
	 TR1=0;
     for(i=0;i<8;i++)con_data_8[i]=AD574();
     con_data=filtering(con_data_8);
	 tem_data=LinearProcessing(con_data);	
     E_nSUB1=E_n;
	 E_nSUB2=E_nSUB1;
	 E_n=tem_data_set-tem_data;
	 if(E_n>=500)
	    {power_on;
         TR0=1;
		 tem_refresh(tem_data);
         return;
		}

		else
		  {PID();
		   if(U_n==0)
		      {power_off;
			   TR0=1;
               tem_refresh(tem_data);
               return;
			   }
           else
		      {TH1=0xFF;
               TL1=256-U_n;
               TR0=1;
               TR1=1;
		       power_on;
		       tem_refresh(tem_data);
			   }
		  }
     return;
	}





/****************************计数器1中断服务程序****************************/
void count1() interrupt 3
    {TR1=0;
	 power_off;

	}




/***************************按键扫描子程序*********************************/
unsigned char KeyScan(void)
   {void delay10ms(unsigned char time);
    unsigned char key;
    P1=0xff;
    P1_0=0;
    if(P1_4==0)
	  {delay10ms(10);
	   if(P1_4==0)
	       {key=0;
            while(P1_4==0);
			return(key);		    
		   }	   
	  }
	else if(P1_5==0)
	  {delay10ms(10);
	    if(P1_5==0)
	       {key=1;
		    while(P1_5==0);
			return(key);
			}
		  
	  }
	else if(P1_6==0)
	  {delay10ms(10);
	    if(P1_6==0)
	      {key=2;
		    while(P1_6==0);
			return(key);
			}
	  }
	else ;

    P1_0=1;
	P1_1=0;
    if(P1_4==0)
	  {delay10ms(10);
	   if(P1_4==0)
	       {key=3;
		    while(P1_4==0);
			return(key);
			}
	  }
	else if(P1_5==0)
	  {delay10ms(10);
	    if(P1_5==0)
	       {key=4;
		    while(P1_5==0);
			return(key);
			}
	  }
	else if(P1_6==0)
	  {delay10ms(10);
	    if(P1_6==0)
	      {key=5;
		    while(P1_6==0);
			return(key);
			}
	  }
	else ;


    P1_1=1;
	P1_2=0;
    if(P1_4==0)
	  {delay10ms(10);
	   if(P1_4==0)
	      {key=6;
		    while(P1_4==0);
		    return(key);
			}
	  }
	else if(P1_5==0)
	  {delay10ms(10);
	    if(P1_5==0)
	      {key=7;
		    while(P1_5==0);
			return(key);
			}
	  }
	else if(P1_6==0)
	  {delay10ms(10);
	    if(P1_6==0)
	      {key=8;
		    while(P1_6==0);
			return(key);
			}
		  
	  }
	else ;


    P1_2=1;
	P1_3=0;
    if(P1_4==0)
	  {delay10ms(10);
	   if(P1_4==0)
	       {key=9;
		    while(P1_4==0);
			return(key);
			}
	  }
	else if(P1_5==0)
	  {delay10ms(10);
	    if(P1_5==0)
	       {key=set_tem;
		    while(P1_5==0);
			return(key);
			}
	  }
	else if(P1_6==0)
	  {delay10ms(10);
	    if(P1_6==0)
	      {key=ok;
		    while(P1_6==0);
			return(key);
			}
	  }
	else return(no_key);
	

   }



				  
/***********************延时程序*************************************/
 void delay10ms(unsigned char time)
       {
        unsigned char i;
        while(time--)
          { 
            for(i=0;i<120;i++) ;
           }
      }
                  
     

⌨️ 快捷键说明

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