#include "STC15Fxxxx.h"
#include "button.h"
#include "LCD1602.h"
#include<absacc.h>
#define uchar unsigned char
//#define OSC 18432000L
//#define BAUD 9600
//#define URMD 0
#define ADC_POWER 0x80
#define ADC_FLAG 0x10
#define ADC_START 0x08
#define ADC_SPEEDLL 0x00
#define ADC_SPEEDL 0x20
#define ADC_SPEEDH 0x40
#define ADC_SPEEDHH 0x60
#define TIMS 65236
#define uchar unsigned char
#define uint unsigned int
#define ADC_7 XBYTE[0x0600] //定义模数转换IO地址
#define DAC_1 XBYTE[0x0640]
//最小拍参数
sbit str = P1^7; //定义A/D启动信号
sbit DIN0 = P1^0; //声明同步信号
uint data time; //声明变量,用于定时
uchar data t0_h,t0_l; //用于存储定时器0的初值
int TK=100; //声明采样周期变量,//采样周期=TK*10ms
int TC; //TK的变量
float KK0=0.5435; //系数kk0
float KK1=-0.2000; //系数kk1
float KK2=0; //系数kk2
float KK3=0; //系数kk3
float PP1=0.7170; //系数pp1
float PP2=0; //系数pp2
float PP3=0; //系数pp3
char UK; //当前时刻的D/A输出
char EK; //当前时刻的偏差
char UK_1,UK_2,UK_3,EK_1,EK_2,EK_3;//前3次采样时刻的控制量和偏差
//标志位
bit flag=0;
unsigned int intr2;
unsigned char intr;
bit adc_flag;
uchar state=1; //初始最小拍控制状态
#define da_cs P15
#define led P17
bit key_flag;
float Err=0,D_Err=0;
float Last_Err=0,Prev_Err=0;
int limit=0;
float vol_set,vol_sample=0,temp_sample,dac=0;
int temp_set=60;
uchar key_table[]={0,0,0};
float uk0=0;
uint ad_data=0;
//bit adc_rd=0;
void timer_0() interrupt 1
{
if(++intr == 10) //1ms?′DDò?′?
{
intr = 0;
key_flag = 1; //10ms判键
}
if(++intr2 == 600) //1ms?′DDò?′?
{
//P47=!P47;
intr2 = 0;
adc_flag=1; //1s adc2é?ù??ê±ê±????
}
//display(temp_set,temp_sample);
}
void Timer0() interrupt 1 using 1
{
str = !str; //产生A/D启动信号
TH0 = t0_h; //重新装入初值
TL0 = t0_l;
}
void adc_int() interrupt 5
{
ADC_CONTR &=!ADC_FLAG;
//if (adc_rd==1){
ad_data=ADC_RES*4+ADC_RESL;
// } if (adc_rd==0) {adc_rd=1;}
}
float zuixiaopai( )
{
TMOD = 0x01;
time = 10; //定时10ms
t0_h = (65536-500*time)/256; //计算定时器0初值
t0_l = (65536-500*time)%256;
t0_l = t0_l+20; //修正因初值重装而引起的定时误差
TH0 = t0_h;
TL0 = t0_l;
IT1 = 1; //边沿触发中断
EX1 = 1; //开外部中断1
ET0 = 1; //开定时中断0
TR0 = 1; //启动定时器
TC = 1;
DAC_1= 0x80; //D/A清零
UK=UK_1=UK_2=UK_3=0;
EK=EK_1=EK_2=EK_3=0;
EA = 1;
return(UK); //开总中断
while(1);
}
void int1() interrupt 2 using 2
{ float i,j;
DIN0 = 1; //读取输入前,先输出高电平
if(DIN0) //判同步信号到否
{
UK=UK_1=UK_2=UK_3=0;
EK=EK_1=EK_2=EK_3=0;
DAC_1 =0x80; //D/A输出零
TC=1;
}
else
{
TC--; //判采样周期到否
if(TC==0)
{
EK = ADC_7-128; //采样当前的偏差值,并计算偏差的变化量
i=EK*KK0; //计算i=EK*KK0+EK_1*KK1+EK_2*KK2+EK_3*KK3)
i=i+EK_1*KK1;
i=i+EK_2*KK2;
i=i+EK_3*KK3;
j=UK_1*PP1; //计算j=UK_1*PP1+UK_2*PP2+UK_3*PP3
j=j+UK_2*PP2;
j=j+UK_3*PP3;
i=i-j; //i-j
if(i>0) //判控制量是否溢出,溢出赋极值
{
if(i>=127)
UK=127;
else
UK=(char)i;
}
else
{
if(i<-128)
UK=-128;
else
UK=(char)i;
}
DAC_1=UK+128; //D/A输出控制量
UK_3=UK_2; //控制量递推
UK_2=UK_1;
UK_1=UK;
EK_3=EK_2; //偏差递退
EK_2=EK_1;
EK_1=EK;
TC=TK; //采样周期变量恢复
}
}
}
void main()
{
unsigned char key_temp;
unsigned char ch=0; //AD2é?ùí¨μà
uchar i=0;
P3=0;
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x01;
P1M1 = 0x01;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
P6M0 = 0x00;
P6M1 = 0x00;
P7M0 = 0x00;
P7M1 = 0x00;
CLK_DIV=0x03;
lcd_init();
display_init();
led=1;
TL0=TIMS;
TH0=TIMS>>8;
AUXR&=0x3F;
AUXR1=0X08;
TMOD=0x00;
TR0 = 1;
ET0 = 1;
EA = 1;
EADC=1;
P1ASF=0xFF;
ADC_RES=0;
temp_sample=vol_sample*16+20; //设置换算温度初始值,对应0-5V,采样温度范围20-100°C
ADC_CONTR =ADC_POWER |ADC_SPEEDLL | ADC_START | ch;
//for(i=0;i<10000;i++);
//ADC_CONTR &=!ADC_FLAG;
da_cs=0; //D/A初始值
while(1)
{
if(key_flag) //10ms扫描键盘1次
{
key_flag = 0;
key_temp = read_key();
}
switch (state) //状态切换
{
case 1: //PID控制
if (adc_flag==1)
{
ADC_CONTR=ADC_POWER |ADC_SPEEDLL | ADC_START | ch;
// ad_data=0
adc_flag=0;
vol_set=(temp_set-20)/16.0; //温控设定范围20-100度,AD 0-5V
vol_sample=(float)(ad_data)*5/1024; //采样数字量0-1023换算成电压值0-5V
temp_sample=vol_sample*16+20; //换算成温度
Err = vol_set - vol_sample;
uk0 = zuixiaopai( ); //调用最小拍
dac+=(uk0/5*256*5/12);
limit=round(dac);
if(limit<0) limit=0;
if(limit>255) limit=255;
P3=limit;
}
display(temp_set,temp_sample);
if (key_temp==10) //设置键按下
{
state=2;
led=0; //设置指示灯亮
}
break;
case 2: //设置给定温度
if (key_temp>=0&&key_temp<=9) //数字键按下
{key_table[i++]=key_temp; //按位记录按键设定值
if (i==3) i=0;}
else if (key_temp==11)
{
led=1;
Err=0;
D_Err=0;
state=1;
break;
}
//led=0;
temp_set=key_table[0]*100+key_table[1]*10+key_table[2]; //组合成温度设定值
display(temp_set,temp_sample);
break;
}
}
}
|