单片机应用系统设计说明书.docx
《单片机应用系统设计说明书.docx》由会员分享,可在线阅读,更多相关《单片机应用系统设计说明书.docx(30页珍藏版)》请在冰豆网上搜索。
单片机应用系统设计说明书
单片机应用系统设计说明书
设计题目:
温度控制系统设计
设计者姓名:
李键学号:
123122334禹鑫学号:
123122333
自动化学院
2013年6月1日
一、系统设计小组工作分工
序号
成员
工作分工
1
禹鑫
LCD1602显示
2
李键
18b20温度检测
3
二.系统设计目标
我的设计是基于STC98C52系列单片机的温度控制系统,以DS18B20作为温度检测元件,实时监测温度;以LCD1602显示实时温度、预设温度以及PID调节参数的设定。
三.系统方案设计
1.单片机选型
STC89C52RC单片机是宏晶科技推出的新一代高速/低功耗/超强抗干扰的单片机,指令代码完全兼容传统8051单片机,12时钟/机器周期和6时钟/机器周期可以任意选择。
单片机主要特性如下:
1.增强型8051单片机,6时钟/机器周期和12时钟/机器周期可以任意选择,指令代码完全兼容传统8051.
2.工作电压:
5.5V~3.3V(5V单片机)/3.8V~2.0V(3V单片机)
3.工作频率范围:
0~40MHz,相当于普通8051的0~80MHz,实际工作频率可达48MHz
4.用户应用程序空间为8K字节
5.片上集成512字节RAM
6.通用I/O口(32个)复位后为:
,P1/P2/P3/P4是准双向口/弱上拉,P0口是漏极开路输出,作为总线扩展用时,不用加上拉电阻,作为I/O口用时,需加上拉电阻。
7.ISP(在系统可编程)/IAP(在应用可编程),无需专用编程器,无需专用仿真器,可通过串口(RxD/P3.0,TxD/P3.1)直接下载用户程序,数秒即可完成一片
8.具有EEPROM功能
9.具有看门狗功能
10.共3个16位定时器/计数器。
即定时器T0、T1、T2
11.外部中断4路,下降沿中断或低电平触发电路,PowerDown模式可由外部中断低电平触发中断方式唤醒
12.通用异步串行口(UART),还可用定时器软件实现多个UART
13.工作温度范围:
-40~+85℃(工业级)/0~75℃(商业级)
P0端口(P0.0~P0.7P0.7,39~32引脚):
P0口是一个漏极开路的8位双向I/O口。
作为输出端口,每个引脚能驱动8个TTL负载,对端口P0写入每个引脚能驱动写入“1”时,可以作为高阻抗输入。
在访问外部程序和数据存储器时在访问外部程序和数据存储器时,P0口也可以提供低8位地址和8位数据的复用总线位数据的复用总线。
此时,P0口内部上拉电阻有效。
在FlashROM编在程时,P0端口接收指令字节端口接收指令字节;而在校验程序时,则输出指令字节则输出指令字节。
验证时,要求外接上拉电阻。
P1端口(P1.0~P1.7,1~8引脚):
P1口是一个带内部上拉电阻的8位双向I/O口。
P1的输出缓冲器可驱动(吸收或者输出电流方式)4个TTL输入。
对端口写入1时,通过内部的上拉电阻把端口拉到高电位,这是可用作输入口。
P1口作输入口使用时,因为有内部上拉电阻,那些被外部拉低的引脚会输出一个电流。
P2端口(P2.0~P2.7,21~28引脚):
P2口是一个带内部上拉电阻的8位双向I/O端口。
P2的输出缓冲器可以驱动(吸收或输出电流方式)4个TTL输入。
对端口写入1时,通过内部的上拉电阻把端口拉到高电平,这时可用作输入口。
P2作为输入口使用时,因为有内部的上拉电阻,那些被外部信号拉低的引脚会输出一个电流(I)。
P3端口(P3.0~P3.7,10~17引脚):
P3是一个带内部上拉电阻的8位双向I/O端口。
P3的输出缓冲器可驱动(吸收或输出电流方式)4个TTL输入。
对端口写入1时,通过内部的上拉电阻把端口拉到高电位,这时可用作输入口。
P3做输入口使用时,因为有内部的上拉电阻,那些被外部信号拉低的引脚会输入一个电流。
RST(9引脚):
复位输入。
当输入连续两个机器周期以上高电平时为有效,用来完成单片机单片机的复位初始化操作。
看门狗计时完成后,RST引脚输出96个晶振周期的高电平。
特殊寄存器AUXR(地址8EH)上的DISRTO位可以使此功能无效。
DISRTO默认状态下,复位高电平有效。
ALE/ROG(30引脚)地址锁存控制信号:
(ALE)是访问外部程序存储器时,锁存低8B位地址的输出脉冲。
在Flash编程时,此引脚(ROG)也用作编程输入脉冲。
2.温度传感器
DS18B20单线数字温度传感器。
提供计9位(二进制)温度读数,指示器件温度。
信息经过单线接口送入DS18B20送出,因此从主机CPU到DS18B20仅需一条线(和地线)。
DS18B20的电源可以有数据本身提供而不需要外部电源。
以为每一个DS18B20在出厂时已经给定了唯一的序号,因此任意多个DS18B20可以放在同一条单线总线上。
这允许在许多不同的地方放置温度敏感器件DSl820的测量范围从-55到+125增量值为0.5可在ls(典型值)内把温度变换成数字。
DSl8B20中还有用于贮存测得的温度值的两个8位存贮器RAM编号为0号和1号。
1号存贮器存放温度值的符号,如果温度为负(℃),则1号存贮器8位全为1,否则全为0。
0号存贮器用于存放温度值的补码,LSB(最低位)的“1”表示0.5℃将存贮器中的二进制数求补再转换成十进制数并除以2就得到被测温度值(-55—125)。
每只DS18B20都可以设置成两种供电方式,即数据总线供电方式和外部供电方式。
采取数据总线供电方式可以节省一根导线,但完成温度测量的时间较长;采取外部供电方式则多用一根导线,但测量速度较快。
3.液晶显示
1602液晶,它是一种专门用来显示字母、数字、符号等的点阵型液晶模块。
它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此所以它不能很好地显示图形(用自定义CGRAM,显示效果也不好)。
1602LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。
管脚功能:
第1脚:
VSS为电源地
第2脚:
VCC接5V电源正极
第3脚:
V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)。
第4脚:
RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。
第5脚:
RW为读写信号线,高电平
(1)时进行读操作,低电平(0)时进行写操作。
第6脚:
E(或EN)端为使能(enable)端,高电平
(1)时读取信息,负跳变时执行指令。
第7~14脚:
D0~D7为8位双向数据端。
第15脚背光正极。
第16脚背光负极。
四.硬件电路设计及描述
五.软件设计及描述
1.主程序流程图:
单片机上电,LCD1602液晶初始化,定时器T0、T1初始化,之后进入循环函数,键盘扫描;读取温度;送去LCD1602显示。
定时器T02秒终端一次,调用PID程序,即每两秒进行一次PID运算。
定时器T1为PWM波形生成函数。
2、源程序代码
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitDQ=P2^3;//ds18b20与单片机连接口
sbitRS=P2^5;//1602
sbitRW=P2^6;//1602
sbitEN=P2^7;//1602
sbitout=P1^7;
unsignedcharcodestr1[]={"T."};
unsignedcharcodestr2[]={"t."};
unsignedcharcodestr3[]={"P.I.D."};
chardatadisdata[5];
uinttvalue;//温度值k为return返回值
uchark,flag;
uinta;//atimer1定时时间参数
uchartflag;//温度正负标志
ucharsetflag;//模式标志
ucharflagdat;
charnum,bai,shi,ge,xiaoshu,Kp_ge,Kp_xiao,Ki_ge,Ki_xiao,Kd_ge,Kd_xiao;
sbitsetkey=P3^2;//模式键1
sbitup_key=P3^3;//加键
sbitdown_key=P3^4;//减键
ucharcount,EkFlag[3];//输出时间单位计数器
uintEk[3],RK,CK,Uk,KP,KI,KD;//RK设定值;CK实际值;Uk输出电压
/**********函数声明************/
voidPIDOutput();
voidPIDOperation();
/*********************PID调节程序**********************/
voiddelay1ms(ucharms)//延时1毫秒(不够精确的)
{
uchari,j;
for(i=0;ifor(j=0;j<100;j++);
}
voidPIDOperation()
{
ucharTemp[3];
KP=Kp_ge+0.1*Kp_xiao;
KI=Ki_ge+0.1*Ki_xiao;
KD=Kd_ge+0.1*Kd_xiao;
RK=1000*bai+100*shi+10*ge+xiaoshu;
CK=tvalue;
if(RK>CK)//设定值大于实际值否?
{
if(RK-CK>100)//偏差大于10否?
{
Uk=100;
}//偏差大于10为上限幅值输出(全速加热)
else
{
Temp[0]=RK-CK;//偏差<=10,计算E(k)
Ek[2]=Ek[1];
Ek[1]=Ek[0];
Ek[0]=Temp[0];
Uk=KP*Ek[0]-KI*Ek[1]+KD*Ek[2];
}
}
elseUk=0;
}
voidPIDOutput(void)
{
staticchari;
i=Uk;
if(i==100)
{
ET1=0;
TR1=0;
out=1;
}
if(i==0)
{
ET1=0;
TR1=0;
out=0;
}
if((i<100)&&(i>0))//如定时中断为40MS,40MS*5=0.2S(输出时间单位),加热周期20S(100等份)
{//每20SPID运算一次
ET1=1;
TR1=1;
a=655*i+3*i/10;
}
}
/*************************lcd1602程序**************************/
voidwr_com(unsignedcharcom)//写指令//
{
delay1ms
(1);
RS=0;
RW=0;
EN=0;
P0=com;
delay1ms
(1);
EN=1;
delay1ms
(1);
EN=0;
}
voidwr_dat(unsignedchardat)//写数据//
{
delay1ms
(1);;
RS=1;
RW=0;
EN=0;
P0=dat;
delay1ms
(1);
EN=1;
delay1ms
(1);
EN=0;
}
voidlcd_init()//初始化设置//
{
delay1ms(15);
wr_com(0x38);
delay1ms(5);
wr_com(0x08);
delay1ms(5);
wr_com(0x01);
delay1ms(5);
wr_com(0x06);
delay1ms(5);
wr_com(0x0c);
delay1ms(5);
}
voiddisplay(unsignedchar*p)//显示//
{
while(*p!
='\0')
{
wr_dat(*p);
p++;
delay1ms
(1);
}
}
init_play()//初始化显示
{
lcd_init();
wr_com(0x80);
display(str1);
wr_com(0x88);
display(str2);
wr_com(0xc0);
display(str3);
num=0;
bai=0;
shi=0;
ge=0;
xiaoshu=0;
return(k);
}
/*******************************温度按键程序**********************************/
voidkey()
{
if(setkey==0)
{
delay1ms(100);
if(setkey==0)
{
setflag++;
if(setflag==12)setflag=0;
}
while(setkey==0);
}
if((up_key==0)&&(setflag!
=0))
{
delay1ms(100);
if(up_key==0)
{
num++;
if(num==10)num=0;
switch(setflag)
{
case0:
;break;
case1:
if(num%2==0)
{
wr_com(0x89);
wr_dat(0x20);
}
else
{
wr_com(0x89);
wr_dat(0x2d);
}
break;
case2:
if(num==0)
{
wr_com(0x8a);
wr_dat(0x20);
bai=num;
}
else
{
wr_com(0x8a);
wr_dat(num+0x30);
bai=num;
}
break;
case3:
if((bai==0)&&(num==0))
{
wr_com(0x8b);
wr_dat(0x20);
shi=num;
}
else
{
wr_com(0x8b);
wr_dat(num+0x30);
shi=num;
}
break;
case4:
wr_com(0x8c);
wr_dat(num+0x30);
wr_com(0x8d);
wr_dat(0x2e);//显示小数点
ge=num;
break;
case5:
wr_com(0x8e);
wr_dat(num+0x30);
xiaoshu=num;
break;
case6:
wr_com(0xc1);
wr_dat(num+0x30);
Kp_ge=num;
wr_com(0xc2);
wr_dat(0x2e);//显示小数点
break;
case7:
wr_com(0xc3);
wr_dat(num+0x30);
Kp_xiao=num;
break;
case8:
wr_com(0xc6);
wr_dat(num+0x30);
wr_com(0xc7);
wr_dat(0x2e);//显示小数点
Ki_ge=num;
break;
case9:
wr_com(0xc8);
wr_dat(num+0x30);
Ki_xiao=num;
break;
case10:
wr_com(0xcb);
wr_dat(num+0x30);
Kd_ge=num;
wr_com(0xcc);
wr_dat(0x2e);//显示小数点
break;
case11:
wr_com(0xcd);
wr_dat(num+0x30);
Kd_xiao=num;
break;
}
}
}
if((down_key==0)&&(setflag!
=0))
{
delay1ms(100);
if(down_key==0)
{
num--;
if(num<0)num=9;
switch(setflag)
{
case0:
;break;
case1:
if(num%2==0)
{
wr_com(0x89);
wr_dat(0x20);
}
else
{
wr_com(0x89);
wr_dat(0x2d);
}
break;
case2:
if(num==0)
{
wr_com(0x8a);
wr_dat(0x20);
bai=num;
}
else
{
wr_com(0x8a);
wr_dat(num+0x30);
bai=num;
}
break;
case3:
if((bai==0)&&(num==0))
{
wr_com(0x8b);
wr_dat(0x20);
shi=num;
}
else
{
wr_com(0x8b);
wr_dat(num+0x30);
shi=num;
}
break;
case4:
wr_com(0x8c);
wr_dat(num+0x30);
wr_com(0x8d);
wr_dat(0x2e);//显示小数点
ge=num;
break;
case5:
wr_com(0x8e);
wr_dat(num+0x30);
xiaoshu=num;
break;
case6:
wr_com(0xc1);
wr_dat(num+0x30);
Kp_ge=num;
wr_com(0xc2);
wr_dat(0x2e);//显示小数点
break;
case7:
wr_com(0xc3);
wr_dat(num+0x30);
Kp_xiao=num;
break;
case8:
wr_com(0xc6);
wr_dat(num+0x30);
wr_com(0xc7);
wr_dat(0x2e);//显示小数点
Ki_ge=num;
break;
case9:
wr_com(0xc8);
wr_dat(num+0x30);
Ki_xiao=num;
break;
case10:
wr_com(0xcb);
wr_dat(num+0x30);
Kd_ge=num;
wr_com(0xcc);
wr_dat(0x2e);//显示小数点
break;
case11:
wr_com(0xcd);
wr_dat(num+0x30);
Kd_xiao=num;
break;
}
}
}
}
/******************************ds1820程序***********************************/
voiddelay_18B20(unsignedinti)//延时1微秒
{
while(i--);
}
voidds1820rst()/*ds1820复位*/
{
unsignedcharx=0;
DQ=1;//DQ复位
delay_18B20(4);//延时
DQ=0;//DQ拉低
delay_18B20(100);//精确延时大于480us
DQ=1;//拉高
delay_18B20(40);
}
uchards1820rd()/*读温度数据*/
{
unsignedchari=0;
unsignedchardat=0;
for(i=8;i>0;i--)
{
DQ=0;//给脉冲信号
dat>>=1;
DQ=1;//给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(10);
}
return(dat);
}
void