#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define ulint unsigned long int
#define on 0
#define off 1
sbit key1=P2^0;
sbit key2=P2^1;
sbit key3=P2^2;
sbit beep=P2^3;
sbit out=P2^4;
sbit DS=P2^5;
sbit dula=P2^6;
sbit wela=P2^7;
uint temp,a,sztemp=40*10;
uchar szflag,xiansiflag,xiansi,pid_count=0,t1_count=0;
bit pid_flag;
typedef struct PIDValue
{
ulint Ek_32[3]; //差值保存,给定和反馈的差值
uint EkFlag_8[3]; //符号,1则对应的为负数,0为对应的为正数
uint KP_8;
uint KI_8;
uint KD_8;
uint UK_16; //上一时刻的控制电压
uint RK_16; //设定值
uint CK_16; //实际值
}PIDValue;
PIDValue PID;
uchar code table[]={
0x3f,0x06,0x5b,0x4f, //数码管编码 "0-F"
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,
0xbf,0x86,0xdb,0xcf, //数码管编码 "0.-9."
0xe6,0xed,0xfd,0x87,
0xff,0xef,
0x00,0x40 //显示"+",显示"-"
};
void delay(uchar i);
/*............................................
PID=uk+kp*[e(k)-e(k-1)]+ki*e(k)+kd*[e(k)-2e(k-1)+e(k-2)]
函数入口:RK(设定值),CK(实际值),KP,KI,KD
函数出口:PID.Uk_16
.............................................*/
beep_control()
{
if(a>=sztemp)
{
beep=on;
}
else
{
beep=off;
}
}
pid_control()
{
ulint temp[3]={0,0,0};
ulint postsum=0;
ulint negsum=0;
PID.RK_16=sztemp;
PID.CK_16=a;
PID.KP_8=30;
PID.KI_8=PID.KP_8*10/200;
PID.KD_8=PID.KP_8*150/10;
if( PID.RK_16 > PID.CK_16 ) //设定值大于实际值否?
{
if( PID.RK_16 - PID.CK_16 >100 ) //偏差大于10否?
{
PID.UK_16 = 100; //偏差大于10为上限幅值输出(全速加热)
}
else
{
temp[0] = PID.RK_16 - PID.CK_16; //偏差<=10,计算E(k)
PID.EkFlag_8[1]=0; //E(k)为正数
//数值移位
PID.Ek_32[2] = PID.Ek_32[1];
PID.Ek_32[1] = PID.Ek_32[0];
PID.Ek_32[0] = temp[0];
if( PID.Ek_32[0] >PID.Ek_32[1] ) //E(k)>E(k-1)否?
{
temp[0]=PID.Ek_32[0] - PID.Ek_32[1]; //E(k)>E(k-1)
PID.EkFlag_8[0]=0;
} //E(k)-E(k-1)为正数
else
{
temp[0]=PID.Ek_32[0] - PID.Ek_32[1]; //E(k)<E(k-1)
PID.EkFlag_8[0]=1;
} //E(k)-E(k-1)为负数
temp[2]=PID.Ek_32[1]*2 ; // 2E(k-1)
if( (PID.Ek_32[0]+ PID.Ek_32[2])>temp[2] ) //E(k-2)+E(k)>2E(k-1)否?
{
temp[2]=(PID.Ek_32[0]+ PID.Ek_32[2])-temp[2]; //E(k-2)+E(k)>2E(k-1)
PID.EkFlag_8[2]=0;
} //E(k-2)+E(k)-2E(k-1)为正数
else
{
temp[2]=temp[2]-(PID.Ek_32[0]+ PID.Ek_32[2]); //E(k-2)+E(k)<2E(k-1)
PID.EkFlag_8[2]=1;
} //E(k-2)+E(k)-2E(k-1)为负数
temp[0] = (ulint)PID.KP_8 * temp[0]; // KP*[E(k)-E(k-1)]
temp[1] = (ulint)PID.KI_8 * PID.Ek_32[0]; // KI*E(k)
temp[2] = (ulint)PID.KD_8 * temp[2]; // KD*[E(k-2)+E(k)-2E(k-1)]
//所有的正数项叠加,负数项叠加
////KP*[E(k)-E(k-1)]
if(PID.EkFlag_8[0]==0)
postsum += temp[0]; //正数和
else
negsum += temp[0]; //负数和
// KI*E(k)
if(PID.EkFlag_8[1]==0)
postsum += temp[1]; //正数和
else
_nop_(); //空操作,E(K)>0
//KD*[E(k-2)+E(k)-2E(k-1)]//
if(PID.EkFlag_8[2]==0)
postsum += temp[2]; //正数和
else
negsum += temp[2]; //负数和
///U(K)//
postsum += (ulint)PID.UK_16;
if(postsum > negsum ) // 是否控制量为正数
{
temp[0] = postsum - negsum;
if( temp[0] < 100 ) //小于上限幅值则为计算值输出
PID.UK_16 = (uint) temp[0];
else
PID.UK_16 = 100; //否则为上限幅值输出
}
else //控制量输出为负数,则输出0(下限幅值输出)
PID.UK_16 = 0;
}
}
else
{
PID.UK_16 = 0;
}
pid_flag=0;
}
/*pid_control()
{
if(sztemp-a>100)
{
PID.UK_16=100;
}
else
{
if(sztemp-a<=100&&sztemp-a>90)
{
PID.UK_16=90;
}
if(sztemp-a<=90&&sztemp-a>70)
{
PID.UK_16=75;
}
if(sztemp-a<=70&&sztemp-a>60)
{
PID.UK_16=60;
}
if(sztemp-a<=60&&sztemp-a>45)
{
PID.UK_16=50;
}
if(sztemp-a<=45&&sztemp-a>30)
{
PID.UK_16=30;
}
if(sztemp-a<=30&&sztemp-a>20)
{
PID.UK_16=25;
}
if(sztemp-a<=20&&sztemp-a>10)
{
PID.UK_16=20;
}
if(sztemp-a<=10&&sztemp-a>=0)
{
PID.UK_16=10;
}
if(a-sztemp>0)
{
PID.UK_16=0;
}
}
pid_flag=0;
}
*/
pwm_control()
{
if(PID.UK_16==0)
out=0;
else
{
out=1;
}
}
void delay(uchar i) //延时程序
{
int j,k;
for(j=i;j>0;j--)
for(k=125;k>0;k--);
}
/*************************
功能:ds18b02 所需的延时
入口:延时时间 count
出口:
************************/
void delay_DS(uint count) //delay
{
uint i;
while(count)
{
i=200;
while(i>0)
i--;
count--;
}
}
/*************************
功能:一位数码管显示
入口:数据:dat,位置:wei
出口:
************************/
display(uchar dat,uchar wei)
{
dula=0;
wela=0;
P0=~table[dat];
dula=1;
dula=0;
wela=0;
dula=0;
P0=(1<<wei);
wela=1;
wela=0;
delay(2);
P0=0x00;
wela=1;
wela=0;
}
void dsreset(void) //发送复位,初始化命令
{
uint i;
DS=0;
i=103;
while(i>0)i--;
DS=1;
i=4;
while(i>0)i--;
}
bit tmpreadbit(void) //读一位
{
uint i;
bit dat;
DS=0;
_nop_();
_nop_();
DS=1;
_nop_();
_nop_();
dat=DS;
i=16;
while(i>0)
i--;
return (dat);
}
uchar tmpread(void) //读一个字节
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tmpreadbit();
dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里
}
return(dat);
}
void tmpwritebyte(uchar dat) //写一个字节到 ds18b20
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) //写 1
{
DS=0;
_nop_();
_nop_();
_nop_();
_nop_();
DS=1;
i=16;while(i>0)i--;
}
else
{
DS=0; //写 0
i=16;while(i>0)i--;
DS=1;
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
void tmpchange(void) //DS18B20 开始转换
{
dsreset();
delay(1);
tmpwritebyte(0xcc); // 跳过rom
tmpwritebyte(0x44); // 转换
}
uint tmp() //读温度
{
float tt;
uchar a,b;
dsreset();
delay_DS(1);
tmpwritebyte(0xcc);
tmpwritebyte(0xbe);
a=tmpread();
b=tmpread();
temp=b;
temp<<=8; //两个字节的温度读取
temp=temp|a;
tt=temp*0.0625;
temp=tt*10+0.5;
return temp;
}
display_all()
{
if(xiansiflag==0)
{
if(a>=100)
{
display(a/1000,0);
display(a/100%10,1);
display(a/10%10+16,2);
display(a%10,3);
}
else
{
display(a/100,0);
display(a/10%10+16,1);
display(a%10,2);
display(a%1,3);
}
}
else if(xiansiflag==1)
{
if(
Automatic-heating-control-system.rar_加热控制
版权申诉
103 浏览量
2022-09-20
18:28:12
上传
评论
收藏 110KB RAR 举报
朱moyimi
- 粉丝: 65
- 资源: 1万+
最新资源
- 3层独栋别墅图纸编号D055-三层-26.00&20.50米- 施工图.dwg
- 三层别墅图纸编号D054-三层-17.70&15.00米-施工图.DWG
- 三层别墅图纸编号D053-三层-16.59&19.58米-施工图.dwg
- 三层别墅图纸编号D052-三层-13.40&17.77米- 施工图.dwg
- 某日温度曲线以及日负荷曲线数据
- 全新STC12C5A60S2单片机+LCD19264大屏万年历农历生肖节气节日显示+闹钟+温湿度+台灯.rar
- 流水灯(库函数)三个灯依次亮灭
- 3层独栋别墅图纸编号D051-三层-10.14&17.04米- 施工图.dwg
- 常用的MIME TYPE类型枚举类Enum整理 静态方法直接检索使用
- Python网络爬虫实际例子代码
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈