资源下载地址:https://download.csdn.net/download/sheziqiong/87879975
资源下载地址:https://download.csdn.net/download/sheziqiong/87879975
基于单片机的电阻炉温度控制系统选题背景及意义可以从以下几个方面来考虑:
工业生产的需求:电阻炉是一种常用的加热设备,广泛应用于各种工业生产中。而温度控制是电阻炉正常运行的关键,因此基于单片机的电阻炉温度控制系统可以提高生产效率和产品质量。
技术发展的趋势:随着科技的不断发展,单片机技术已经得到广泛应用。而基于单片机的电阻炉温度控制系统可以充分发挥单片机的优势,提高温度控制的精度和稳定性。
节能减排的要求:随着环保意识的不断提高,节能减排已成为各行各业的重要任务。而基于单片机的电阻炉温度控制系统可以通过精确控制温度,减少能源的浪费,降低对环境的影响。
综上所述,基于单片机的电阻炉温度控制系统具有重要的背景和意义,可以提高生产效率和产品质量,充分发挥单片机技术的优势,同时也符合节能减排的要求。
温度设定部分
设定部分主要是键盘输入,此部分主要由三个按键组成,PLAS为加,SUBS为减,START为开始。当系统启动时,默认设定温度为30℃,当按下PLAS时设置水温增加,按下SUBS时设置水温减小,当按下START时为开始加热。
此部分按键为常开按钮,当不触发时为断开状态,按键按下之后与地连接,故为低电平,单片机读取按键数据为低电平时有效。
仿真说明
由于单片机端口的驱动能力有限,所以令其低电平触发光电耦合器,故当P1.5口输出低电平时电热丝加热。
当设定温度与实际温度之差大于10℃时属于粗调,即令电热丝持续加热,无PWM控制;当设定温度与实际温度之差小于10℃时属于微调,即电热丝加热时受PWM控制。
仿真结果
对各温度仿真结果如下:
(1)实际温度19℃,设定温度30℃
当差值大于10℃时,输出为低电平,电热丝持续加热,如图5.1所示:
图1.1仿真图一
(2)实际温度21℃,设定温度30℃
当差值小于10℃,控制算法开始起作用,由低电平部分控制加热,如图5.2所示:
图1.2仿真图二
(3)实际温度24℃,设定温度30℃
当差值逐渐缩小,低电平时间减少,电热丝功率降低,如图5.3所示:
图1.3仿真图三
(4)实际温度28℃,设定温度30℃
当差值逐渐缩小,低电平时间减少,电热丝功率降低,如图5.4所示:
图1.4仿真图四
(5)实际温度32℃,设定温度30℃
当设定温度小于实际温度时,PWM输出高电平,电热丝不工作,如图5.5所示:
图1.5仿真图五
1.2结论
(1)当设定温度与实际温度之差小于10℃时,P1.5输出PWM方波控制电热丝加热功率,以达到精确调温的目的。
(2)当差值大于10℃时,电热丝持续加热,使其尽快进入到PWM调节阶段
(3)当设定温度小于实际温度,说明温度已超调,故电热丝不工作,使其降温。
//包含的头文件
#include<REG51.H>
#include<math.h>
#include<INTRINS.H>
#include<string.h>
//定义宏定义
#define CIRCLE 100
#define uchar unsigned char
#define uint unsigned int;
struct PID {
unsigned int SetPoint; // 设定目标 Desired Value
unsigned int Proportion; // 比例常数 Proportional Const
unsigned int Integral; // 积分常数 Integral Const
unsigned int Derivative; // 微分常数 Derivative Const
unsigned int LastError; // Error[-1]
unsigned int PrevError; // Error[-2]
unsigned int SumError; // Sums of Errors
};
struct PID spid; // PID Control Structure
unsigned int rout; // PID Response (Output)
unsigned int rin; // PID Feedback (Input)
typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef bit BOOL ;
sbit key1=P3^2; //定义按键位置
sbit key2=P3^3;
sbit key3=P3^4;
sbit rs = P1^0;
sbit rw = P1^1;
sbit ep = P1^2;
sbit pwm=P1^5; //PWM输出端设置为P1.5输出
sbit DQ=P1^3;//ds18b20 信号引脚即DQ
sfr dataled=0x80;//显示数据端口 即P2口为段选码输入口
uchar temp;//温度变量
unsigned char set_temper=30;
unsigned char high_time;
unsigned int s;
uchar flag_get,count,num,counter; //温度读取标志位、中断次数变量t0中断次数以读取温度值, t1中断次数以控制周期和PWM的占空比
char const table[]={
100,80,70,60,50,40,30,20,0};//高电平时间查表
uchar
code
tab[]={
0x28,0xEB,0x32,0xA2,0xE1,0xA4,0x24,0xEA,0x20,0xA0,0x60,0x25,0x3C,0x23,0x34,
0x74,0xF7,0xFF};//,0x88,0x83,0xC6,0xA1,0x86,0x8E};//共阳led显示段码115段码表
uchar shi,ge,danwei,dang,dang_dis; // 定义温度十位、个位、摄氏度单位、及档位变量名称,及显示档位的查表变量
void delay1(uchar MS);// 延时函数
unsigned char ReadTemperature(void);//读温度子函数
void Init_DS18B20(void);// DS18B20初始化
unsigned char ReadOneChar(void);//读字节子函数
void WriteOneChar(unsigned char dat);//写字节子函数
void delay(unsigned int i);//延时
//void del(unsigned int);
void drive_moto();//由P1低四位输出控制信号
void initial();
unsigned int TempBuffer[5];
BYTE code dis1[] = {
"Temperature:"};
BYTE code dis2[] = {
"Set_Temper:"};
BYTE code dis3[] = {
"0123456789"};
BYTE code dis4[] = 0xdf;
BYTE code dis5[] = {
"C"};
//定义函数
void delay2(BYTE ms)
{
BYTE i;
while(ms--)
{
for(i = 0; i< 250; i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
// 测试LCD忙碌状态
BOOL lcd_bz()
{
BOOL result;
rs = 0;
rw = 1;
ep = 1;
_nop_();
_nop_();
_nop_();
_nop_();
result = (BOOL)(P0 & 0x80);
ep = 0;
return result;
}
// 写入指令数据到LCD
void lcd_wcmd(BYTE cmd)
{
while(lcd_bz());
rs = 0;
rw = 0;
ep = 0;
_nop_();
_nop_();
P0 = cmd;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 1;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 0;
}
//设定显示位置
void lcd_pos(BYTE pos)
{
lcd_wcmd(pos | 0x80);
}
//写入字符显示数据到LCD
void lcd_wdat(BYTE dat)
{
while(lcd_bz());
rs = 1;
rw = 0;
ep = 0;
P0 = dat;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 1;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 0;
}
//LCD初始化设定
void lcd_init()
{
lcd_wcmd(0x38); //
delay2(1);
lcd_wcmd(0x0c); //
delay2(1);
lcd_wcmd(0x06); //
delay2(1);
lcd_wcmd(0x01); //清除LCD的显示内容
delay2(1);
}
//初始化相应的寄存器
void initial()
{
EA=1;
TMOD=0x11;//定时器设置皆工作在16定时计数器模式
TH0=0xef;//T0赋初值
TL0=0xf0;
TH1=(65536-1000)/256;//T1赋初值
TL1=(65536-1000)%256;
ET1=1;
ET0=1;
TR0=1;
TR1=1;
P2=0xff;
count=0;
counter=0;//pwm占空比控制变量
//IP=0x08; //T1优先级高于T0 ,后来证明此语句是多余的因为当加入此句后反/而PWM调速和温度检测都变得有点不稳定
}
//延时函数
void delay(unsigned int i)
{
while(i--);
}
//18b20初始化函数检测总线上是否有从属器件DS的存在若存在则通讯成功
void Init_DS18B20(void)
{
unsigned char x=0;
DQ = 1; //DQ复位
delay(8); //稍做延时
DQ = 0; //单片机将DQ拉低
delay(80); //延时 大于 480us
DQ = 1; //拉高总线
delay(10);
x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败因为DQ复位成功的回答信号即存在信号是低电平
delay(5);
}
//读一个字节ROM
unsigned char ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 给脉冲信号
dat>>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x80;//
delay(5);
}
return(dat);
}
//写一个字节
void WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
delay(5);
DQ = 1;
dat>>=1;
}
delay(5);
}
//读取温度
unsigned char ReadTemperature(void)
{
unsigned char a=0;
unsigned char b=0;
unsigned char t=0;
Init_DS18B20();// 复位
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
delay(100);
Init_DS18B20(); //每次操作前都要进行复位
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器等共可读9个寄存器 前两个就是温度
a=ReadOneChar();
b=ReadOneChar();
s=(unsigned int)(a&0x0f);
b<<=4;//取高字节的第四位因为高四位为符号位1111为负0000为正
b+=(a&0xf0)>>4;//忽略小数位取a的高四位与b的相加就是此时所测得到整数温度值
t=b;
return(t);//返回温度值给这个函数
}
//显示函数
void printf()
{
BYTE i;
delay2(10);
lcd_pos(0x00); // 设置显示位置为第一行的第5个字符
i = 0;
while(dis1[i] != '\0')
{
lcd_wdat(dis1[i]);
i++;
}
lcd_pos(0x40); // 设置显示位置为第二行第二个字符
i = 0;
while(dis2[i] != '\0')
{
lcd_wdat(dis2[i]); // 显示字符
i++;
}
TempBuffer[0]=temp/10; //十位
TempBuffer[1]=temp%10; //个位
lcd_pos(0x0c);
lcd_wdat(dis3[TempBuffer[0]]); //测试温度十位
lcd_pos(0x0d);
lcd_wdat(dis3[TempBuffer[1]]); //测试温度个位
lcd_pos(0x0e);
lcd_wdat(dis4[0]);
lcd_pos(0x0f);
lcd_wdat(dis5[0]);
TempBuffer[2]=set_temper/10; //十位
TempBuffer[3]=set_temper%10; //个位
lcd_pos(0x4c);
lcd_wdat(dis3[TempBuffer[2]]); //设置温度十位
lcd_pos(0x4d);
lcd_wdat(dis3[TempBuffer[3]]); //设置温度个位
lcd_pos(0x4e);
lcd_wdat(dis4[0]);
lcd_pos(0x4f);
lcd_wdat(dis5[0]);
}
//键盘输入函数
void keyscan()
{
if(key1==0)
{
delay(200);
if(key1==0)
{
set_temper++;
}
}
if(key2==0)
{
delay(200);
if(key2==0)
{
set_temper--;
}
}
// //开始按键
// if(key3==0)
// {
// delay(300);
// if(key3==0)
// {
// TR1=1;
// }
// }
}
//T1定时中断服务程序
void into(void) interrupt 3
{
TH1=(65536-1000)/256;//初值重装
TL1=(65536-1000)%256;
counter++;
if(counter>CIRCLE)
{
counter=0;限定周期为T=100X0.01ms=10ms
}
if(counter<=high_time)//取得查表参数以调节pwm的占空比
pwm=1;//PWM高电平
else
pwm=0;
}
//设定占空比函数
void compare_temper()
{
char shi=0,ge=0;
if(set_temper>temp)
{
//当设置温度与实际温度大于10度时
if(set_temper-temp>=10)
{
//进入死循环
while(1)
{
TR1=0; //关闭定时器 从而关闭PWM波
pwm=0; //输出低电平
temp=ReadTemperature(); //读取温度传感器的值
shi=temp/10; //分离出十位
ge=temp%10; //分离出个位
lcd_pos(0x0c); //设置显示位置
lcd_wdat(0x30+shi); //在指定位置显示十位
lcd_pos(0x0d); //设置显示位置
lcd_wdat(0x30+ge); //在指定位置显示各位
if(set_temper-temp<10) //如果温度差值低于10度
{
TR1=1; //打开定时器 开pwm波
break; //跳出循环
}
}
}
else
{
//打开定时器
TR1=1;
//根据差值调整PWM波
if (set_temper-temp==9)
high_time=10;
if (set_temper-temp==8)
high_time=20;
if (set_temper-temp==7)
high_time=30;
if (set_temper-temp==6)
high_time=40;
if (set_temper-temp==5)
high_time=50;
if (set_temper-temp==4)
high_time=60;
if (set_temper-temp==3)
high_time=70;
if (set_temper-temp==2)
high_time=80;
if (set_temper-temp==1)
high_time=90;
}
}
else if(set_temper<temp)
{
//关闭定时器
pwm=1;
TR1=0;
}
}
main()
{
initial();// 初始化个变量及定时器的初值开中断等
lcd_init(); // 初始化LCD
while(1)
{
//比较函数
compare_temper();
//输出函数
printf();
//读取温度函数
temp=ReadTemperature();
//键盘扫描函数
keyscan();
}
}
资源下载地址:https://download.csdn.net/download/sheziqiong/87879975
资源下载地址:https://download.csdn.net/download/sheziqiong/87879975