基于51单片机的温度检测设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
基于51单片机的温度检测设计一.基本功能
利用AT89c51作为主控器和温度检测芯片DS18B20组成一个温度检测系统,实现温度的实时监控并由数码管显示。
二.硬件设计
图1.总设计图
1.单片机最小系统
1.1选用AT89C51的引脚功能
图2. AT89C51
XTAL1:单芯片系统时钟的反向放大器输入端。
XTAL2:系统时钟的反向放大器输出端,一般在设计上只要在XTAL1和XTAL2上接上一只石英震荡晶体系统就可以工作了,此外可以在两引脚与地之间加入20PF的小电容,可以使系统更稳定,避免噪音干扰而死机。
RESET:重置引脚,高电平动作,当要对晶体重置时,只要对此引脚电平提升至高电平并保持两个及其周期以上的时间便能完成系统重置的各项动作,使得内部特殊功能寄存器内容均被设成已知状态。
I/O:端口3是具有内部提升电路的双向I/O端口,通过控制各个端口的高低电平来控制数码管得位选。端口2用来控制数码管的段选。
1.2复位电路
如图所示,当按下按键时,就能完成整个系统的复位,使得程序从新运行。
图3.复位电路
1.3时钟电路
时钟电路用于产生单片机工作所需要的时钟信号,单片机本身就是一个复杂的同步时序电路,为了保证同步工作方式的实现,电路应在唯一的时钟信号控制下严格地按时序进行工作。
在AT89C51芯片内部有一个高增益反相放大器,其输入端为芯片引脚X1,输出端为引脚X2,在芯片的外部跨接晶体振荡器和微调电容,形成反馈电路,就构成了一个稳定的自激振荡器。此电路采用12MHz的石英晶体。
图4.时钟电路
2.数码管部分
图5.数码管电路3.DS18B20部分
图5.
三.软件设计
3.1编程语言及编程软件的选择
本设计选择C语言作为编程语言。C语言虽然执行效率没有汇编语言高,但语言简洁,使用方便,灵活,运算丰富,表达化类型多样化,数
据结构类型丰富,具有结构化的控制语句,程序设计自由度大,有很好
的可重用性,可移植性等特点。而汇编语言使用起来并没有这么方便。
本设计选用了Keil作为编程软件,.Keil C51生成的目标代码效率非常之高,多数语句生成的汇编代码很紧凑,容易理解。在开发大型软件时更能体现高级
语言的优势。
3.2 DS18B20工作原理
DS18B20的读写时序和测温原理与DS1820相同,只是得到的温度值的位数因分辨率不同而不同,且温度转换时的延时时间由2s减为750ms。 DS18B20测温原理如图2-6-1所示。图中低温度系数晶振的振荡频率受温度影响很小,用于产生固定频率的脉冲信号送给计数器1。高温度系数晶振随温度变化其振荡率明显改变,所产生的信号作为计数器2的脉冲输入。计数器1和温度寄存器被预置在-55℃所对应的一个基数值。计数器1对低温度系数晶振产生的脉冲信号进行减法计数,当计数器1的预置值减到0时,温度寄存器的值将加1,计数器1的预置将重新被装入,计数器1重新开始对低温度系数晶振产生的脉冲信号进行计数,如此循环直到计数器2计数到0时,停止温度寄存器值的累加,此时温度寄存器中的数值即为所测温度。图3中的斜率累加器用于补偿和修正测温过程中的非线性,其输出用于修正计数器1的预置值。
图6: DS18B20测温原理框图
3.3 数码管显示原理
本设计使用的是共阴极的八段式LED数码管,每个数码管是由8个小LED灯组成,通过控制每个小LED灯的亮灭来显示不同的数字。通过控制相应I/O的电平变化就可以控制数码管的显示。
四.程序
#include
#define uchar unsigned char
#define uint unsigned int
#define dx P2
#define wx P3
sbit ds=P3^7;
uint temp;
float f_temp;
uchar code t[]={ 0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x80
};
void delayms(uchar xms)
{
uint i,j;
for(i=xms;i>0;i--)
for(j=120;j>0;j--);
}
void delayus(uint time)
{
while(time--);
}
void dsreset(void) //DS18B20复位,初始化函数{
ds=0;
delayus(103);
ds=1;
delayus(4);
}
bit tempreadbit(void) //读一位数据的函数
{
uint x;
bit dat;
ds=0;x++; //起延时用
ds=1;x++;x++;
dat=ds;
delayus(8);
return(dat);
}
uchar tempread(void) // 读一个字节的函数
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tempreadbit();
dat=(j<<7)|(dat>>1); // 读出的数据最低位在前面}
return(dat);
}
void tempwritebyte(uchar dat) //向DS18B20写一个字节数据{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb)
{
ds=0;
i++;i++;
ds=1;
delayus(8);
}
else
{
ds=0;
delayus(8);
ds=1;
i++;i++;
}
}
}
void tempchange(void) //开始获取温度并转换
{
dsreset();
delayms(1);
tempwritebyte(0xcc); //跳过读ROM指令
tempwritebyte(0x44); //写温度指令指令
}
uint get_temp() //读取寄存器中的温度数据
{
uchar a,b;
dsreset();
delayms(1);
tempwritebyte(0xcc); //跳过读ROM指令
tempwritebyte(0xbe); //写暂存器
a=tempread(); //读低八位
b=tempread(); // 读高八位
temp=b;