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

📄 main.c

📁 一个实用的pid算法
💻 C
字号:
#include	"reg52.h"
#include <intrins.h>
#define uchar 	unsigned char
#define uint 	unsigned int

/****************************************************************
 
       I2C总线协议程序

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

#define  NOP _nop_()     /*定义空指令*/
 
sbit SDA=P1^2;           /*模拟I2C数据传送位*/
sbit SCL=P1^3;           /*模拟I2C时钟控制位*/
bit ack;	             /*应答标志位*/
   
void Start_I2c()
{
  SDA=1;  NOP;
  SCL=1;  NOP;   
  SDA=0;  NOP;        
  SCL=0;  NOP; 
}

void Stop_I2c()
{
  SDA=0;  NOP;  
  SCL=1;  NOP; 
  SDA=1;  NOP;  
}

void  Senduchar(uchar c)
{
  uchar i;
  for(i=0;i<8;i++)  /*要传送的数据长度为8位*/
  {
     if((c<<i)&0x80)SDA=1;  
	 else  SDA=0;  NOP;
     SCL=1;  NOP;          
     SCL=0;  NOP;
  }
    
  SDA=1;  NOP;     
  SCL=1;  NOP;   
  if(SDA==1)ack=0;  else ack=1;      
  SCL=0;  NOP; 
}

uchar  Rcvuchar()
{
  uchar x=0;
  uchar i;
  
  SDA=1;             /*置数据线为输入方式*/
  for(i=0;i<8;i++)
  {
    SCL=0;  NOP;   
    SCL=1;  NOP; 
    x=x<<1;
    if(SDA==1) x=x+1; /*读数据位,接收的数据位放入retc中 */
    NOP; 
  }
  SCL=0;  NOP;  
  return(x);
}


void Ack_I2c(bit a)
{
  
  if(a==0) SDA=0;  
  else SDA=1;
  NOP;        
  SCL=1; NOP;   
  SCL=0; NOP;    
}

bit ISendStr(uchar sla,uchar suba,uchar *s,uchar no)
{
   uchar i;

   Start_I2c();               /*启动总线*/
   Senduchar(sla);            /*发送器件地址*/
   if(ack==0)return(0);
   Senduchar(suba);            /*发送器件子地址*/
   if(ack==0)return(0);

   for(i=0;i<no;i++)
   {   
     Senduchar(*s);               /*发送数据*/
     if(ack==0)return(0);
     s++;
   } 
  Stop_I2c();                 /*结束总线*/ 
  return(1);
}


bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no)
{
   uchar i;

   Start_I2c();               /*启动总线*/
   Senduchar(sla);             /*发送器件地址*/
   if(ack==0)return(0);
   Senduchar(suba);            /*发送器件子地址*/
   if(ack==0)return(0);

   Start_I2c();
   Senduchar(sla+1);
   if(ack==0)return(0);

   for(i=0;i<no-1;i++)
    {   
     *s=Rcvuchar();               /*发送数据*/
      Ack_I2c(0);                /*发送就答位*/  
     s++;
    } 
   *s=Rcvuchar();
   Ack_I2c(1);                 /*发送非应位*/
   Stop_I2c();                 /*结束总线*/ 
   return(1);
}

/****************************************************************
 
       ZLG7219程序

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

#define zlg7290 0x70 //ZLG7290的IIC地址
#define SubKey  0x01 
#define SubCmdBuf 0x07
#define SubDpRam 0x10

void delayMS(uint i)
{ 
	uchar j;
	while(i--)
		for(j=0;j<60;j++);
}


uchar ZLG7290_SendCmd(uchar Data1,uchar Data2)
{
    uchar Data[2];
	Data[0]=Data1;
	Data[1]=Data2;
	ISendStr(zlg7290,0x07,Data,2);
	delayMS(10);
	return 1;
}  


uchar	ZLG7290_GetKey()
{
    uchar rece;
	rece=0;
	IRcvStr(zlg7290,1,&rece,1);
	delayMS(10);
	return rece;
}


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

   TLC549   A/D转换
   TLC5620  D/A转换

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

sbit  CLK=P1^5;
sbit  DAT=P1^6;
sbit  CS =P1^7;
sbit  LOAD=P1^4;
uchar TLC549ADC(void)
{
	uchar i,x;
	CLK=0; DAT=1; CS=0;
	for(i=0;i<8;i++)
	{
		CLK=1; NOP;	
		x<<=1;
		if(DAT==1) x++;
		CLK=0; NOP;
	}
	CS=1;
	return (x);
}


void  DAC5620(uchar ch,uchar dat) 
{
    uchar i,x;
	ch=ch<<6;
	x=ch;//+0x20;		//这里要看参考电压是5V还是2.5V
	for(i=0;i<3;i++)
	{
		x=x<<1;
		DAT=CY;;
	    CLK=1; NOP;  
		CLK=0; NOP;
	}
	x=dat;
	for(i=0;i<8;i++)
	{
		x=x<<1;
		DAT=CY;;
	    CLK=1; NOP;  
		CLK=0; NOP;
	}
	LOAD=0;	LOAD=1;
}

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

sbit	RST=P1^0;
sbit	KEY_INT=P3^3;
uchar key,adc,dac,sr;
int  r,e0,e1,e2,y0,u;
uint m,s,tm1,tm2;
unsigned char disp[8]={8,9,5,1,5,2,6,7};
#define time1 -10000
#define time2 -2000
#define K 20			//@@@* 加入K只是为了化小数运算为整数运算,加入K即是将原来小数的Kp,Ki,Kd乘上K得现在整数的Kp,Ki,Kd,K可取100
#define Kp 3
#define Ki 1
#define Kd 0

void Display() interrupt 1
{
  TH0=time1>>8;TL0=time1&0xff;
  tm1++;
}

void GetKey() interrupt 2 
{
  key=ZLG7290_GetKey();
}


void Control() interrupt 3
{
  TH1=time2>>8;TL1=time2&0xff;
  if(++tm2>10)
  {
     tm2=0; 
	 adc=TLC549ADC();
     y0=adc;r=sr;
	 e2=e1; e1=e0; e0=r-y0;
	 u+=e0*Ki+(e0-e1)*Kp+(e0-2*e1+e2)*Kd;
	 if(u>255*K) u=255*K;
	 if(u<0) u=0;
	 dac=u/K;
     DAC5620(3,dac);	
  }
}

void main()
{
    uchar i,p,n;
	IE=0x80+0x08+0x04+0x02;  TMOD=0x11; IT1=1;
    TH0=time1>>8;TL0=time1&0xff;TR0=1;
    TH1=time2>>8;TL1=time2&0xff;TR1=1;
	RST=0;	
	delayMS(10);
	RST=1;	sr=0x80;
	delayMS(10);
	tm1=0; tm2=0; m=0;
	DAC5620(0,0x20);
	DAC5620(1,0x40);
	DAC5620(2,0x80);
	DAC5620(3,0xc0);
 	while(1)
	{
        if(tm1>50) 
		{
		  tm1=0; s=p;
	  	  switch(key)
		  {
		    case 1: sr=0x10; break;
		    case 2: sr=0x30; break;
		    case 3: sr=0x50; break;
		    case 4: sr=0x70; break;
		    case 5: sr=0x90; break;
		    case 6: sr=0xb0; break;
		    case 7: sr=0xd0; break;
		    case 8: sr=0xf0; break;
		  }
          if(key!=0) n=key;  
		  key=0;
		  disp[0]=dac&0xf;
		  disp[1]=(dac>>4)&0xf;
		  disp[2]=0x1f;
		  disp[3]=adc&0xf;
		  disp[4]=(adc>>4)&0xf;
		  disp[5]=0x1f;
		  disp[6]=sr&15;
		  disp[7]=(sr>>4)&15;
          for(i=0;i<8;i++) 
          {
             ZLG7290_SendCmd(0x60+i,disp[i]);
	         delayMS(10);
          }
		}
	}
}

⌨️ 快捷键说明

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