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

📄 温度控制.c

📁 PID 的温度控制
💻 C
字号:
#include <REG52.H>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char

sbit  wireless_1 = P3^0;
sbit  wireless_2 = P3^1;
sbit  wireless_3 = P3^2;
sbit  wireless_4 = P3^3;
sbit  ACC0 = ACC^0;
sbit  ACC7 = ACC^7;

void show_time(); //液晶显示程序
#define tim0 65536-1000    
#define tim1 65536-20000
uchar tm=1,tx=0;          //记数两个定时中断的
enum{Y,U,R,Ts,Kd,Kp};//Y采集量 U控制量 R 设定量 Ts 采样时间 Kd 微分 Kp比例
int para[6],ptr,out;       //out 是从PID()得到的控制量
int wd,wd1,r,kp,kd,ts,e2,e1,e0,u; //wd 是从DS18B20采到的数据

bit  dealCS=0;
sbit EN1=P2^2;
sbit IN1=P2^1;
sbit PWM=P2^0;




sbit DQ = P2^4;        //温度传送数据IO口
char done,count,temp,flag,up_flag,down_flag;
uchar temp_value;      //温度值
uchar TempBuffer[15], week_value[2];
uchar TempBuffer1[7];
uchar Ctrltab[20]={8,15,20,40,50,60,70,80,100,120,140,160,180,200};

char	T=23;
char 	disp;
void	show_time1(void);
void	debouncer(void);   //去键盘抖动延时函数
void	shezhiwendu(void); //设定温度函数
void	scanner(void);
void     PID(); 	   //键盘扫描函数
#define	rowkey()(~P1)&0x0f //读取端口宏定义

/**************去抖动延时函数***************/
void	debouncer(void)
{	int i;
	for(i=0;i<2400;i++);
}
/*******************************************/

/**************设置温度函数***************/
void	shezhiwendu(void)
{
 while(1)
      { 
	  	scanner();
		show_time1();

	  	if(disp==2)   { T++;	disp=0; } 
			 
        if(disp==3)   { T--;	disp=0; } 
			  
	    if(disp==4)    break; 
		
      }
}

/*******************************************/

/***********键盘扫描函数********************/

void	scanner(void)
{	char	col,row;
	char	scan,keyin;
	scan=0xef;
	for(col=0;col<4;col++)
	{	P1=scan;
		keyin=rowkey();
		if(keyin!=0)
			{	for(row=0;row<4;row++)
					{	if(keyin==(0x01<<row))
							{	disp=row+4*col;
								break;
							}
							if(row==4)
							disp=0;
					}
					while(rowkey());
					debouncer();
			}
			scan=(scan<<1)|0x01;
	}
}

/*****************************************************/




void  initTimer0_Timer1()    //初始化定时器0,定时器1
{


TMOD=0x01;
TH0=tim0>>8; TL0=tim0; 

TR0=1;
ET0=1;
EA=1;


}

void  initPID()          //初始化PID函参数
{
 
  para[Kp]=100; 
  para[Kd]=3;  
  para[Ts]=10;
  
}


void PID()             //PID服务程序
{  
   
   TR0=0;
   ET0=0;
   EA=0;       		       //检测的温度
  		               //wd设定的温度
  e0=e1;e1=e2;e2=wd-T; 
  kp=para[Kp]; kd=para[Kd]; ts=para[Ts];
  u=wd+kp*(e2+kd*(e2-e1));
  if(u<0) u=0;
  if(u>500) u=500;
  out=u/10;		       //控制量
   
   TR0=1;
   ET0=1;
   EA=1; 


}


void PWM_timer0() interrupt 1    //定时器0中断服务子程序
{
  TH0=tim0>>8; TL0=tim0; 
  
     if(tm++>=out) 
       
      PWM=0;        //通过变量out控制PWM脉冲宽度
       else PWM=1; 
 
if(tm>=50) 
 {  

PID();     
tm=1;           //通过变量tm控制PWM的周期
  }  
		   
}


/*

void timer1() interrupt 3      //定时器1中断服务子程序 
{
  TH1=tim1>>8; TL1=tim1;
  if(dealCS==0)            ///模糊控制
  {
    wdCtrl=para[R];
    if((wdCtrl-wd/10)>10)out=0;
    else if((wd/10-wdCtrl)>2)out=225;
  else out=Ctrltab[wdCtrl+2-wd/10]; 
  }
else if(tx++>=ts)          //dealCS为1,选择的是PID();
  {

  tx=0;
  }
}	*/	
  

/***********1602液晶显示部分子程序****************/

sbit LcdRs		= P2^5;
sbit LcdRw		= P2^6;
sbit LcdEn  	= P2^7;
sfr  DBPort 	= 0x80;		//P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口

//内部等待函数**************************************************************************
unsigned char LCD_Wait(void)
{
	LcdRs=0;
	LcdRw=1;	_nop_();
	LcdEn=1;	_nop_();
						 
	LcdEn=0;
	return DBPort;		
}
//向LCD写入命令或数据************************************************************
#define LCD_COMMAND			0      // Command
#define LCD_DATA			1      // Data
#define LCD_CLEAR_SCREEN	0x01      // 清屏
#define LCD_HOMING  		0x02      // 光标返回原点

void LCD_Write(bit style, unsigned char input)
{
	LcdEn=0;
	LcdRs=style;
	LcdRw=0;		_nop_();
	DBPort=input;	_nop_();//注意顺序
	LcdEn=1;		_nop_();//注意顺序
	LcdEn=0;		_nop_();
	LCD_Wait();	
}

//设置显示模式************************************************************
#define LCD_SHOW			0x04    //显示开
#define LCD_HIDE			0x00    //显示关	  

#define LCD_CURSOR			0x02 	//显示光标
#define LCD_NO_CURSOR		0x00    //无光标		     

#define LCD_FLASH			0x01    //光标闪动
#define LCD_NO_FLASH		0x00    //光标不闪动

void LCD_SetDisplay(unsigned char DisplayMode)
{
	LCD_Write(LCD_COMMAND, 0x08|DisplayMode);	
}

//设置输入模式************************************************************
#define LCD_AC_UP			0x02
#define LCD_AC_DOWN			0x00      // default

#define LCD_MOVE			0x01      // 画面可平移
#define LCD_NO_MOVE			0x00      //default

void LCD_SetInput(unsigned char InputMode)
{
	LCD_Write(LCD_COMMAND, 0x04|InputMode);
}

//初始化LCD************************************************************
void LCD_Initial()
{
	LcdEn=0;
	LCD_Write(LCD_COMMAND,0x38);           //8位数据端口,2行显示,5*7点阵
	LCD_Write(LCD_COMMAND,0x38);
	LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR);    //开启显示, 无光标
	LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);   //清屏
	LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE);       //AC递增, 画面不动
}

//液晶字符输入的位置************************
void GotoXY(unsigned char x, unsigned char y)
{
	if(y==0)
		LCD_Write(LCD_COMMAND,0x80|x);
	if(y==1)
		LCD_Write(LCD_COMMAND,0x80|(x-0x40));
}

//将字符输出到液晶显示
void Print(unsigned char *str)
{
	while(*str!='\0')
	{
		LCD_Write(LCD_DATA,*str);
		str++;
	}
}



/***********ds18b20延迟子函数(晶振12MHz )*******/ 

void delay_18B20(unsigned int i)
{
	while(i--);
}

/**********ds18b20初始化函数**********************/

void Init_DS18B20(void) 
{
	 unsigned char x=0;
	 DQ = 1;          //DQ复位
	delay_18B20(8);  //稍做延时
	 DQ = 0;          //单片机将DQ拉低
	 delay_18B20(80); //精确延时 大于 480us
	 DQ = 1;          //拉高总线
	 delay_18B20(14);
	 x=DQ;            //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
	 delay_18B20(20);
}

/***********ds18b20读一个字节**************/  

unsigned char ReadOneChar(void)
{
	uchar i=0;
	uchar dat = 0;
	for (i=8;i>0;i--)
	 {
		  DQ = 0; // 给脉冲信号
		  dat>>=1;
		  DQ = 1; // 给脉冲信号
		  if(DQ)
		  dat|=0x80;   // 位 或;
		  delay_18B20(4);
	 }
 	return(dat);
}

/*************ds18b20写一个字节****************/  

void WriteOneChar(uchar dat)
{
 	unsigned char i=0;
 	for (i=8; i>0; i--)
 	{
  		DQ = 0;
 		DQ = dat&0x01;
    	delay_18B20(5);
 		DQ = 1;
    	dat>>=1;
 }
}

/**************读取ds18b20当前温度************/

void ReadTemp(void)
{
	unsigned char a=0;
	unsigned char b=0;
	unsigned char t=0;

	Init_DS18B20();
	WriteOneChar(0xCC);    	// 跳过读序号列号的操作
	WriteOneChar(0x44); 	// 启动温度转换

    delay_18B20(100);       // this message is wery important

	Init_DS18B20();
	WriteOneChar(0xCC); 	//跳过读序号列号的操作
	WriteOneChar(0xBE); 	//读取温度寄存器等(共可读9个寄存器) 前两个就是温度

	delay_18B20(100);

	a=ReadOneChar();    	//读取温度值低位
	b=ReadOneChar();   		//读取温度值高位
	temp_value=b<<4;
	temp_value+=(a&0xf0)>>4;               
}
void temp_to_str()   //温度数据转换成液晶字符显示
{
 
 
 
  TempBuffer[0]='t';  //十位
  TempBuffer[1]='i';  //个位
  TempBuffer[2]='m';   //温度符号
  TempBuffer[3]='e';
  TempBuffer[4]='0';
  TempBuffer[5]=':';

  TempBuffer[6]=temp_value/10+'0';  //十位
  TempBuffer[7]=temp_value%10+'0';  //个位
  TempBuffer[8]=0xdf;   //温度符号
  TempBuffer[9]='C';
  TempBuffer[10]='\0';


}

void temp_to_str1()   //温度数据转换成液晶字符显示
{

  
  TempBuffer1[0]='t';  //十位
  TempBuffer1[1]='1';  //十位
  TempBuffer1[2]=':';  //十位
 
  TempBuffer1[3]=T/10+'0';
  TempBuffer1[4]=T%10+'0';
  TempBuffer1[5]=0xdf;   //温度符号
  TempBuffer1[6]='C';
  TempBuffer1[7]='\0';
}





void Delay1ms(unsigned int count)
{
	unsigned int i,j;
	for(i=0;i<count;i++)
	for(j=0;j<120;j++);
}

/*延时子程序*/
void mdelay(uint delay)
{	uint i;
 	for(;delay>0;delay--)
   		{for(i=0;i<62;i++) //1ms延时.
       		{;}
   		}
}



////////////////////////////////////////////////////////////////////////////////////////////////////////////

void show_time()   //液晶显示程序
{

  
                    //开启温度采集程序
  temp_to_str();                 //温度数据转换成液晶字符
  GotoXY(0,0);                //液晶字符显示位置
  Print(TempBuffer);             //显示温度
  GotoXY(1,1);
  
 
                 //扫描延时
}


void show_time1()   //液晶显示程序
{

  temp_to_str1(); 
   GotoXY(0,1);                 //液晶字符显示位置
    Print(TempBuffer1);             //显示温度
   GotoXY(1,1);
  
 
                 //扫描延时
} 


main()
{
   	EN1=1;
	IN1=0;
	LCD_Initial();         //液晶初始化
	Init_DS18B20();        //DS18B20初始化
    initTimer0_Timer1();   //初始化定时器0,定时器1
    initPID();             //初始化PID 参数
                    //进入默认液晶显示
while(1)
 
       {   ReadTemp(); 
	   	   	
		  wd=temp_value;	  
	     show_time();
	    show_time1();	   
	   	
		scanner();		  		
       	if(disp==1)
		{shezhiwendu();
   		 }
		}
}




⌨️ 快捷键说明

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