基于51单片机的水温PID控制系统protues仿真

硬件设计

链接:https://pan.baidu.com/s/1nxUqjmwDl6ZdTEpUanSrFA
提取码:fnaq
在这里插入图片描述

代码设计

#include"reg51.h" 
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
/*****************引脚定义*********************************/
//l298n
sbit output=P2^5;
sbit in1=P2^3;
sbit in2=P2^4;
/********************************/
//AD芯片
sbit CLOCK=P3^1; 
sbit D_IN=P2^7; 
sbit D_OUT=P2^6; 
sbit _CS=P3^0;
/********************************/
//lcd液晶
sbit lcdrs=P2^0;
sbit lcdrw=P2^1;
sbit lcden=P2^2;
/********************************/
//灯
sbit led=P3^2;
//蜂鸣器
sbit speaker=P3^3;
/*****************引脚定义*********************************/
/*****************变量定义(申明)*********************************/
int freq=500,pwm=0;
uchar setflag=0,pageflag=0,ok=0;
float pwm_temp=0;
float  KP=100,KI=10,KD=0;  
uint  pul_count=0;
float ek=0,ek1=0,ek2=0;
float keytemp=0;

uchar code str[16]="    welcome!    ";
uchar code str1[16]=" temperature PID";
uchar code str2[16]="set-T     now-T " ;
uchar code str3[16]="P:     I:     D:" ;
uchar code str4[16]="set-P:       " ;
uchar code str5[16]="set-I:       " ;
uchar code str6[16]="set-D:       " ;
void Init(void);
uint adcread(uchar port); 
void delay(uint n); 
void writecom(uchar com);
void writedata(uchar date);
void initlcd();
float keyscan(void);
uchar keyscans(void);
void lcdnumdisplay(uchar pos,double  f);
void lcdnumdisplays(uchar pos,double  f);
uint read_pul();
void mypid(float Kp,float Ki,float Kd,uint count,uint point);
/*****************变量定义(申明)*********************************/

void main()
{
    uchar i;float scantemp;
	float adnum0=0;
	float adnum1=0;
	bit init0,init1,init2,init3,init4;
	Init();
	initlcd(); 
    writecom(0x80);
	for(i=0;i<16;i++)writedata(str[i]);		 //huanyin
	writecom(0x80+0x40);
	for(i=0;i<16;i++)writedata(str1[i]); 	 //shuming
	delay(2000);
//	output=0;
//	in1=1;in2=0;
//	while(1);
	while(1)
	{ 
		 pwm_temp=500*(float)(adnum0)/4095;
		 //pwm=pwm_temp;
		 mypid(KP,KI,KD,adnum1,pwm_temp);
		 scantemp=keyscan();
		 if(adnum1>=pwm_temp-1.5&&adnum1<=pwm_temp+1.5)
		   {
			led=0;
			speaker=1;
		   }
		else{
		    led=1;
			speaker=0;
			}
	    if(setflag==0)
		{
		 adnum0=adcread(0);
		 adnum1=adcread(1)/45;
		 if(init0==0)
		 {
		 initlcd(); 
		 writecom(0x80);
	     for(i=0;i<16;i++)
					writedata(str2[i]); 	 //shuming
			init0=1;init1=0;init2=0;init3=0;init4=0;
		 }
		 lcdnumdisplays(0x80+0x40,(float)pwm_temp);	 //pwm_temp
		 lcdnumdisplays(0x80+0x4a,(float)adnum1);	 
		 }

		 if(setflag!=0&&pageflag==0)
		 {
		    if(init1==0)
			{
			initlcd();
			writecom(0x80);
			for(i=0;i<16;i++)writedata(str3[i]); 	 
			init0=0;init1=1;init2=0;init3=0;init4=0;
			}
			lcdnumdisplays(0x80+0x40,KP);
			lcdnumdisplays(0x80+0x46,KI);
			lcdnumdisplays(0x80+0x4D,KD);	
		 }
		 if(setflag!=0&&pageflag==1)
		 {
		    if(init2==0)
			{
			initlcd();
			writecom(0x80);
			for(i=0;i<16;i++)writedata(str4[i]); 	 
			init0=0;init1=0;init2=1;init3=0;init4=0;
			}
			lcdnumdisplays(0x80+0x40,scantemp);
			if(ok==1){KP=scantemp;ok=0;}	
		 }
		 if(setflag!=0&&pageflag==2)
		 {
		    if(init3==0)
			{
			initlcd();
			writecom(0x80);
			for(i=0;i<16;i++)writedata(str5[i]); 	 
			init0=0;init1=0;init2=0;init3=1;init4=0;
			}
			lcdnumdisplays(0x80+0x40,scantemp);
			if(ok==1){KI=scantemp;ok=0;}	
		 }
		 if(setflag!=0&&pageflag==3)
		 {
		    if(init4==0)
			{
			initlcd();
			writecom(0x80);
			for(i=0;i<16;i++)writedata(str6[i]); 	
			init0=0;init1=0;init2=0;init3=0;init4=1;
			}
			lcdnumdisplays(0x80+0x40,scantemp);
			if(ok==1){KD=scantemp;ok=0;}		
		 } 	    
    }
}

void mypid(float Kp,float Ki,float Kd,uint count,uint point)
{
   static float Uk;
   ek=point-count;
//   if(ek>=5&&ek<=-5)   //积分分离                                       
   {Uk=Kp*(ek-ek1)+Ki*ek+Kd*(ek-2*ek1+ek2);}       
//   else 
//   Uk=Kp*ek;
   pwm=Uk;
	 //lcdnumdisplays(0x80+0x4a,(float)pwm);	
   if(pwm>freq)pwm=freq;
   if(pwm<=0){pwm=0;in1=0;in2=1;}
   if(pwm>0) {in1=1;in2=0;}
   ek2=ek1;
   ek1=ek;
}
uint read_pul()
{
  uint t1,th1,th2;				 
  uint val;
  while(1)
  {
     th1=TH1;
	 t1=TL1;
	 th2=TH1;
	 if(th1==th2)
	   break;
  }       
     val=th1*256+t1;
	 return val;
} 


void delay(uint n)
{
uint i,j;
for(i=n;i>0;i--)
for(j=1;j>0;j--);
}

void Init(void)//初始化函数
{ 
    TMOD=0x51; 
	TH0=(65536-10)/256;
	TL0=(65536-10)%256;
	EA=1;
	ET0=1;		
	TR0=1;
	TH1=0;
	TL1=0;
	TR1=1;
} 

void  Timer_0(void) interrupt 1
{ 
       static ulong t_count=0;
	   static uint num_count=0;
       TR0=0;
	   TH0=(65536-10)/256;
	   TL0=(65536-10)%256;
	   TR0=1;
	   num_count++; 
//	   t_count++;
//	   if(t_count==2320) 
//	         {
//			     t_count=0;
//				 TR1=0;
//				 pul_count=read_pul();		
//		         TH1=0;
//		         TL1=0; 
//				 TR1=1;
//	         }
	   if(num_count>freq)num_count=0;    //1khz;
	   if(num_count<pwm)output=1;
	   else output=0;
	   
}
//lcd写命令
void writecom(uchar com)
{ 
   lcdrs=0; 
   P0=com;
   delay(1);
   lcden=1;
   delay(1);
   lcden=0;	 
}
//lcd写数据
void writedata(uchar date)
//初始化lcd
{  
   lcdrs=1;	   
   P0=date;
   delay(1);
   lcden=1;
   delay(1);
   lcden=0;	   
 }
void initlcd()
 { 
   lcdrw=0;
   writecom(0x38);delay(1);	
   writecom(0x0c);delay(1); 	 
   writecom(0x06);delay(1);
   writecom(0x01);delay(5); 
 }

//adc读
uint adcread(uchar port) 
{  		
   uint ad=0,i;
	
   CLOCK=0;
   _CS=0;
   port<<=4;
   for(i=0;i<12;i++)
  {
		if(D_OUT) 
			ad|=0x01;
		D_IN=(bit)(port&0x80);
		CLOCK=1;
		delay(1);
		CLOCK=0;
		delay(1);
		port<<=1;
		ad<<=1;
  }
  _CS=1;
	
  ad>>=1;
  return(ad);
}
//lcd显示数据1
void lcdnumdisplays(uchar pos,float f)		//(0.001-99999) 精度低 但方便数据更新
{  
   uchar i;
   writecom(pos);
   if(f>65535&&f<0.001) for(i=0;i<5;i++)writedata(0x23);//超出范围 显示#
   else if(f==0){writedata(0x30);for(i=0;i<4;i++)writedata(0x20);}
   else 
     {
	   if((uint)f/10000!=0)
	   {
	    writedata((uint)f/10000+0x30);
	    writedata((uint)f%10000/1000+0x30);
		writedata((uint)f%1000/100+0x30);
		writedata((uint)f%100/10+0x30);
		writedata((uint)f%10+0x30);
	   }
	   else
	   {
	    if((uint)f/1000!=0)
		{
		writedata(0+0x30);
	    writedata((uint)f/1000+0x30);
		writedata((uint)f%1000/100+0x30);
		writedata((uint)f%100/10+0x30);
		writedata((uint)f%10+0x30);
		}
		else
		{
		  if((uint)f/100!=0)
		  {
		    writedata((uint)f/100+0x30);
		   	writedata((uint)f%100/10+0x30);
		    writedata((uint)f%10+0x30);
			writedata(0x2e);
			writedata((uint)(f*10)%10+0x30);
		  }
		  else 
		  {
		    if((uint)f/10!=0)
			{
			writedata((uint)f/10+0x30);
			writedata((uint)f%10+0x30);
			writedata(0x2e);
			writedata((uint)(f*10)%10+0x30);
			writedata((uint)(f*100)%10+0x30);
			}
			else
			{
			writedata((uint)f%10+0x30);
			writedata(0x2e);
			writedata((uint)(f*10)%10+0x30);
			writedata((uint)(f*100)%10+0x30); 
			writedata((uint)(f*1000)%10+0x30); 
			}
		  }
		 }
	   } 
	 }
}


//lcd显示数据2
void lcdnumdisplay(uchar pos,float f0)		//(0.00001-99999.99999) 精度高 但数据需刷屏更新
 { 
   uchar temp;
   ulong    f;
   writecom(pos);
   f=(ulong)f0;
   temp=f/10000;	 //整数部分
   if(temp!=0)
     {
	    writedata(temp+0x30);
		writedata(f%10000/1000+0x30);
		writedata(f%1000/100+0x30);
		writedata(f%100/10+0x30);
		writedata(f%10+0x30);
	 }
   else
     {
	    temp=f%10000/1000;
		if(temp!=0)
		{
		   writedata(temp+0x30);
		   writedata(f%1000/100+0x30);
		   writedata(f%100/10+0x30);
		   writedata(f%10+0x30);
		}
		else
		{
		   temp=f%1000/100;
		   if(temp!=0)
		   { 
		      writedata(temp+0x30);
			  writedata(f%100/10+0x30);
		      writedata(f%10+0x30); 
		   }
		   else
		   {
		      temp=f%100/10;
			  if(temp!=0)
				{ 
				   writedata(temp+0x30);
				   writedata(f%10+0x30);     
				}
				else
				{
				   temp=f%10;
				   if(temp!=0)
				   {
				     writedata(temp+0x30);
				   }
				   else writedata(0+0x30);
				 }
			  }  
		   }
		} 


    if((ulong)(f0*10)%10!=0||(ulong)(f0*100)%10!=0||(ulong)(f0*1000)%10!=0||(ulong)(f0*10000)%10!=0)		   
	{
	   	   writedata(0x2e);
		   temp=(ulong)(f0*10000)%10;
		   if(temp!=0)
		   {
		     writedata((ulong)(f0*10)%10+0x30);
			 writedata((ulong)(f0*100)%10+0x30);
			 writedata((ulong)(f0*1000)%10+0x30);
			 writedata(temp+0x30);
		   }
		   else
		   {
		       temp=(ulong)(f0*1000)%10;
		       if(temp!=0)
			   {
			     writedata((ulong)(f0*10)%10+0x30);
			     writedata((ulong)(f0*100)%10+0x30);
				 writedata(temp+0x30);
			   }
			   else
			   {
			      temp=(ulong)(f0*100)%10;
				  if(temp!=0)
				  {
				    writedata((ulong)(f0*10)%10+0x30);
					writedata(temp+0x30);
				  }
				  else
				  {
				    temp=(ulong)(f0*10)%10;
					if(temp!=0)
					  writedata(temp+0x30);
				  }
			    }	    
		      }
		    }
 }


  • 7
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 基于51单片机的电子时钟项目需要通过Keil编写程序,并使用Proteus进行仿真电路搭建。该项目主要包括以下几个步骤: 1. 硬件搭建:按照电子时钟的设计需求,连接51单片机和相关的电子元件,如晶体振荡器、数码管、按键等。通过Proteus软件,可以将这些元件连接起来,搭建出完整的电路。 2. Keil程序编写:使用Keil软件,编写51单片机的C语言程序。该程序需要实现时钟的功能,包括时、分、秒的显示和计时、调整时间、闹钟功能等。通过编程,可以控制数码管的显示,以及对按键进行响应。 3. Proteus仿真:将编写好的程序通过Proteus软件连接至搭建好的电路。进行仿真测试时,可以通过模拟时钟的不同状态,调试和验证编写的程序的正确性和稳定性。仿真过程中,可以检查数码管的显示情况,以及程序对按键输入的响应。 4. 优化和调试:根据仿真过程中的结果,对程序进行优化和调试。可能需要根据具体的需求,修改程序中的一些逻辑或代码,确保电子时钟的功能正常运行,并符合设计要求。 总的来说,基于51单片机的电子时钟项目需要通过Keil编写程序,并结合Proteus进行仿真电路搭建和测试。通过这样的开发流程,可以实现一个功能完善、稳定可靠的电子时钟。 ### 回答2: 基于51单片机的电子时钟keil程序和protues仿真电路组成了一个完整的设计方案。 首先,keil程序是用于开发51单片机的集成开发环境,它提供了编译、调试和仿真等功能,能够帮助程序员快速开发出51单片机的应用程序。在电子时钟的设计中,我们可以使用keil来编写单片机的程序代码,实现时钟的各种功能。 其次,protues是一款电子设计自动化软件,它提供了电子电路仿真和PCB布局设计等功能,能够帮助我们快速验证电路的正确性。在电子时钟的设计中,我们可以使用protues来建立电子时钟的仿真电路,验证单片机代码的正确性和稳定性。 基于51单片机的电子时钟设计,我们可以使用keil来编写单片机的程序代码,实现时钟的各种功能,包括时间显示、报时功能、闹钟功能等。通过keil的编译、调试和仿真功能,我们可以验证代码的正确性和稳定性。 在电路设计方面,我们可以使用protues来建立电子时钟的仿真电路,通过仿真可以验证电路的正确性和稳定性,包括时钟电路、数码管驱动电路、按钮输入电路等。通过protues的电路仿真功能,我们可以检查电路设计的错误和漏洞,提前解决电路问题。 基于51单片机电子时钟keil程序和protues仿真电路的组合,我们可以全面验证电子时钟的功能和性能,确保设计的准确性和可靠性,为最终实现一个完整的电子时钟设计提供了有力的支持。 ### 回答3: 基于51单片机的电子时钟keil程序和protues仿真电路可以实现以下功能: 1. 显示当前时间:我们可以使用数码管或LCD显示模块来显示当前的时、分和秒。通过编写相应的程序,我们可以从单片机的时钟源获取当前时间,并将其转换为可以在数码管或LCD上显示的格式。 2. 时间调整功能:可以通过按钮或旋钮等输入设备来调整电子时钟的时间。当用户按下或旋转输入设备时,我们可以响应用户的操作,并对时钟的时间进行相应的调整。 3. 闹钟功能:我们可以设置闹钟功能,让电子时钟在特定的时间点发出警报声。通过在程序中设置闹钟时间和警报声的播放方式,我们可以实现这一功能。 4. 温湿度监测:如果我们希望电子时钟能够同时监测室内的温度和湿度,我们可以连接温湿度传感器,并在程序中读取传感器的数据。然后,我们可以将这些数据显示在数码管或LCD上。 程序开发过程中,我们可以使用keil来编写51单片机的程序,通过keil提供的调试工具来测试和调试程序的正确性。同时,我们可以在protues中设计和仿真电子时钟的电路,包括单片机、显示模块、输入设备和传感器等所有的硬件组件。这样,我们可以在protues中验证电路的功能和效果,并进行性能优化和调试。当电路和程序都满足我们的要求后,我们就可以将程序烧录到实际的硬件上,并使用它作为一台完整的电子时钟了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值