|
|
针对电阻加热炉温控需求,本文设计了一套以AT89C51 单片机为核心的温度闭环控制系统。系统采K型热电偶搭配MAX6675转换芯片完成高温信号采集,依托芯片内置 12 位 ADC、冷端补偿及 SPI 通信功能,实现温度信号的数字化转换与稳定传输;使用 8 位共阳数码管实时展示温度数据与系统状态,通过独立按键完成目标温度、报警阈值、PID 参数的在线整定与工作模式切换。系统以数字 PID 算法作为核心控制策略,结合软件方式生成 PWM 波形,通过调节双向晶闸管导通占空比改变加热功率,进而实现电阻加热炉的恒温控制。同时电路增设声光报警模块,具备超温、传感器故障提示功能。经整体调试,该系统结构简单、成本低廉、抗干扰能力强、操作便捷,控温效果稳定,能够满足中小型电阻加热炉的温度控制要求,具备较强的实际应用价值。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
电路原理图如下:
程序流程图:
单片机K型热电偶电热炉源程序如下:- #include "reg51.h"
- #include "max6675.h"
- #define uchar unsigned char
- #define uint unsigned int
- sbit smg1=P2^0;//数码管
- sbit smg2=P2^1;
- sbit smg3=P2^2;
- sbit smg4=P2^3;
- sbit smg5=P2^4;
- sbit smg6=P2^5;
- sbit smg7=P2^6;
- sbit smg8=P2^7;
- sbit k1=P1^0;//按钮
- sbit k2=P1^1;
- sbit k3=P1^2;
- sbit k4=P1^3;
- sbit k5=P1^4;
- sbit k6=P1^5;
- sbit k7=P1^6;
- sbit beep=P3^7;//蜂鸣器
- sbit out=P3^6;//输出控制
- uchar time=0;//系统定时
- uint wendu=0;//温度
- uchar pwm=0;//占空比
- uchar mode=0;//模式
- uint set=800;//设置温度
- uint limit=1000;//报警温度
- uchar ii=0;
- //数码管编码
- uchar code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
- uchar P_dat=1,I_dat=1,D_dat=1;//PID参数
- uint pid_dat[]={0,0,0,0,0}; //临时数据
- //PID计算,返回占空比
- uchar PID(uint mub,uint dat)//调整目标+测量数据
- {
- uchar i=0;
- uint j=0,sum=0,k=0;
- //存储数据
- for(i=0;i<4;i++)
- pid_dat[i]=pid_dat[i+1];
- pid_dat[4]=dat;
- //P调节
- j=0;
- if(dat<mub)
- {
- j=j+(mub-dat)*P_dat;
- if(j>100)
- j=100;
- }
- else
- {
- k=(dat-mub)*P_dat;
- if(j>k)
- j=j-k;
- }
- //I调节
- sum=0;
- for(i=0;i<5;i++)
- sum+=pid_dat[i];
- sum=sum/5;
- if(sum>mub)//减小
- {
- k=(sum-mub)*I_dat;
- if(j>k)
- j=j-k;
- }
- else //增加
- {
- k=(mub-sum)*I_dat;
- j+=k;
- if(j>100)
- j=100;
- }
- //D调节
- if(dat>pid_dat[3])//减小
- {
- k=(dat-pid_dat[3])*D_dat;
- if(j>k)
- j=j-k;
- }
- else //增加
- {
- k=(pid_dat[3]-dat)*D_dat;
- j+=k;
- if(j>100)
- j=100;
- }
- return j;
- }
- //延时
- void delay(uint i)
- {
- while(i--)
- {
- if(ii<99)//占空比计时
- ii++;
- else
- ii=0;
- if(ii<pwm)//输出控制
- out=0;
- else
- out=1;
- }
- }
- //主函数
- void main()
- {
- uchar k=0;
- TMOD|=0X01;//初始化定时器
- TH0=0X3C;
- TL0=0XB0;
- ET0=1;//打开定时器0中断允许
- EA=1;//打开总中断
- TR0=1;//打开定时器
- while(1)
- {
- if(P1==0xff)
- k=0;
- //设置
- if(!k1 &&(k!=1))//设置切换
- {
- k=1;
- if(mode<5)
- mode++;
- else
- mode=0;
- }
- //设置调整温度
- if(mode==1)
- {
- if(!k2 &&(k!=2))//+1
- {
- k=2;
- if(set<9999)
- set++;
- }
- if(!k3 &&(k!=3))//-1
- {
- k=3;
- if(set>0)
- set--;
- }
- if(!k4 &&(k!=4))//+10
- {
- k=4;
- if(set<9999)
- set+=10;
- }
- if(!k5 &&(k!=5))//-10
- {
- k=5;
- if(set>10)
- set-=10;
- }
- if(!k6 &&(k!=6))//+100
- {
- k=6;
- if(set<9999)
- set+=100;
- }
- if(!k7 &&(k!=7))//-100
- {
- k=7;
- if(set>100)
- set-=100;
- }
- }
- //设置报警温度
- if(mode==2)
- {
- if(!k2 &&(k!=2))//+1
- {
- k=2;
- if(limit<9999)
- limit++;
- }
- if(!k3 &&(k!=3))//-1
- {
- k=3;
- if(limit>0)
- limit--;
- }
- if(!k4 &&(k!=4))//+10
- {
- k=4;
- if(limit<9999)
- limit+=10;
- }
- if(!k5 &&(k!=5))//-10
- {
- k=5;
- if(limit>10)
- limit-=10;
- }
- if(!k6 &&(k!=6))//+100
- {
- k=6;
- if(limit<9999)
- limit+=100;
- }
- if(!k7 &&(k!=7))//-100
- {
- k=7;
- if(limit>100)
- limit-=100;
- }
- }
- //设置P参数
- if(mode==3)
- {
- if(!k2 &&(k!=2))//+1
- {
- k=2;
- if(P_dat<99)
- P_dat++;
- }
- if(!k3 &&(k!=3))//-1
- {
- k=3;
- if(P_dat>0)
- P_dat--;
- }
- }
- //设置I参数
- if(mode==4)
- {
- if(!k2 &&(k!=2))//+1
- {
- k=2;
- if(I_dat<99)
- I_dat++;
- }
- if(!k3 &&(k!=3))//-1
- {
- k=3;
- if(I_dat>0)
- I_dat--;
- }
- }
- //设置D参数
- if(mode==5)
- {
- if(!k2 &&(k!=2))//+1
- {
- k=2;
- if(D_dat<99)
- D_dat++;
- }
- if(!k3 &&(k!=3))//-1
- {
- k=3;
- if(D_dat>0)
- D_dat--;
- }
- }
- //报警
- if(wendu>limit)
- beep=0;
- else
- beep=1;
- //显示
- if(mode==0)
- {
- P0=smgduan[wendu/1000]; smg5=0;delay(50);smg5=1;
- P0=smgduan[wendu%1000/100]; smg6=0;delay(50);smg6=1;
- P0=smgduan[wendu%100/10]; smg7=0;delay(50);smg7=1;
- P0=smgduan[wendu%10]; smg8=0;delay(50);smg8=1;
- }
- if(mode==1)
- {
- P0=smgduan[1]; smg1=0;delay(50);smg1=1;
- P0=smgduan[set/1000]; smg5=0;delay(50);smg5=1;
- P0=smgduan[set%1000/100]; smg6=0;delay(50);smg6=1;
- P0=smgduan[set%100/10]; smg7=0;delay(50);smg7=1;
- P0=smgduan[set%10]; smg8=0;delay(50);smg8=1;
- }
- if(mode==2)
- {
- P0=smgduan[2]; smg1=0;delay(50);smg1=1;
- P0=smgduan[limit/1000]; smg5=0;delay(50);smg5=1;
- P0=smgduan[limit%1000/100]; smg6=0;delay(50);smg6=1;
- P0=smgduan[limit%100/10]; smg7=0;delay(50);smg7=1;
- P0=smgduan[limit%10]; smg8=0;delay(50);smg8=1;
- }
- if(mode==3)
- {
- P0=smgduan[3]; smg1=0;delay(50);smg1=1;
- P0=smgduan[P_dat/10]; smg7=0;delay(50);smg7=1;
- P0=smgduan[P_dat%10]; smg8=0;delay(50);smg8=1;
- }
- if(mode==4)
- {
- P0=smgduan[4]; smg1=0;delay(50);smg1=1;
- P0=smgduan[I_dat/10]; smg7=0;delay(50);smg7=1;
- P0=smgduan[I_dat%10]; smg8=0;delay(50);smg8=1;
- }
- if(mode==5)
- {
- P0=smgduan[5]; smg1=0;delay(50);smg1=1;
- P0=smgduan[D_dat/10]; smg7=0;delay(50);smg7=1;
- P0=smgduan[D_dat%10]; smg8=0;delay(50);smg8=1;
- }
- }
- }
- //定时器0中断
- void Timer0() interrupt 1
- {
- unsigned long j;
- if(time<10)//0.5s
- time++;
- else
- {
- time=0;
- wendu=max_read();//测温
- j=wendu;
- j=j*100/138;
- wendu=j;
- pwm=PID(set,wendu);//PID计算
- }
- TH0=0X3C;
- TL0=0XB0;
- }
复制代码
|
|