数字温度控制器的设计.docx
《数字温度控制器的设计.docx》由会员分享,可在线阅读,更多相关《数字温度控制器的设计.docx(16页珍藏版)》请在冰豆网上搜索。
![数字温度控制器的设计.docx](https://file1.bdocx.com/fileroot1/2023-2/2/c6d0558c-8cf8-45b5-80b7-cc60961c239c/c6d0558c-8cf8-45b5-80b7-cc60961c239c1.gif)
数字温度控制器的设计
数字温度控制器的设计
王宁
1001应用电子
1、实验项目
数字温度控制器的设计
2、实验要求
用AT89C51单片机作为控制器,检测数字温度传感器DS18B20,并将检测到的温度信息和当前电机转动方向显示在1602LCD液晶显示模块上。
温度控制范围在20+学号尾数℃——35℃,占空比调整,每变化0.1℃时占空比调整学号尾数。
当温度在28℃-35℃之间时,第一行显示“XXX.X℃STOP”,第二行显示“TG!
H/L:
0%”,驱动直流电机的PWM波占空比为0,直流电机不转动;
当温度在高于35℃时,第一行显示“XXX.X℃CWD”,第二行显示“TH!
H/L:
XXX%”,直流电机顺时针转动,温度每上升0.1℃,驱动直流电机的PWM波占空比增加8%;
当温度在低于28℃时,第一行显示“XXX.X℃CCWD”,第二行显示“TL!
H/L:
XXX%”,直流电机逆时针转动,温度每下降0.1℃,驱动直流电机的PWM波占空比增加8%;
另:
显示增加班级、姓名、学号等信息
完成程序,生成hex文件,运行仿真
3、实验原理图
图1显示为:
第一行显示“温度STOP(电机工作状态)姓名首字母”
第二行显示“TG!
(温度状态)H/L:
0%(占空比)学号”
图1
图2温度传感器的连接方式,显示温度值;
图2
图3为电机接线图
图3
图4为电路原理总图
图4
4、程序设计
#include
//引脚定义
sbitRS=P2^0;//1602LCDRS
sbitRW=P2^1;//1602LCDRW
sbitE=P2^2;//1602LCDE
sbitMoto1=P2^3;//直流电机控制端
sbitMoto2=P2^4;//直流电机控制端
sbitDQ=P2^5;//DS18B20DQ
//宏定义
#defineucharunsignedchar
#defineuintunsignedint
#defineLcdDataP0
#defineCWDMoto1=1;Moto2=0
#defineCCWDMoto1=0;Moto2=1
#defineStopMoto1=1;Moto2=1
//全局变量定义
ucharHPulseNum;//高电平数(PWM波高电平持续长度)
ucharLPulseNum;//低电平数(PWM波低电平持续长度)
uintNumChange;
bitTempFlag;//正负温度标志:
温度为正Temp_Flag=0,否则为1
uintTemp;//温度值
ucharMotoStatus;//直流电机转向状态0CWD(顺时针方向)1CCWD(逆时针方向)
bitPulseStatus;//PWM波状态,0高电平1低电平
//函数申明
voidDelayms(uintxms);//ms级延时函数
voidWriteLcd(ucharDat,bitx);//写1602LCD指令、数据函数
voidInitLCD(void);//初始化1602LCD函数
voidStatusLCD(void);//1602LCD显示状态函数
voidInitT0(void);//初始化定时器T0函数
voidDelayus(ucharxus);//us级延时函数
bitInit_DS18B20(void);//初始化DS18B20函数
ucharRead_DS18B20(void);//读DS18B20函数
voidWrite_DS18B20(ucharDat);//写DS18B20函数
voidGetTemp();//取温度函数
voidMotoControl();
ucharFirstLine[16]={"CSTOPwn"};//用于1602LCD第一行显示的数组
ucharSecondLine[16]={"TG!
H/L:
0%28"};//用于1602LCD第二行显示的数组
voidDelayms(uintxms)//延时程序
{
uinti,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
voidWriteLcd(ucharDat,bitx)//写1602LCD指令、数据函数
{
E=0;
LcdData=Dat;
RS=x;//写指令时x=0,写数据时x=1
RW=0;
E=1;
Delayms
(1);
E=0;
}
voidInitLcd(void)//初始化1602LCD函数
{
WriteLcd(0x38,0);//功能设定(38H)
WriteLcd(0x0C,0);//显示开、关设定(0CH)
WriteLcd(0x06,0);//输入模式设定(06H)
WriteLcd(0x01,0);//清除显示(01H)
}
voidStatusLCD(void)//1602LCD显示状态函数
{
if(TempFlag)FirstLine[0]='-';//如果温度值为负,显示负符号
elseFirstLine[0]='';//否则不显示温度符号
if(Temp<1000)FirstLine[1]='';//如果温度值小于100,百位显示空白(不显示0)
elseFirstLine[1]=Temp/1000+0x30;//取温度百位并转换成ASCII码
if(Temp<100)FirstLine[2]='';//如果温度值小于10,十位显示空白(不显示0)
else
FirstLine[2]=Temp%1000/100+0x30;//取温度十位并转换成ASCII码
FirstLine[3]=Temp%100/10+0x30;//取温度个位并转换成ASCII码
FirstLine[4]='.';//显示小数点
FirstLine[5]=Temp%10+0x30;//取温度十分位并转换成ASCII码
FirstLine[6]=0xDF;//显示℃中C前面的小圆
if(NumChange!
=0)
{
if(MotoStatus==1)//顺时针时显示CWD
{
FirstLine[9]='';
FirstLine[10]='C';
FirstLine[11]='W';
FirstLine[12]='D';
}
if(MotoStatus==2)//逆时针时显示CCWD
{
FirstLine[9]='C';
FirstLine[10]='C';
FirstLine[11]='W';
FirstLine[12]='D';
}
}
else
{
FirstLine[9]='S';
FirstLine[10]='T';
FirstLine[11]='O';
FirstLine[12]='P';
}
if((TempFlag)|(Temp<280))//如果温度为负或小于25度,温度过低
SecondLine[1]='L';//改写1602LCD第二行显示内容
if((!
TempFlag)&(Temp>=280)&(Temp<=350))//如果温度为正且在25℃~30℃之间,温度正常
SecondLine[1]='G';//改写1602LCD第二行显示内容
if((!
TempFlag)&(Temp>350))//如果温度为正且大于30度,温度过高
SecondLine[1]='H';//改写1602LCD第二行显示内容
if(NumChange<100)//占空比小于100%时,不显示百位
SecondLine[8]='';
else
SecondLine[8]=NumChange/100+0x30;//取占空比百位并转换成ASCII码
if(NumChange<10)//占空比小于10%时,不显示十位
SecondLine[9]='';
else
SecondLine[9]=NumChange%100/10+0x30;//取占空比十位并转换成ASCII码
SecondLine[10]=NumChange%10+0x30;//取占空比个位并转换成ASCII码
}
voidDelayus(ucharxus)//晶振为12MHz,延时时间为2i+5us
{
while(--xus);
}
bitInit_DS18B20(void)//初始化DS18B20函数
{
bitx;
DQ=1;
DQ=0;
Delayus(250);
DQ=1;
Delayus(27);
if(!
DQ)x=0;
elsex=1;
Delayus(250);
DQ=1;
returnx;
}
ucharRead_DS18B20(void)//读DS18B20函数
{
uchari=0,Dat=0;
for(i=0;i<8;i++)
{
DQ=1;
DQ=0;
Dat>>=1;
DQ=1;
if(DQ)Dat|=0x80;
DQ=1;
Delayus(30);
}
returnDat;
}
voidWrite_DS18B20(ucharDat)//写DS18B20函数
{
uchari=0;
for(i=0;i<8;i++)//循环8次,写入一个字节
{
DQ=1;//未发送前的状态
Dat>>=1;//将要传送的最低位放入CY
DQ=0;//将总线拉低,产生写时序
DQ=CY;//将要传送的位状态送到总线上
Delayus(30);//延时50us,即保持总线状态,待DS18B20采样
DQ=1;//恢复期,总线置1
}
}
voidGetTemp(void)//获取温度函数
{
uchara=0,b=0;
TR0=0;
Init_DS18B20();
Write_DS18B20(0xcc);//跳过ROM
Write_DS18B20(0x44);//开启温度转换
Init_DS18B20();
Write_DS18B20(0xcc);//跳过ROM
Write_DS18B20(0xbe);//读暂存器
a=Read_DS18B20();//读取高速暂存字节0,温度低8位
b=Read_DS18B20();//读取高速暂存字节1,温度高8位
Temp=b;
Temp<<=8;
Temp=Temp|a;//将高、低位温度编码合在一起
if(b>=8)//判断温度值是否为负,如果温度高字节大于等于8说明温度值为负
{
Temp=~Temp+1;//将补码转换成原码
TempFlag=1;//温度标志为1,表示温度为负
}
else
{
TempFlag=0;//温度标志为0,表示温度为正
}
Temp=Temp*0.0625*10+0.5;//将温度编码转换成温度值放大10倍加0.5是为了四舍五入
TR0=1;
}
voidInitT0(void)//初始化外部中断INT0和定时器T0
{
EA=1;
ET0=1;
TMOD=0x02;//T0工作于定时、方式2
TH0=6;//250us定时
TL0=6;
TR0=1;//启动定时器
}
voidT0Serv()interrupt1//T0定时器中断服务函数
{
if(!
PulseStatus)//如果当前处于PWM波高电平段
{
if(HPulseNum--!
=0)//如果高电平段延时计数不为0
{
if(MotoStatus!
=0)//如果MotoStatus!
=0(为0是停止状态)
{
if(MotoStatus==1)
{
CWD;//顺时针驱动直流电机
}
else//MotoStatus=1
{
CCWD;//逆时针驱动直流电机
}
}
}
Else//高电平段延时计数为0
{
PulseStatus=!
PulseStatus;//取反PWM波电平状态
LPulseNum=100-NumChange;
}
}
Else//当前处于PWM波低电平段
{
if(LPulseNum--!
=0)
{
Stop;//停止驱动直流电机
}
else
{
PulseStatus=!
PulseStatus;//取反PWM波电平状态
HPulseNum=NumChange;
}
}
}
voidMotoControl()
{
if((!
TempFlag)&(Temp>350))
{
MotoStatus=1;
NumChange=(Temp-350)*8;
if(NumChange>=100)NumChange=100;//控制上限
}
if((!
TempFlag)&(Temp<=350)&(Temp>=280))
{
MotoStatus=0;
NumChange=0;
}
if((Temp<280)|(TempFlag))
{
MotoStatus=2;
NumChange=(280-Temp)*8;
if((NumChange>=100)|(TempFlag))NumChange=100;//控制上限
}
}
voidmain()
{
uchary;
InitLcd();//初始化1602LCD
HPulseNum=NumChange;//装载PWM波高电平段延时计数,为高电平段延时做准备
InitT0();//初始化外部中断INT0和定时器T0
while
(1)
{
GetTemp();
Delayms(500);//延时0.5s,降低温度读取频率
MotoControl();//根据当前工作状态改变1602LCD显示状态
StatusLCD();//指定送入的字符显示于1602LCD第一行第一个字符位置
WriteLcd(0x80,0);
for(y=0;y<16;y++)//循环送入
WriteLcd(FirstLine[y],1);//向1602LCD送第一行显示内容数组
WriteLcd(0xc0,0);
for(y=0;y<16;y++)//循环送入
WriteLcd(SecondLine[y],1);//向1602LCD送第二行显示内容数组
}
}
5、实验过程
利用keil软件编写程序,利用仿真软件绘制原理图,将生成的.hex文件装入原理图进行仿真运行
6、实验小结
注意占空比的调整,如何利用程序合理调整及分配电机运行的速度,2*16的LCD的显示及如何合理写入字符串与字符。
温度传感器的初始化和写、读的程序编写。