单片机工程师考试文档.docx
《单片机工程师考试文档.docx》由会员分享,可在线阅读,更多相关《单片机工程师考试文档.docx(29页珍藏版)》请在冰点文库上搜索。
单片机工程师考试文档
单片机开发与设计工程师考试文档
学校:
湖南人文科技学院
设计题目:
数字温度计
学生姓名:
尹葵
日期:
2010年6月25日
摘要
随着时代的进步和发展,单片机技术已经普及到我们生活,工作,科研,各个领域,已经成为一种比较成熟的技术,本文将介绍一种基于单片机控制的数字温度计,本温度计属于多功能温度计,可以设置上下报警温度,当温度不在设置范围内时,可以报警。
本设计所介绍的数字温度计与传统的温度计相比,具有读数方便,测温范围广,测温准确,其输出温度采用数字显示,主要用于对测温比较准确的场所,或科研实验室使用,该设计控制器使用单片机STC89C52,测温传感器使用DS18B20,用3位共阳极LED数码管实现温度显示。
使用矩阵键盘来调节报警温度的上下限。
关键词:
单片机,数字控制,温度计,DS18B20,STC89C52
数字温度计
设计要求
本课题以单片机为核心,设计并制作一个数字温度计,具有以下功能:
1、测温范围:
-30℃~80℃;
2、分辨率:
0~1℃;
3、温度输出显示:
3位;
4、能任意设置上下限报警温度;
5、超过上、下限能自动报警;
1数字温度计系统设计方案
本数字温度计设计采用美国DALLAS半导体公司继DS1820之后推出的一种改进型只能温度传感器DS18B20作为检测元件,测温范围为-55~125℃,最高分辨率可达0.0625℃。
此传感器可直接读出被测温度值,硬件电路简单,具有低成本和易使用的特点。
按照系统设计功能的要求,确定系统主要有3个模块组成:
主控制器、测温电路、显示电路和键盘电路。
图1系统方框图
2硬件模块设计
2.1主控制器STC89C52与IO接口扩展芯片8255
本设计采用主控芯片是STC89C52,外加一IO接口扩展芯片8255来控制键盘与数码管的工作。
8255具有3个8位并行口PA,PB和PC。
如图2所示:
图2单片机89C52与8255
2.2温度传感器DS18B20
DS18B20温度传感器是美国DALLAS半导体公司最新推出的一种改进型智能温度传感器,与传统的热敏电阻等测温元件相比,它能直接读出被测温度,并且可根据实际要求通过简单的编程实现9~12位的数字值读数方式。
DS18B20的性能特点如下:
●独特的单线接口仅需要一个端口引脚进行通信;
●多个DS18B20可以并联在惟一的三线上,实现多点组网功能;
●无须外部器件;
●可通过数据线供电,电压范围为3.0~5.5V;
●零待机功耗;
●温度以9或12位数字;
●用户可定义报警设置;
●报警搜索命令识别并标志超过程序限定温度(温度报警条件)的器件;
●负电压特性,电源极性接反时,温度计不会因发热而烧毁,但不能正常工作;
图3DS18B20
2.3数码管显示模块
LED数码管来显示当前的温度和设置报警温度时显示报警温度上下限的值。
此电路采用的是共阳极的六位数码管,PA0~PA5为数码管的位选,PB口为数码管的段选。
低电平有效。
电路如图4所示:
图4数码管显示硬件电路
2.44*4矩阵键盘模块
通过键盘来设置报警温度值,设置4个按键,分别用来增加或减少上下限温度值。
即用到了如下图所示的第一列。
键盘采用的是矩阵式的。
PC0~PC3口接下拉电阻,作为输入,控制键盘的行;PA0~PA3控制键盘的列。
键盘扫描子函数里,采用的是:
先将PA0口置高电平,在读取PC口的状态。
如果PC0~PC3口中某个出现了高电平,说明检测到该行与PA0口交汇处的键盘被按下。
电路如图5示:
图5矩阵键盘
2.4其他模块
此电路为高电平复位电路。
进行复位操作时,外部电路需在RST引脚产生两个机器周期(即24个时钟周期)以上的高电平。
如图6所示,按下键盘,电源对C1充电,使RST端快速产生高电平;松开按键,C1向芯片的内阻放电,恢复为低电平,从而使单片机可靠复位。
图6复位模块
报警模块采用的蜂鸣器,其输入信号直接从单片机P3.3口输出,通过高低电平交错出现加上延时程序,便能发出声音。
当检测到的温度超过上下限时,蜂鸣器报警。
如图7所示:
图7报警电路
3软件模块设计
主程序
图8软件系统工作流程图
本设计软件系统工作流程主要分为四块:
初始化、读取温度、显示温度模块,键盘模块。
下面逐一对各个模块进行软件设计。
3.1初始化模块
此子程序实现对温度传感器DS18B20的初始化。
先将DQ即信号线置1,稍做延时,再将其拉低,精确延时,须大于580us,再拉高DQ,延时后,如果x=0则初始化成功;如x="1则初始化失败"。
程序如下:
//初始化函数
voidInit_DS18B20(void)
{
unsignedcharx=0;
DQ=1;//DQ复位
delay
(1);//稍做延时
DQ=0;//单片机将DQ拉低
delay(80);//精确延时大于480us
DQ=1;//拉高总线
delay(5);
x=DQ;//稍做延时后如果x=0则初始化成功x="1则初始化失败"
while(x);
delay(15);
}
3.3读取温度模块
先将DS18B20初始化,接着写一个跳过ROM操作的指令0XCC,再写一个开始温度转换的指令0X44。
再初始化,写一个跳过ROM操作的指令0XCC,接着读取存储器的值,将读出来的值分别赋给a,b.其中a存放低八位,b存放高八位。
读取温度子程序如下:
voidReadTemp(void)
{
Init_DS18B20();
WriteOneChar(0xCC);//SkipROM跳过ROM操作
WriteOneChar(0x44);//StartConversion开始温度转换
Init_DS18B20();
WriteOneChar(0xCC);//SkipROM跳过ROM操作
WriteOneChar(0xBE);//读存储器的值
a=ReadOneChar();
b=ReadOneChar();
}
3.4计算温度子程序
voidwork_temp()//温度处理之函数
{
b1=b>>4;
if(b>0xFC)//温度为负数时,把高位取反,低位取反加1
{
b=~b;
a=~a+1;
}
temp=(a>>4|b<<4);//a右移4位,得整数部分,b左移4位去掉符号位
temp1=((a&0x0f)*10/16);//去温度的小数位(四位)乘以十再除十六即可得到一位小数
}
3.5键盘子程序
通过不段扫描键盘是否有键按下,来设置报警温度的上下限。
本设计采用的是先将PA1口拉高,然后判断PC口的值,看PC口是否有高电平,如果有,则说明有键盘按下,且出现高电平的某个PC口与PA1口的交汇处的键盘就是当前被按下的键盘。
由于程序运行的时间很短,而按键下去的时间相对来说比较长,所以必须加上等待按键释放的语句,才能保证按键一次,温度值加或减1。
程序如下:
voidscan_keyboard()
{
ucharkdata;
PA=0x01;
kdata=PC;
if(kdata==0x01)
{
delay(5);//延时一会
kdata=PC;//重新读取PC口的值
if(kdata==0x01)
{
while(PC);//等待按键释放
upper++;
flag=1;
}
}
if(kdata==0x02)
{
delay(5);
kdata=PC;
if(kdata==0x02)
{
while(PC);
upper--;
flag=1;
}
}
if(kdata==0x04)
{
delay(5);
kdata=PC;
if(kdata==0x04)
{
while(PC);
lower++;
flag=1;
}
}
if(kdata==0x08)
{
delay(5);
kdata=PC;
if(kdata==0x08)
{
while(PC);
lower--;
flag=1;
}
}
}
3.6温度显示子程序
本设计用到了两个显示子程序,即一个用来显示当前温度值的大小,当检测到有键盘按下时,另一个显示当前的设置的报警温度的上下限值。
具体程序如下:
voiddisplay(ucharnum,ucharnum1)//显示子函数,分别显示整数和小数部分
{
CON=0x89;
PA=0xFF;
PB=0xFF;
PA=0xFD;//显示十位
PB=table[num/10];
delay(50);
PB=0xFF;
PA=0xFB;//显示个位
PB=table[num%10];
delay(50);
PB=0xFF;
PA=0xF7;//显示小数位
PB=table[num1];
delay(50);
PB=0xFF;
if(b1==0xFF)//显示负号
{
PA=0xFE;
PB=0x7F;
delay(50);
}
}
voiddisplay1(ucharm,ucharn)//显示温度的上下限
{
CON=0x89;
PA=0xFF;
PB=0xFF;
PA=0xFE;//显示负号
PB=0x7F;
delay(50);
PA=0xFD;//显示温度值下限的十位
PB=table[m/10];
delay(50);
PB=0xFF;
PA=0xFB;//显示温度值下限的个位
PB=table[m%10];
delay(50);
PB=0xFF;
PA=0xEF;//显示温度值上限的十位
PB=table[n/10];
delay(50);
PB=0xFF;
PA=0xDF;//显示温度值上限的个位
PB=table[n%10];
delay(50);
PB=0xFF;
}
4系统调试
系统的调试以程序调试为主。
硬件调试比较简单,首先检查电路的焊接是否正确,然后可用万用表测试或通电检测。
软件调试可以先编写好显示程序并进行硬件的正确性检验,然后分别进行主程序。
读取温度子程序、计算温度子程序和显示数据程序等的编程和调试。
由于DS18B20与单片机采用串行数据传送,因此,对DS18B20进行读/写编程时必须严格地保证读/写的时序;否则将无法读取测量的温度。
本程序采用的是C语言编写,用KeilC51编译器编程调试。
软件调试到能显示温度值,而且有温度变化时(例如用手去接触)说明已经DS18B20
正常工作了。
再按下键盘,调节报警温度的上下限。
5系统操作流程
第一步:
打开装置的电源开关,数码管显示当前的温度值,程序里默认的报警温度的上限是30度。
第二步:
用手握住温度传感器DS18B20,此时看到数码管上显示的温度值在上升,当超过30度时,蜂鸣器报警。
第三步:
按键调节温度的上限,把它设置为29度,此时再握住DS18B20,温度不断上升,当达到29度时,蜂鸣器报警。
参考文献
[1]张鑫.单片机原理及应用。
北京:
电子工业出版社,2005
[2]楼然梦.李光飞。
单片机课程设计指导。
北京:
北京航空航天大学出版社,2007
[3]朱定华.戴汝平。
单片微机原理与应用。
北京:
清华大学出版社,2003
[4]张毅刚.单片机原理及应用。
北京:
高等教育出版社,2004
[5]立全利.迟荣强。
单片机原理及接口。
北京:
高等教育出版社,2004
[6]蔡明文.冯先成。
单片机课程设计。
武汉:
华中科技大学出版社,2007
[7]潘永雄.新编单片机原理及应用。
西安:
西安电子科技大学出版社,2003
附录一:
八段共阳数码管段码表
十进制数字
十六进制段码值
0
0xA0
1
0XBB
2
0x62
3
0x2A
4
0x39
5
0x2C
6
0x24
7
0xBA
8
0x20
9
0x28
附录二:
元器件清单
元器件名称
数量
30pF电容
2
8255
1
104电容
1
发光二极管
1
单片机AT89C52
1
三极管9015
7
六位八段共阳数码管
2
按键
17
12M晶振
1
1k电阻
20
附录三:
DS18B20温度与表值对应表
温度/℃
二进制表示
十六进制表示
+125
0000011111010000
07D0H
+85
0000010101010000
0550H
+25.0625
0000000110010000
0191H
+10.125
0000000010100001
00A2H
+0.5
0000000000000010
0008H
0
0000000000001000
0000H
-0.5
1111111111110000
FFF8H
-10.125
1111111101011110
FF5EH
-25.0625
1111111001101111
FE6FH
-55
1111110010010000
FC90H
附录四:
原理图
附录五:
数字温度计的源程序
/*************************************************************
名称:
数字温度计
日期:
2010年6月25日
*************************************************************/
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
#definePAXBYTE[0xD1FF]/*PA口地址*/
#definePBXBYTE[0xD2FF]/*PB口地址*/
#definePCXBYTE[0xD5FF]/*PC口地址*/
#defineCONXBYTE[0xD7FF]/*控制字地址*/
uchara=0,b=0,b1=0,temp=0,temp1=0,upper,lower,flag;
uintk;
voiddelay(unsignedinti);
voiddisplay(ucharnum,ucharnum1);
voidscan_keyboard();
voidInit_DS18B20();
voidReadTemp();
sbitDQ=P1^7;//定义18B20数据端口
sbitbeep=P3^3;//定义蜂鸣器端口
unsignedcharconsttable[10]={
0xA0,/*0*/
0xBB,/*1*/
0x62,/*2*/
0x2A,/*3*/
0x39,/*4*/
0x2C,/*5*/
0x24,/*6*/
0xBA,/*7*/
0x20,/*8*/
0x28,/*9*/
};
//延时函数
voiddelay(uinti)
{
while(i--);
}
//初始化函数
voidInit_DS18B20(void)
{
unsignedcharx=0;
DQ=1;//DQ复位
delay
(1);//稍做延时
DQ=0;//单片机将DQ拉低
delay(80);//精确延时大于480us
DQ=1;//拉高总线
delay(5);
x=DQ;//稍做延时后如果x=0则初始化成功x="1则初始化失败"
while(x);
delay(15);
}
//读一个字节
unsignedcharReadOneChar(void)
{
unsignedchari=0;
unsignedchardat=0;
for(i=8;i>0;i--)
{
DQ=0;//给脉冲信号
dat>>=1;
DQ=1;//给脉冲信号
if(DQ)
dat|=0x80;
delay
(2);
}
return(dat);
}
//写一个字节
voidWriteOneChar(unsignedchardat)
{
unsignedchari;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
delay
(2);
DQ=1;
dat>>=1;
}
delay
(2);
}
/************************************
**
*读取温度*
**
************************************/
voidReadTemp(void)
{
Init_DS18B20();
WriteOneChar(0xCC);//SkipROM跳过ROM操作
WriteOneChar(0x44);//StartConversion开始温度转换
Init_DS18B20();
WriteOneChar(0xCC);//SkipROM跳过ROM操作
WriteOneChar(0xBE);//读存储器的值
a=ReadOneChar();
b=ReadOneChar();
}
voidwork_temp()//温度处理之函数
{
b1=b>>4;
if(b>0xFC)//温度为负数时,把高位取反,低位取反加1
{
b=~b;
a=~a+1;
}
temp=(a>>4|b<<4);//a右移4位,得整数部分,b左移4位去掉符号位
temp1=((a&0x0f)*10/16);//去温度的小数位(四位)乘以十再除十六即可得到一位小数
}
/************************************
**
*显示函数*
**
************************************/
voiddisplay(ucharnum,ucharnum1)//显示子函数,分别显示整数和小数部分
{
CON=0x89;
PA=0xFF;
PB=0xFF;
PA=0xFD;//显示十位
PB=table[num/10];
delay(50);
PB=0xFF;
PA=0xFB;//显示个位
PB=table[num%10];
delay(50);
PB=0xFF;
PA=0xF7;//显示小数位
PB=table[num1];
delay(50);
PB=0xFF;
if(b1==0xFF)//显示负号
{
PA=0xFE;
PB=0x7F;
delay(50);
}
}
voiddisplay1(ucharm,ucharn)//显示温度的上下限
{
CON=0x89;
PA=0xFF;
PB=0xFF;
PA=0xFE;//显示负号
PB=0x7F;
delay(50);
PA=0xFD;//显示温度值下限的十位
PB=table[m/10];
delay(50);
PB=0xFF;
PA=0xFB;//显示温度值下限的个位
PB=table[m%10];
delay(50);
PB=0xFF;
PA=0xEF;//显示温度值上限的十位
PB=table[n/10];
delay(50);
PB=0xFF;
PA=0xDF;//显示温度值上限的个位
PB=table[n%10];
delay(50);
PB=0xFF;
}
/************************************
**
*键盘函数*
**
************************************/
voidscan_keyboard()
{
ucharkdata;
PA=0x01;
kdata=PC;
if(kdata==0x01)
{
delay(5);
kdata=PC;
if(kdata==0x01)
{
while(PC);//等待按键释放
upper++;
flag=1;
}
}
if(kdata==0x02)
{
delay(5);
kdata=PC;
if(kdata==0x02)
{
while(PC);
upper--;
flag=1;
}
}
if(kdata==0x04)
{
delay(5);
kdata=PC;
if(kdata==0x04)
{
while(PC);
lower++;
flag=1;
}
}
if(kdata==0x08)
{
delay(5);
kdata=PC;
if(kdata==0x08)
{
while(PC);
lower--;
flag=1;
}
}
}
voidmain()
{
upper=30;
lower=10;
while
(1)
{
scan_keyboard();
if(flag==1)
{
flag=0;
k=800;
while(k--)
{
display1(lower,upper);
scan_keyboard();
}
}
else
{
PA=0xFB;//显示小数点
PB=0xDF;
ReadTemp();//读取温度
work_temp();
display(temp,temp1);
if(