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

📄 c1.c

📁 用PID算法控制一个加热装置烧水(有传感器测量水温)
💻 C
字号:
#include "hardware.h"
#include "SPCE061V004.h"
#include "unSPMACRO.h"
#include "math.h"
#define initialb 0xff0f
#define initiala 0xfffe
#define	P_ADC_MUX_Ctrl (volatile unsigned int *)(0x702B)
//#define	P_ADC_Ctrl (volatile unsigned int *)(0x7015)

#define P_ADC_MUX_Data (volatile unsigned int *)(0x702C)


//#define *P_ADC_MUX_Ctrl 0x702b
//#define *P_ADC_MUX_Data 0x702c




//void init();




//描述水温的各个参量

unsigned int temperature; //当前水的温度
unsigned int settemperature; //设定的水温
int integral;  //稳态时一段时间的温度偏差积累
int pgain; //比例调整的比例系数
int igain; //积分系数
int dgain; //微分系数
int deadband;  //决定是只进行比例调整还是PID综合调整的界限(当前水温和设定水温的差值)
int last_error;//上次调节后实际温度与设定温度的差值

int tag,tag1,tag2,tag3,tag4;
int reg;//控制波形翻转

int key1,key2,key3,key4,key5,key6,key7,key8,key9,key10,key11,key12,key13,key14,key15,key16;//各个按键的确认变量
int change;//调整占空比的变量

int err;
int delay;
int ave;
unsigned int temperature1;
int show_time,show_what;
int second,minute,hour;
int time_temp;
int slow;


void initial()//初始化IO口以及各个参量值
{
  //_init();
  *P_IOA_Dir=initiala; //设置A,B口的属性
  *P_IOA_Attrib=0xffff;
  *P_IOA_Data=0x0000;
  *P_IOB_Dir=initialb;
  *P_IOB_Attrib=initialb;
  *P_IOB_Data=0x0000;
  tag3=*P_IOB_Attrib;
  key1=key2=key3=key4=key5=key6=key7=key8=key9=key10=key11=key12=key13=key14=key15=key16=0;//按键检测变量初始化 
  reg=0;  //频率控制量初始化
  *P_INT_Ctrl=0x0010;//设置中断
  asm("IRQ ON");
  integral=0;//PID算法的个变量初始化
  pgain=13;
  igain=5;
  dgain=4;
  last_error=0;
  tag=0;
  //*P_DAC_Ctrl=0x0000;
  //asm("[P_ADC_MUX_Ctrl]=%0"::"r"(0x0001));
  *P_ADC_MUX_Ctrl=0x0007;//设置IOA6为模拟信号输入
  tag1=*P_ADC_MUX_Ctrl;
  *P_ADC_Ctrl=0x0101;//关断2V电压使用参考电压为AVdd并允许AD转换同时屏蔽MICIN
  tag2=*P_ADC_Ctrl;
  //asm("[P_ADC_Ctrl]=%0"::"r"(0x0003));
  temperature=0;  //温度初值 
  settemperature=40;
  delay=0;
  ave=0;
  temperature1=0;
  show_time=show_what=second=minute=hour=0;
  time_temp=0;
  slow=0;
  
}

void key()//扫描键盘,检测到有效按键时,修改对应的参量值
{
  unsigned int temp1;
  
  *P_IOB_Data=0x00fe;//扫描键盘第一行
  temp1=*P_IOB_Data;
  temp1^=0x00fe;
  if(temp1==0x0010)
  	key1=1;
  else if(temp1==0x0020)
  	key2=1;
  else if(temp1==0x0040)
  	key3=1;
  else if(temp1==0x0080)
  	key4=1;
  	
  if(temp1==0&&key1==1)//按键一的处理程序
  {
  	key1=0;
  	settemperature++; 
  	show(settemperature,temperature);
  }
  else if(temp1==0&&key2==1)//按键二的处理程序
  {
  	key2=0;
  	settemperature--; 
  	show(settemperature,temperature);
  }
  else if(temp1==0&&key3==1)//按键三的处理程序
  {
  	key3=0;
  	settemperature+=10;
  	show(settemperature,temperature);
  }
  else if(temp1==0&&key4==1)//按键四的处理程序
  {
  	key4=0;
  	settemperature-=10;
  	show(settemperature,temperature);
  }	
  	
  	
  *P_IOB_Data=0x00fd;//扫描键盘第二行
  temp1=*P_IOB_Data;
  temp1^=0x00fd;
  if(temp1==0x0010)
  	key5=1;
  else if(temp1==0x0020)
  	key6=1;
  else if(temp1==0x0040)
  	key7=1;
  else if(temp1==0x0080)
  	key8=1;
  
  
  if(temp1==0&&key5==1)
  {
    key5=0;
    show_time=0;
  }
  else if(temp1==0&&key6==1)
  {
    key6=0;
    show_time=1;
  }
  else if(temp1==0&&key7==1)
  {
    key7=0;
    show_what=0;
  }
  else if(temp1==0&&key8==1)
  {
    key8=0;
    show_what=1;
  }

  
}
void calculate()//根据水温的当前状态和设定状态计算各个参量值
{
  int pterm,dterm;
  err=settemperature*10-temperature;//计算当前水温和设定水温之间的差距
  if(abs(err)>deadband)//如果温差大于设定值,就进行PID调节
  {
    pterm=err*pgain;//计算比例调节量
    if(pterm>100||pterm<-100)//温差过大,不用积分调整
      integral=0;
    else
    {
      integral+=igain*err;
      if(integral>100)//积分值界限
        integral=100;
      else if(integral<0)
        integral=0;	
    }
    dterm=(err-last_error)*dgain;//计算微分调整量
    change=pterm+dterm+integral;//计算最终调节量
  }
  else
  {
    if(integral>200)
      integral=0;
    integral+=err;
    if(integral>0)
      change=integral;//温差不大,只进行积分调节
    else
      change=2;
  }
  if(abs(change)>998)change=998;
  last_error=err;  //更新温差
}


void ad()
{
  unsigned int check;
  unsigned int temp2;
  check=*P_ADC_MUX_Ctrl;
  check&=0xc000;//判断是否完成AD转换
  if(check==0x8000)
  {
    temp2=*P_ADC_MUX_Data;
    tag4=temp2;
    if(ave==64)
    { 
      temperature=temperature1>>6;
      if(temperature>340)  
        temperature+=(temperature-340)/8;
      //else
        //temperature-=(300-temperature)/10;
      if(show_what==0)  
        show(settemperature,temperature);
      delay=0;
      ave=0;
      temperature1=0;
    }
  }
}


void InitIO_7219()
{ 
   *P_IOB_Dir|=0x0400; 
   *P_IOB_Attrib|=0x0400;
   *P_IOB_Data|=0x0400;
   *P_IOB_Dir|=0x0200; 
   *P_IOB_Attrib|=0x0200;
   *P_IOB_Data|=0x0200; 
   *P_IOB_Dir|=0x0100;
   *P_IOB_Attrib|=0x0100;
   *P_IOB_Data|=0x0100;
   SendData_7219(0x0c,0x01); // 使其7219工作正常模式 
   SendData_7219(0x0b,0x07); // 配置scan limit模式,使其8个管子都工作
   SendData_7219(0x0a,0x0f); // 设置亮度为最亮 
   SendData_7219(0x0d,0xff);
   SendData_7219(0x09,0xff); // 使8个管子都用编码方式
                                    //第七位设置为1,可以启动该位小数点
}




void time_display()
{
  int  data;
  int b;
  if(second>=60)
  {
    minute++;
    second=0;
  }
  if(minute>=60)
  {
    hour++;
    minute=0;
  }  
  if(hour>=24)
    hour=0;
   data=second+100*minute;
  if(show_time==1&&show_what==1)
    show(hour,data);
    
}





int main()
{
   initial();//初始化IO口,设定一些变量的初值
   InitIO_7219();
   while(1)
   {
     ad();//将前向电路采集到的电压信号转换为数字信号
     key();//扫面键盘,改变对应键值
     if(settemperature<=55)
       deadband=70;
     else if(settemperature<=70)
       deadband=45;
     else  
       deadband=10;
     time_display();
     calculate();//核心部分,PID计算
     //display();//显示当前水温和设定水温
   }  
}

void IRQ4(void)__attribute__((ISR));
void IRQ4(void)
{
  unsigned int temp;
  *P_Watchdog_Clear=1;
  delay++;
  slow++;
  if(slow==32)
  {
    ave++;
    slow=0;
    if(ave<65)
      temperature1+=tag4/40;
  }
  time_temp++;
  temp=*P_INT_Ctrl;
  if(temp==0x0010&&err>2)
  {
    reg++;
    if(reg>=999)
    {
      reg=0;
      *P_IOA_Data^=0x8100;
    }
    
    else if(reg<=change)
      *P_IOA_Data|=0x8100;  
    else 
      *P_IOA_Data&=0x7eff;       
  }
  else
    *P_IOA_Data&=0x7eff;
  
  if(time_temp==1020)
  {
    time_temp=0;
    second++;
  }
  *P_INT_Clear=0x0010;
  
}  

⌨️ 快捷键说明

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