//摘要:溫度控制器系統(溫度顯示精確到0.1度)
//調溫調節范圍設定在35-65度
//共計5種模式:
//模式0:溫度實時值顯示(前1位數碼管顯示模式,后2位顯示實時溫度值,精確到0.1C
//模式1:目標溫度設定(35-65 度)
//模式2: PID 參數中的P參數調節模式(0.0-50.0)
//模式3: PID參數中的I參數調節模式(0.0-50.0)
//模式4: PID參數中的D參數調節模式(0.0-50.0)
//數碼管第一位顯示模式值,后三位顯示參數值
//按MODE鍵顯示對應模式,按UP,DOWN修改參數,按ENT鍵返回模式0即顯示實時溫度值
#include "STC12C5A60S2.h"
#include "table.h"
#define AD CHANNEL 0
#define uchar unsigned char
#define uint unsigned int
#define THCO 0xf8 //11.0592MHZ 晶振
#define TLCO 0xcb //定時 2ms時間常數值
unsigned char Data_Buffer[4]= {1,2,3,4};
uchar code
Duan[ 17]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71 ,0x76};
sbit P24=P2^4; //四 個數碼管的位碼口定義
sbit P25=P2^5;
sbit P26=P2^6;
sbit P27=P2^7;
sbit warm=P3^4;
sbit Mode_key=P2^0;
sbit UP_key=P2^1;
sbit DOWN_key=P2^2;
sbit ENT_key=P3^2;
void AD_init();
unsigned int AD_Sample(unsigned char channel);
void Buffer_fresh();
bit kuaisu=0; //按 鍵快速處理
unsigned char V_mode=0; //0-4
unsigned int canshu[5]= {0,450,110,50,10;//均放大10倍
//模式0:溫度實時值顯示(前1位數碼管顯示模式,后2位顯示實時溫度值,精確到0.1C
//模式1:目標溫度設定(35-65 度)
//模式2: PID參數中的P參數調節模式(0.0-50.0)
//模式3: PID參數中的I參數調節模式(0.0-50.0)
//模式4: PID參數中的D參數調節模式(0.0-50.0)
unsigned int maxcanshu[5]= {0,700,500,500,500};
unsigned int mincanshu[5]= {0,300,1,1,1};
bit ADflag=0;
bit PIDflag=0;
bit Disp_flag=0;
/*---------------------------------------------
溫度計算,放大10倍
---------------------------------------------*/
unsigned int ADtempreture(void)
{
unsigned int da=0,max,min,mid;
unsigned int V;
float t,t1j;
v=AD_ Sample(AD_ CHANNEL);
t=v;
t=v*4.83///4.883=5000/1024 ;
t1=t/1000; //t1為電壓值
t1=(5000-t)/t1;
v=(unsigned int)t1*10; // 計算得電阻值
da=v;
max=97; min=0;
while(1)//查表求出溫度值
{
mid=(max +min)/2;
if(Table[mid]<da) max-mid;
else min=mid;
if(max-min)<=1) break;
}
if(max-min)da-min* 10; //溫度值放大10倍
else
{
j=(Table[min]-Table[max])/10;
j=(Table[min]-da)j;
da=j;
da= 10*min+da;
}
return da;
}
unsigned char pid_val_mid=0;
void PIDcompute()
{
/*-------------------------------------------------
根據設定及采集值進行計算PID調節,計算出PID——VAL——MID 的值
--------------------------------------------------*/
static int SumError-0,PrevError-0,L astError-=0;
int dError-0,Error=0;
double j=0.0,i;
Error =canshu[1]-cansbu[0];
if(Error> 10){pid val mid-25s;returm;}
else if(Errort 10<0){pid _val mid-0;return;}
SumError +=Error;
dError- Error-LastError;
PrevError-LastError;
LastError-Error;
// j=canshu[2]*Error + canshu[3]*SumError + canshu[4]*dError; //放大100倍
i=canshu[2];
j=Error*i;
i=canshu[3];
j=j+SumError*i;
i=canshu[4];
j=j+dError*i;
if(j>0) j=j/10; //PID參數放大了10倍,所以要減小10倍
if(j> 255)pid _val mid= 255; //全幵
else ifj<0)pid val mid-0; //全關
else pid _val _mid=j; //計算值
}
/******************** ******/
void main(void) //主程序
{
bit x: -0,y=0;;
TMOD =0x11; //沒置定肘器0工作模式,16位汁數模式
TH0=THCO;
TL0=TLCO;
TR0=1; //啟動計時器
ET0=1; //使能定時器中斷
EA=l; //幵總中斷
CCON=0; //清標志
CL=0; //清計數器
CH=0;
CMOD=0x08; //PCA時鐘為SYSCLK
PCAPWM1=0X0;
CCAP1H=CCAP1L=0xff; //pwm0 output 50% duty cycle脈寬值越低輸出越大DA
CCAPM1=0X42; //PCA module-0 work in 8-bit PWM mode
CR= 1; //PCA timer start run
AD_init();
while(1)
{
if(Disp_ flag==1)
{ Disp_ flag=0;Bufer_ fresh0;}
if(ADflag==1)
{canshu[0]=ADtempreture0;ADflag =0;
if(V_ mode= -0)Disp_ flag=1;}
if(PIDflag==1)
{PIDflag=0;PIDcompute0;CCAP1H=CCAP1L= 255-pid_ val mid;}
if(Mode_ key== =1)x=0;
else if(x= =0)
{x=1;
V_mode++;Disp_ flag= l;
if(V_ mode>4)V_ mode=0;
}
if(ENT_ key==1)y=0; //按ENT鍵觀察實時溫度
else if(y==0)
{y=1;
Disp_ flag=l;
V_ mode=0;
}
if(canshu[0] > 500)||canshu[0]<350)
{
P3 = 0x00;
}
else
{
P3 = 0XFF;
}
}
}
void AD_ init();
{
P1M0=P1M0&(~(1<<AD_ CHANNEL)); //P10 設為AD轉換功以能
PIM1=P1M1|(1<<AD_ CHANNEL);
P1ASF=1<<AD_ CHANNEL; //通道選擇
AUXRI|=0x04;
ADC_ _CONTR=0x80; //打開A/D轉換器電源
}
unsigned int AD_ Sample(unsigned char channel)
{
unsigned int temp;
ADC_ CONTR=0x88|channel; //選擇AD當前通道,并啟動轉換
while((ADC_ CONTR&0x10)==0); //等待AD轉換結束
ADC_ _CONTR =0x80; //清除轉 換結束標志
temp (ADC_ RES&0x03)*256+ADC_ RESL;
return temp;
}
void timer0) interrupt 1 //定時 器中斷服務子程序
{
static unsigned int count=0,count1 =0,keytime =0; //軟計時變量定義
static unsigned char Bit=0; //靜態變量,退出程序后,值保留
TH0=THCO;
TL0=TLCO;
Bit++;
if(Bit>=4)Bit=0;
P2|=0xf0; //先關位碼
P0=Duan[Data_ _Buffer[Bit];
if(Bit== 2|Bit==0)P0|=0X80;
switch(Bit) //送位碼
{
case 0: P24=0;break;
case 1: P25=0;break;
case 2: P26=0;break;
case 3: P27=0;break;
}
count++;
if(count>=100) //200ms更新采集一次溫度,并做一次 PID
{
count=0;
ADflag=l;
}
count1++;
if(count1>=400) //800ms做一次PID
{
count1=0;
PIDflag=1;
}
if(UP_ key-=0|DOWN_ key==0)&&V_ mode!=0)
{
if(+ +keytime >30)
{
keytime=0;
if(UP_ key==0)
{canshu[V_ mode]++;if(canshu[V_ mode]>maxcanshu[V_ mode])canshu[V_ mode]- mincanshu[V_ mode];Disp_ flag=1;}
else if(DOWN_ key--0)
{if(canshu[V_ mode] =mincanshu[V_ mode])canshu[V_ mode]=maxcanshu[V mode],canshu[V_ mode]--;Disp_ flag=1;}
}
}
else (keytime=0;)}
}
void Buffer_ fresh()
{ Data_ Buffer[0]=V_ mode;
Data_ Buffer[ l]=canshu[V_ mode]/100%10;
Data Buffer[2]=canshu[V_ mode]/10%10;
Data_ Buffer[3]= canshu[V_ mode]%10;
}
|