新手入门
- 积分
- 25
- 金钱
- 25
- 注册时间
- 2014-5-21
- 在线时间
- 0 小时
|
5金钱
#include <reg52.h>
#include<intrins.h>
#include<string.h>
#include <stdio.h>
#include <math.h>
#define uchar unsigned char
#define uint unsigned int//位定义
//max6675
sbit SO=P1^0;
sbit SCK=P1^1;
sbit CS=P1^2;
//按键
sbit key1=P3^4; //功能键
sbit key2=P3^5; //+
sbit key3=P3^7; //-
sbit BEEP=P2^3; //蜂鸣器
//DAC0832
sbit CSDA=P3^2;
sbit wr=P3^6;
int shang=1250; //上限报警温度,默认值为1250
int SetPoint=1200; //设定目标
int wendu,k1;
uchar qian=0,bai=0,shi=0,ge=0,xiao=0;
float Kp,Ki,Kd;
uchar tab1[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//共阴极数码管赋值 0,1,2,3,4,5,6,7,8,9
uchar code tab[]={0x7e,0x7d,0x7b,0x77};//数码管位选
sbit dula=P2^6; //数码管段选,锁存器控制信号
sbit wela=P2^7;//数码管位选,锁存器控制信号
uint Re_Convert(); //热电偶数据读取,返回温度
int ek=0;
int ek1=0; //第K-1采样时的偏差值,Error[-1]
int ek2=0; //第K-2采样时的偏差值,Error[-2]
float LastOutput=0; //上次PID输出
float Output=0; //PID的输出
uchar high_time,low_time,count=0;//占空比调节参数
//---------------------------延时子程序---------------------------//
void delay_50ms(uint m)
{
uchar x,y;
for(x=m;x>0;x--)
for(y=50;y>0;y--) ;
}
/*********** MAX6675函数***********/
uint Re_Convert() //热电偶数据读取,返回温度
{
uchar i;
unsigned long Temp_2;
Temp_2=0;
CS=1; //片选段
SCK=0; //sck串行时钟输入
delay_50ms(5);
CS=0; //片选段,低电平选通
for(i=0;i<16;i++)//16位数据读取
{
Temp_2=Temp_2<<1;//向左移一位
SCK=1;// 上升
if(SO==1) //so串行数据输出
{
Temp_2=Temp_2|0x01;
}
else Temp_2=Temp_2|0x00;
SCK=0;
}
Temp_2=Temp_2<<1; //向左移一位,取0-14位
Temp_2=Temp_2>>4; //向右移4位,取3-14位
Temp_2=Temp_2*1024/4096;//变换为温度值,后边Temp_2是你采集到的数据,temp是转换成实际温度的数据,可以直接送到显示部分显示,精度0.25
return Temp_2;
}
//*************温度显示程序*******************//
void Disp_temp1(uint temp)//温度显示
{
ge=temp%10; //取个数位数字
temp=temp/10;
shi=temp%10;//取十位数字
temp=temp/10;
bai=temp%10;//取百位数字
qian=temp/10;//取千位数字
 0=0Xff;//关掉数码管的位选信号。阻止数码管受到P0口信号的影响。
delay_50ms(10);
wela=1;
delay_50ms(10);
wela=0;
dula=0;
 0=tab1[qian]; //送数字到段码端口,显示数字
dula=1; // 高电平,打开段选锁存器
dula=0; //低电平,锁存段选
wela=0;
 0=tab[0]; //数码管位选
wela=1; //打开位选选存器
wela=0; //锁存位选
delay_50ms(10);
P0=0Xff;//关掉数码管的位选信号。阻止数码管受到P0口信号的影响。
delay_50ms(10);
wela=1;
delay_50ms(10);
wela=0;
dula=0;
P0=tab1[bai];//送数字到段码端口
dula=1;
dula=0;
wela=0;
P0=tab[1]; //数码管位选
wela=1;
wela=0;
delay_50ms(10);
P0=0Xff;//关掉数码管的位选信号。阻止数码管受到P0口信号的影响。
delay_50ms(10);
wela=1;
delay_50ms(10);
wela=0;
dula=0;
P0=tab1[shi]; //送数字到段码端口
dula=1;
dula=0;
wela=0;
P0=tab[2]; //数码管位选
wela=1;
wela=0;
delay_50ms(10);
 0=0Xff;//关掉数码管的位选信号。阻止数码管受到P0口信号的影响。
delay_50ms(10);
wela=1;
delay_50ms(10);
wela=0;
dula=0;
 0=tab1[ge]; //送数字到段码端口
dula=1;
dula=0;
wela=0;
 0=tab[3]; //数码管位选
wela=1;
wela=0;
delay_50ms(10);
}
//*************PID显示程序*******************//
void Disp_temp2(float t)//PID显示
{
uchar temp=t*10;
xiao=temp%10; //取小数位数字
temp=temp/10;
ge=temp%10; //取个数位数字
temp=temp/10;
shi=temp%10;//取十位数字
temp=temp/10;
bai=temp%10;//取百位数字
P0=0Xff;//关掉数码管的位选信号。阻止数码管受到P0口信号的影响。
delay_50ms(10);
wela=1;
delay_50ms(10);
wela=0;
dula=0;
 0=tab1[bai];//送数字到段码端口
dula=1;
dula=0;
wela=0;
 0=tab[0]; //数码管位选
wela=1;
wela=0;
delay_50ms(10);
 0=0Xff;//关掉数码管的位选信号。阻止数码管受到P0口信号的影响。
delay_50ms(10);
wela=1;
delay_50ms(10);
wela=0;
dula=0;
P0=tab1[shi]; //送数字到段码端口
dula=1;
dula=0;
wela=0;
 0=tab[1]; //数码管位选
wela=1;
wela=0;
delay_50ms(10);
P0=0Xff;//关掉数码管的位选信号。阻止数码管受到P0口信号的影响。
delay_50ms(10);
wela=1;
delay_50ms(10);
wela=0;
dula=0;
P0=tab1[ge]|0x80; //送数字到段码端口
dula=1;
dula=0;
wela=0;
P0=tab[2]; //数码管位选
wela=1;
wela=0;
delay_50ms(10);
P0=0Xff;//关掉数码管的位选信号。阻止数码管受到P0口信号的影响。
delay_50ms(10);
wela=1;
delay_50ms(10);
wela=0;
dula=0;
P0=tab1[xiao]; //送数字到段码端口
dula=1;
dula=0;
wela=0;
P0=tab[3]; //数码管位选
wela=1;
wela=0;
delay_50ms(10);
P0=0Xff;//关掉数码管的位选信号。阻止数码管受到P0口信号的影响。
delay_50ms(10);
wela=1;
delay_50ms(10);
wela=0;
dula=0;
}
//*************PID运算程序*******************//
PID()
{
float P,D,iIncpid;
ek=SetPoint-wendu;
if(ek<=2)
{
iIncpid=0;
}
P=ek-ek1; //增量计算
D=ek-2*ek1+ek2;
if(ek<=5) //判断积分分离
iIncpid=Kp*P+Ki*ek+Kd*D;
else
{iIncpid=Kp*P+Kd*D;} //积分分离,去掉积分
Output=LastOutput+iIncpid;
if(Output>=1300)
Output=1300;
if(Output<=0)
Output=0;
ek2=ek1; //存储误差,用于下次计算
ek1=ek;
LastOutput=Output;
return (Output);
}
//*************报警子程序*******************//
void Alarm()//蜂鸣器间断
{ if(wendu>shang)
{
int f;
for(f=100;f>0;f--)
{ BEEP=0;
delay_50ms(10);
}
}
}
void compare_temper()
{
uint temper=wendu;
if(SetPoint>temper) //是否设置的温度大于实际温度
{
if(SetPoint-temper>100) //设置的温度比实际的温度是否是大于100度
{
high_time=100; //如果是,则全速加热
low_time=0;
}
else //如果是在100度范围内,则运行PID计算
{
PID();
if (high_time<=100)
high_time=(uchar)(Output/4); //?
else
high_time=100;
low_time= (100-high_time);
}
}
else if(SetPoint<=temper)
{
high_time=0;
low_time=100;
}
}
//
// void serve_T0() interrupt 1
//{
//TH0=(65536-50000)/256; //初值
//TL0=(65536-50000)%256;
//
//if(++count<=(high_time))
//Output=1;
//else if(count<=100)
//{
//Output=0;
//}
//else
//count=0;
//TH0=0xf0;
//TL0=0x60;
//}
//*******功率放大子程序*******//
void timer0() interrupt 1
{
int a;
CSDA=0;
WR=0;
P0=0Xc0; //输出正脉冲
TR0=0; //关T0记数
for(a=100;a>0;a--); //脉冲宽度由延时确定
P0=0X00;
}
void int0() interrupt 0 //外部中断
{
TH0=0X30; //T0初值确定晶闸管导通角
TL0=0X31;
TR0=1; //允许T0记数
}
//*******按键子程序*******//
void keyset()
{
k1++;
Disp_temp2(Kp);
delay_50ms(50);
while(k1<7)
{
if(k1==1)
{
Disp_temp2(Kp);
if(key1==0)
delay_50ms(10);
if(key1==0)
{k1++;
Disp_temp2(Kp);
delay_50ms(1);
while(!key1);
}
if(key2==0)
delay_50ms(10);
if(key2==0)
{
Kp=Kp+0.1;
Disp_temp2(Kp);
delay_50ms(1);
while(!key2);
}
if(key3==0)
delay_50ms(10);
if(key3==0)
{
Kp=Kp-0.1;
Disp_temp2(Kp);
delay_50ms(1);
while(!key3);
}
}
if(k1==2)
{
Disp_temp2(Kp);
if(key1==0)
delay_50ms(10);
if(key1==0)
{k1++;
Disp_temp2(Kp);
delay_50ms(1);
while(!key1);
}
if(key2==0)
delay_50ms(10);
if(key2==0)
{
Kp=Kp+0.1;
Disp_temp2(Kp);
delay_50ms(1);
while(!key2);
}
if(key3==0)
delay_50ms(10);
if(key3==0)
{
Kp=Kp-0.1;
Disp_temp2(Kp);
delay_50ms(1);
while(!key3);
}
}
if(k1==3)
{
Disp_temp2(Ki);
if(key1==0)
delay_50ms(10);
if(key1==0)
{k1++;
Disp_temp2(Ki);
delay_50ms(1);
while(!key1);
}
if(key2==0)
delay_50ms(10);
if(key2==0)
{
Ki=Ki+0.1;
Disp_temp2(Ki);
delay_50ms(1);
while(!key2);
}
if(key3==0)
delay_50ms(10);
if(key3==0)
{
Ki=Ki-0.1;
Disp_temp2(Ki);
delay_50ms(1);
while(!key3);
}
}
if(k1==4)
{
Disp_temp2(Kd);
if(key1==0)
delay_50ms(10);
if(key1==0)
{k1++;
Disp_temp2(Kd);
delay_50ms(6);
while(!key1);
}
if(key2==0)
delay_50ms(10);
if(key2==0)
{
Kd=Kd+0.1;
Disp_temp2(Kd);
delay_50ms(1);
while(!key2);
}
if(key3==0)
delay_50ms(10);
if(key3==0)
{
Kd=Kd-0.1;
Disp_temp2(Kd);
delay_50ms(1);
while(!key3);
}
}
if(k1==5)
{
Disp_temp2(Output);
if(key1==0)
{k1++;
Disp_temp2(Output);
delay_50ms(6);
while(!key1);
}
}
if(k1==6)
{
Disp_temp1(shang);
if(key1==0)
delay_50ms(10);
if(key1==0)
{k1++;
Disp_temp1(shang);
delay_50ms(6);
while(!key1);
}
if(key2==0)
delay_50ms(10);
if(key2==0)
{
shang=shang+10;
Disp_temp1(shang);
delay_50ms(1);
while(!key2);
}
if(key3==0)
delay_50ms(10);
if(key3==0)
{
shang=shang-10;
Disp_temp1(shang);
delay_50ms(10);
while(!key3);
}
}
}
delay_50ms(1);
if(k1>6)
k1=0;
}
void init_sys() //系统初始化
{
IT0=1;
EX0=1;
ET0=1;
EA=1;
TMOD=1;
CSDA=0;
wr=0;
P0=0Xc0;
}
//*************主程序*******************//
void main()
{
Kp=1.2;
Ki=3.4;
Kd=5.6;
init_sys();
delay_50ms(1);
while(1)
{
wendu=Re_Convert();// 热电偶数据读取,返回温度
compare_temper();
Disp_temp1(wendu);
if(key1==0)
{
keyset();
}
PID();
Alarm();
}
}
|
|