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

📄 tempdisplay.c

📁 温度控制系统的C程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*-----------------------------------------------------------------------
;MAX1169
-------------------------------------------------------------------------*/
// I2C通用驱动AD程序


SomeNOP(void)
{  //uchar ij=255;
  //   while(ij--){
_nop_();_nop_();_nop_();_nop_();}
//} 

/*--------------------------------------------------------------------------------
调用方式:void I2CStart(void) 2005/12/10
函数说明:私有函数,I2C专用
---------------------------------------------------------------------------------*/
void I2CStart(void)
{
//EA=0;
SDA=1; //SomeNOP();//SCL保持高,SDA从高到低一次跳变,I2C通信开始
SCL=1; SomeNOP();
SDA=0; SomeNOP(); 
SCL=0; SomeNOP();
}
/*--------------------------------------------------------------------------------
调用方式:void I2CStop(void) 2005/12/10
函数说明:私有函数,I2C专用
---------------------------------------------------------------------------------*/
void I2CStop(void)
{
//SCL=0; 
SDA=0; //SomeNOP(); //SCL保持高,SDA从低到高一次跳变,I2C通信停止
SCL=1; SomeNOP(); 
SDA=1; SomeNOP();
SCL=0; SomeNOP();
//EA=1;
}

/*--------------------------------------------------------------------------------
调用方式:I2CAck(void) 2005/12/10
函数说明:私有函数,I2C专用,等待从器件接收方的应答
ACK BY 
---------------------------------------------------------------------------------*/
WaitAck(void)
{
unsigned char errtime=255;//因故障接收方无ACK(ACK对应SDA=0),超时值为255。

SDA=1;
//SDA=0;
SCL=1;
SystemError=0x10; 
while(SDA)
  { errtime--;
    if(!errtime)
     { I2CStop();
       SystemError=0x11; //出错后给全局变量赋值
       return;
      }
  };
SCL=0;
_nop_();
}


/*--------------------------------------------------------------------------------
调用方式:void SendAck(void) ﹫2005/12/10
函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,应答信号。
---------------------------------------------------------------------------------*/
void SendAck(void)
{
SDA=0; SomeNOP(); //数据线保持低,时钟线发生一次从高低的跳变 发送一个应答信号
SCL=1; SomeNOP();
SCL=0;
}

/*--------------------------------------------------------------------------------
调用方式:void SendAck(void) ﹫2005/12/10
函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,非应答信号。
--------------------------------------------------------------------------------*/
void SendNotAck(void)
{
SDA=1; SomeNOP(); //数据线保持高,时钟线发生一次从高低的跳变 没有应答
SCL=1; SomeNOP();
SCL=0;
}

/*--------------------------------------------------------------------------------
调用方式:void I2CSend(uchar ch) 2005/12/10
函数说明:私有函数,I2C专用                               
---------------------------------------------------------------------------------*/
void I2CSendByte(uchar ch)  //write device
{
unsigned char i=8;

while (i--)
{
SCL=0;_nop_();
SDA=(bit)(ch&0x80); ch<<=1; SomeNOP(); //SCK下降沿发送数据
SCL=1; SomeNOP();
}
SCL=0;

}
/*--------------------------------------------------------------------------------
调用方式:uchar I2CReceive(void) 2005/12/10
函数说明:私有函数,I2C专用
---------------------------------------------------------------------------------*/
uchar I2CReceiveByte(void)    //read  device
{
unsigned char i=8,datatmp=0;
SDA=1;           //释放总线
while(i--)
{
  datatmp<<=1;
  SCL=0;SomeNOP();
  SCL=1;SomeNOP(); //SCL做一次从低到高的跳变 可以接收数据
  datatmp|=SDA;
  };
SCL=0;
return datatmp;
}

/*--------------------------------------------------------------------------------
调用方式:uint ADC(void) 2005/12/10
函数说明:用于max1169AD转换测试(转换前是否一定要进行“HS MODE”设置?N,上电即默认为FS)
---------------------------------------------------------------------------------*/
uint ADC(uchar addr)
{       
	uint  adc_data;
    uchar nt1;

	I2CStart();
    nt1=(addr<<1)|0x61;
	I2CSendByte(nt1);      //写入器件地址,并设置器件为R模式
	WaitAck();                         //写入地址后,器件向主机发送ACK。
	
//	SCL=0;                           //用延时的方式等待SCK变高(转换时SCK被max1169置低)
//	SomeNOP();
//	while(!SCL); //由于转换过程很短,转换过程中SCL保持低,转换结束后slave释放对SCL控制权,但SCL仍然为0
	
	adc_data=I2CReceiveByte();        //read d15~d8
	SendAck();
	adc_data<<=8;
	adc_data=adc_data|I2CReceiveByte();  //read d7~d0
	SendNotAck();
	I2CStop();
	
	return(adc_data);
}


void delay(uchar x)
       {    uchar j;
	      for(j=0;j<x;j++)
	         _nop_();
	     }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*-----------------------------------------------------------------------------------------------------------
;中位值平均滤波程序
函数说明: 相当于“中位值滤波法”+“算术平均滤波法”连续采样N个数据,去掉一个最大值和一个最小值然后计算N-2个
           数据的算术平均值
-----------------------------------------------------------------------------------------------------------*/
float filter()
{
   uchar count,i,j,k;
   uint ch_adc[N];
   uint temp;
   float  sum=0.0;
   for  (count=0;count<N;count++)
   {
	  ch_adc[count]=ADC(0x6);
      delay(80);
   }
   _nop_();
  
    for (i=0;i<N-1;i++)
	{
	  k = i;
	  for (j=i+1;j<N;j++)
	    if (ch_adc[j]<ch_adc[k])  k=j;
           temp = ch_adc[k]; ch_adc[k] = ch_adc[i]; ch_adc[i] = temp;	//选择法进行排序    
	}

   for(count=1;count<N-1;count++)
      sum += (float)ch_adc[count];
  	 return (float)(sum/(N-2));
}


/*-----------------------------------------------------------------------------------------------------------
;温度转化程序
函数说明:30~40度的温度曲线
-----------------------------------------------------------------------------------------------------------*/

  double  temptrans(float x)
   {
      double y;
      y=a1*x*x*x+a2*x*x+a3*x+a4;
      return y;
   }


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

/*-----------------------------------------------------------------------------------------------------------
;MAX5541控制程序
-----------------------------------------------------------------------------------------------------------*/
/*void delayms(uchar x)
{
     uchar i; 
     for(i=0;i<x;i++); 
}*/

void  ad5541_ck(void){
      SCLK=0;_nop_();_nop_();       
      SCLK=1;_nop_();_nop_();       
}

void  ad5541(uint da1){
 
      uchar r=16;
      uint ch;
      ch=da1;

      DA_CS=1;
      //dacs2=1;
      ad5541_ck();
      DA_CS=0;
      while (r--){
          DIN=ch&0x8000;
          ad5541_ck();
          ch<<=1;
      }
      DA_CS=1;
      _nop_();_nop_();_nop_();
}

/*----------------------------------------------------------------------------------------------------
    常规PID控制炉温程序(只用到了PI部分)
-----------------------------------------------------------------------------------------------------*/

signed int  pid(struct PIDpara *sp)  
{                                   
   signed int ek = 0,duk = 0,uk = 0;       //ek为当次采样比较误差,duk为pid运算结果
   uint yk;
   yk = (uint)filter() + 9600; 

   ek = sp->rk - yk;   
   duk = (sp->kp + sp->ki) * ek - sp->kp * sp->ek1;
   uk = sp->uk1 + duk;
   sp->ek1 = ek;                       //e(k)数据更新,给下一次PID运算使用
   sp->uk1 = uk;                       //u(k)数据更新
   return(uk);                         //输出给函数返回值
 
}
   

//   -----------------------------------------------------------------------------------------------

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

/*----------------------------------------------------------------------------------------------------------
;温控系统主程序
-----------------------------------------------------------------------------------------------------------*/
main()
{
 uint  DA_i=0;
 uint  ukout=0;
 uint counter = 0;
 //uint rk = 19316;     //40度
 //uint rk = 20000;     //50度
 uint rk = 28600;     //60度
 //uint rk = 34727;     //70度
 //uint rk = 38674;     //80度
 uint yk;
 auto struct PIDpara *p1,data1={3.14,0.065,28600,0,0}; 
 auto struct PIDpara *p2,data2={3.14,0,28600,0,0}; 



 TMOD = 0x01;        //采用定时器0方式1
 TH0 = -100000/256;   //定时器预置计数初值
 TL0 = -100000%256;
 EA = 1;             //CPU开中断
 ET0 = 1;            //开C/T中断
 TR0 = 1;            //启动C/T 
          
  while(1)
  {
     // _nop_();

    if(!(counter++ % 10))
     {   
       disp();
     }
    if(!(counter++ % 30))            //每隔3s做一次运算
     { 
	                           
	   if(rk - yk < 0x1420)          //积分分离PID,当温度大于10度仅为P控制器,当温度小于10度加入积分
	      {
		    p1 = &data1;                //PID参数赋初值
	        ukout = Umax - pid(p1);
		  }
	   else
	      { 
		    p2 = &data2;
	        ukout = Umax - pid(p2);
		  }
            ad5541(ukout);
		  
     }

  }
	   
}




⌨️ 快捷键说明

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