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

📄 wenducontrol.c

📁 温度控制系统
💻 C
字号:
/***********************************************************
 温度控制系统
       2004-4-29
SUPCON Instrument & Equitment Co,.Ltd.
P0口用于液晶数据口
***********************************************************/
#include<reg51.h>
#include<intrins.h>
#include<math.h>
sbit RS=P1^2;
sbit RW=P1^1;
sbit E=P1^0;
sbit plus=P2^0;
sbit subs=P2^1;
sbit stop=P2^2;
sbit output=P3^4;
sbit DQ=P3^3;
unsigned char flag,flag_1;
unsigned char high_time,low_time,count=0;//占空比调节参数
unsigned char set_temper=22;		 //设定温度
unsigned char temper,temper1;			 //测量的温度
unsigned char i;
unsigned char j=0;
/***********************************************************
延时子程序,延时时间以12M晶振为准,延时时间为30us×time
***********************************************************/
void delay(unsigned char time)
  {
   unsigned char m,n;
     for(n=0;n<time;n++)
       for(m=0;m<2;m++){}
 }
/***********************************************************
写一位数据子程序
***********************************************************/
void write_bit(unsigned char bitval)
  {
    EA=0;
      DQ=0;		//拉低DQ以开始一个写时序
    if(bitval==1)
       {
        _nop_();
        DQ=1; 		//如要写1,则将总线置高
        }
      delay(5);  	//延时90us供DA18B20采样
    DQ=1;		//释放DQ总线
    _nop_();
    _nop_();
   EA=0;
   }
/***********************************************************
写一字节数据子程序
***********************************************************/
void write_byte(unsigned char val)
 {
  unsigned char i;
  unsigned char temp;
  EA=0;
  //TR0=0;
  for(i=0;i<8;i++)		//写一字节数据,一次写一位
      {
       temp=val>>i;		//移位操作,将本次要写的位移到最低位
       temp=temp&1;
       write_bit(temp);		//向总线写该位
       }
   delay(7);			//延时120us后
 // TR0=1;
  EA=1;
  }
/***********************************************************
读一位数据子程序
***********************************************************/
unsigned char read_bit()
 {
  unsigned char i,value_bit;
  EA=0;
  DQ=0;			//拉低DQ,开始读时序
  _nop_();
  _nop_();
  DQ=1;			//释放总线
  for(i=0;i<2;i++){}	//8us delay
  value_bit=DQ;
  EA=1;
  return(value_bit);
  }
/***********************************************************
读一字节数据子程序
***********************************************************/
unsigned char read_byte()
  {
   unsigned char i;
   unsigned char value=0;
   EA=0;
   for(i=0;i<8;i++)
      {
       if(read_bit())		//读一字节数据,一个时序中读一次,并作移位处理
         value|=0x01<<i;
       delay(4);		//延时80us以完成此次都时序,之后再读下一数据
       }
   EA=1;
   return(value);
  }
/***********************************************************
复位子程序
***********************************************************/
unsigned char reset()
  {
   unsigned char presence;
  EA=0;
   TR0=0;
   DQ=0;			//拉低DQ总线开始复位
   delay(30);			//保持低电平480us
   DQ=1;			//释放总线
   delay(3);			//等待芯片应答信号 75us
   presence=DQ;			//获取应答信号
   delay(28);			//延时以完成整个时序
   TR0=1;
  EA=1;
   return(presence);		//返回应答信号,有芯片应答返回0,无芯片则返回1
  }
/***********************************************************
获取温度子程序
***********************************************************/
void get_temper()
 {
  unsigned char i,j;
  do
  {
    i=reset();		//复位
  }while(i!=0);		//1为无反馈信号
  i=0xcc;		//发送设备定位命令
  write_byte(i);
  i=0x44;		//发送开始转换命令
  write_byte(i);
  delay(180);		//延时
  do
  {
  i=reset();		//复位
  }while(i!=0);		//0为无反馈信号,再次复位
  i=0xcc;		//设备定位
  write_byte(i);
  i=0xbe;		//读出缓冲区内容
  write_byte(i);
  j=read_byte();	//先读出低位
  i=read_byte();  	//后读出高位
  i=(i<<4)&0x7f;
  j=j>>4;
  temper=i|j;
  }
/***********************************************************
温度比较处理子程序
***********************************************************/
compare_temper()
  {
   if(++flag_1==2)
     {
      if(set_temper>temper)
         {
          if(low_time!=0) 		//温度未达到,但占空比已经100%,则不执行
             {
              high_time++;
              low_time=100-high_time;
             }
           }
      else if(set_temper<temper)
            {
             if(high_time!=0)		//温度超过设定温度,但占空比已经为1%,则不执行
               {
                high_time--;
                low_time=100-high_time;
               }
             }
       else
           {}
      flag_1=0;
      }
  }
/*****************************************************
T0中断服务子程序,用于控制电平的翻转	,40us*100=4ms周期
******************************************************/
void serve_T0() interrupt 1 using 1
  {
   if(++count<=(high_time))
     output=1;
   else if(count<=100)
     {
      output=0;
      }
   else
      count=0;
   TH0=0xff;
   TL0=0xd8;
   }
/*****************************************************
串行口中断服务程序,用于上位机通讯
******************************************************/
void serve_sio() interrupt 4 using 2
  {
   EA=0;
   RI=0;		//clear receive flag
   i=SBUF;
   if(i==2)
      {
       while(RI==0){}		//等待接收温度值
       RI=0;
       set_temper=SBUF;		//设定控制温度值
       SBUF=0x02;		//发给主机02
       while(TI==0){}
       TI=0;
       }
    else if(i==3)		//主机要求采样温度,发温度值
       {
        j=temper;
        //j=126;
        TI=0;
        SBUF=j;
        while(TI==0){}
        TI=0;
        }
     EA=1;
     //TI=0;
     //SBUF=68;
    //while(TI==0){}
     //TI=0;
   }

/*************************************
判断液晶是否忙子程序
*************************************/
void busy()
 {
  unsigned char i;
  EA=0;
  RS=0;			//读写指令代码时RS为低电平有效
  RW=1;			//读出数据或指令时为高电平有效
    P0=0xff;		//向P1口写1
    E=0;		//在E的下降沿数据写入或读出
    E=1;
  do
   {
    i=P0;
    }while((i&0x80)!=0);
   E=0;
  EA=1;
 }
/*************************************
向液晶写入命令子程序
*************************************/
void com(n)
unsigned char n;
{
  EA=0;
    busy();
    RW=0;
    RS=0;
    P0=n;
    E=1;
    E=0;
  EA=1;
  }
/*************************************
向液晶写入数据子程序
*************************************/
void dat(n)
unsigned char n;
  {
   EA=1;
    busy();
    RW=0;
    RS=1;
    P0=n;
    E=1;
    E=0;
   EA=1;
   }
/***********************************************************
显示子程序
***********************************************************/
void display()
 {
  unsigned char j,k,disp[10]={0,0,0x25,0,0,0,0,0,0,0};
  unsigned int i;
  i=1;
  com(i);
  k=temper;						//清屏
  i=(int)(high_time);					//计算占空比
  disp[10]=i/100+0x30;
  i=i%100;
  disp[0]=i/10+0x30;
  disp[1]=i%10+0x30;

  i=k/100;						//显示测量的温度
  disp[3]=i+0x30;
  i=k%100;
  j=i/10;
  disp[4]=j+0x30;
  disp[5]=i%10+0x30;
  i=set_temper/100;				    	//显示设定的温度
  disp[6]=i+0x30;
  i=set_temper%100;
  j=i/10;
  disp[7]=j+0x30;
  disp[8]=i%10+0x30;
  i=0x80;
  com(i);
  i=0x4b;			//显示"K:"
  dat(i);
  i=0x3a;
  dat(i);
  i=disp[10];
  if(i==0x30)
    i=0x20;
    j=i;
  dat(i);
  i=disp[0];
  if((j==0x20)&&(i==0x30))
    i=0x20;
  dat(i);
  i=disp[1];
  dat(i);
  i=disp[2];
  dat(i);
  i=0x88;
  com(i);
  i=0x54;
  dat(i);			//show "Tg:"
  i=0x67;
  dat(i);
  i=0x3a;
  dat(i);
  i=disp[3];
  if(i==0x30)
    i=0x20;
    j=i;
  dat(i);
  i=disp[4];
  if((j==0x20)&&(i==0x30))
    i=0x20;
  dat(i);
  i=disp[5];
  dat(i);
  i=0xc8;
  com(i);
  i=0x54;
  dat(i);			//show "Ts:"
  i=0x73;
  dat(i);
  i=0x3a;
  dat(i);
  i=disp[6];
  if(i==0x30)
    i=0x20;
  dat(i);
  i=disp[7];
  if((j==0x20)&&(i==0x30))
    i=0x20;
  dat(i);
  i=disp[8];
  dat(i);
  temper=k;
  }
/***********************************************************
主程序
***********************************************************/
 main()
 {
  unsigned char z;
  unsigned char a,b,flag2=1;
  TMOD=0x21;			//T1为8位重装定时器,T0为16位定时器
  TH0=0xff;			//10ms中断
  TL0=0xd8;
  SCON=0x50;			//串口工作于方式1,允许接收,采用中断方式
  PCON=0x00;           		//波特率不加倍
  TH1=0xfd;			//波特率为9600
  TL1=0xfd;

  PS=1;			        //串口中断优先
  EA=1;				//开总中断
  EX1=0;			//关外部中断
  ET0=1;			//开定时器0中断
  ES=1;				//开串行口中断
  TR0=1;			//定时器1开始计时
  TR1=1;
  high_time=50;                 //初始化为占空比50%,周期为200ms
  low_time=50;
  com(1);       		//液晶初始化
  com(6);
  com(0x0c);
  com(0x38);
  while(1)
       {
           if(plus==0)
             {
              set_temper=set_temper+1;
              if(set_temper>80)
                 set_temper=1;
              flag=0;
              for(a=0;a<100;a++)
                 for(b=0;b<102;b++){}
              }
            else if(subs==0)
              {
               set_temper=set_temper-1;
               if(set_temper>80)
                 set_temper=80;
               flag=0;
               for(a=0;a<100;a++)
                 for(b=0;b<102;b++){}
               }
                else if(stop==0)
                 {
                   delay(100);
                   flag=0;		        //为停止键,跳出循环,只显示,没有控制
                   com(1);			//清屏指令
                   break;
                  }
      get_temper();
      //b=temper;
      //if(flag2=1)
        // a=b;
      //if((fabs(a-b))>5)
       // temper=a;
      //else
      //  temper=b;
      a=temper;
      flag2=0;
      display();		//用液晶来显示
      compare_temper();  	//温度比较和控制
       }
    TR0=0;
    z=1;
    com(z);
 while(1)
      {
       z=0x85;			//停止后,只显示STOP!
       com(z);
       z=0x53;
       dat(z);
       z=0x54;
       dat(z);
       z=0x4f;
       dat(z);
       z=0x50;
       dat(z);
       z=0x21;
       dat(z);
       if(stop==0)
       {
       delay(100);
       flag=1;		        //为停止键,跳出循环,只显示,没有控制
        com(1);			//清屏指令
        break;
        }
     }
 }


⌨️ 快捷键说明

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