资源描述
HUBEI NORMAL UNIVERSITY
单片机课程设计
所在院系
教育信息与技术学院
专业名称
电子信息工程
班级
1005
题目
基于数字温度传感器的数字温度计
指导教师
成员
完成时间
2012.12.27
一、设计任务及要求:
设计任务:
基于数字温度传感器的数字温度计的设计。
要 求:
1.利用数字温度传感器DS18B20与单片机结合来测量温度;
2.利用数字温度传感器DS18B20测量温度信号,计算后在LCD数码管上显示相应的温度值。其温度测量范围为−55℃~125℃,精确到0.5℃;
3.数字温度计所测量的温度采用数字显示,控制器使用单片机AT89C51,测温传感器使用DS18B20;
4.用蜂鸣器设置警告音。
指导教师签名:
2012年12月28日
二、指导教师评语:
指导教师签名:
2012 年12月 28日
三、成绩
验收盖章
2012年12月28 日
基于数字温度传感器的数字温度计的设计
1.芯片DS18B20的说明
美国Dallas 半导体公司的数字化温度传感器DS1820 是世界上第一片支持 "一线总线"接口的温度传感器,在其内部使用了在板(ON-B0ARD)专利技术。全部传感元件及转换电路集成在形如一只三极管
的集成电路内。一线总线独特而且经济的特点,使用户可轻松地组建传感器网络,为测量系统的构建引入全新概念。现在,新一代的DS18B20 体积更小、更经济、更灵活。使你可以充分发挥“一线总线”的优点。
DS18B20 的主要特性
1.1芯片DS18B20的特点
(1)适应电压范围更宽,电压范围:3.0~5.5V,在寄生电源方式下可由数据线供电
(2)独特的单线接口方式,DS18B20 在与微处理器连接时仅需要一条口线即可实现微处理与DS18B20 的双向通讯
(3)DS18B20 支持多点组网功能,多个DS18B20 可以并联在唯一的三线上,实现组网多点测温
(4)DS18B20 在使用中不需要任何外围元件,全部传感元件及转换电路集成在形如一只三极管的集成电路内
(5)温范围-55℃~+125℃,在-10~+85℃时精度为±0.5℃
(6)可编程的分辨率为9~12 位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和0.0625℃,可以实现高精度测温。
(7)在9位分辨率最多在93.75ms把温度转换成数字,12 位分辨率是最多可在750ms内将温度转换成数字,速度更快。
(8)温度测试结果直接转换成数字温度信号,以“一线总线”串行传输给CPU,同事科传送SRC检验码,菊友极强的抗干扰校正能力。
(9)负压特性:电源极性接反时芯片不会因发热而烧毁,但不会正常工作。
2. 液晶显示器LM016L的说明
接口信号说明:
编号
符号
引脚说明
编号
符号
引脚说明
1
VSS
电源地
9
D2
Data I/0
2
VDD
电源正极
10
D3
Data I/0
3
VL
液晶显示偏压信号
11
D4
Data I/0
4
RS
数据/命令选择端
12
D5
Data I/0
5
R/W
读/写选择端
13
D6
Data I/0
6
E
使能信号
14
D7
Data I/0
7
D0
Data I/0
15
BLA
背光级正极
8
D1
Data I/0
16
BLK
背光级负极
下表为控制命令表:
序号
指令
RS
R/W
D7
D6
D5
D4
D3
D2
D1
D0
1
清显示
0
0
0
0
0
0
0
0
0
1
2
光标返回
0
0
0
0
0
0
0
0
1
*
3
置输入模式
0
0
0
0
0
0
0
1
I/D
S
4
显示开/关控制
0
0
0
0
0
0
1
D
C
B
5
光标或字符移位
0
0
0
0
0
1
S/C
R/L
*
*
6
置功能
0
0
0
0
1
DL
N
F
*
*
7
置字符发生存贮器地址
0
0
0
1
字符发生存贮器地址
8
置数据存贮器地址
0
0
1
显示数据存贮器地址
9
读忙标志或地址
0
1
BF
计数器地址
10
写数到CGRAM或DDRAM)
1
0
要写的数据内容
11
从CGRAM或DDRAM读数
1
1
读出的数据内容
l 液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电平,表示不忙,否则此指令失效。要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,图一是016L的内部显址。
图一
液晶显示简介
①液晶显示原理
液晶显示的原理是利用液晶的物理特性,通过电压对其显示区域进行控制,有电就有显示,这样即可以显示出图形。液晶显示器具有厚度薄、适用于大规模集成电路直接驱动、易于实现全彩色显示的特点,目前已经被广泛应用在便携式电脑、数字摄像机、PDA移动通信工具等众多领域。
②液晶显示器的分类
液晶显示的分类方法有很多种,通常可按其显示方式分为段式、字符式、点阵式等。除了黑白显示外,液晶显示器还有多灰度有彩色显示等。如果根据驱动方式来分,可以分为静态驱动(Static)、单纯矩阵驱动(Simple Matrix)和主动矩阵驱动(Active Matrix)三种。
③字符的显示
用LCD显示一个字符时比较复杂,因为一个字符由6×8或8×8点阵组成,既要找到和显示屏幕上某几个位置对应的显示RAM区的8字节,还要使每字节的不同位为“1”,其它的为“0”,为“1”的点亮,为“0”的不亮。这样一来就组成某个字符。但由于内带字符发生器的控制器来说,显示字符就比较简单了,可以让控制器工作在文本方式,根据在LCD上开始显示的行列号及每行的列数找出显示RAM对应的地址,设立光标,在此送上该字符对应的代码即可。
3. 总体电路流程图
时钟振荡
主
控
电
路
LCD显示
温度传感器
开始
DS18B20的初始化
跳过读序列号的操作
启动温度转换
读取温度寄存器
跳过读序列号的操作
DS18B20的初始化
结束
4. 总体电路设计
LCD与AT89C51的连接,(如图一所示)将LCD的D0~D7引脚分别与单片机的P0.1~P0.7相连,使LCD能接受来自单片机的信号。
电路如图二所示
如图可见,电路主要是由AT89C51芯片和LM016L和蜂鸣器构成了主要电路。开关的控制,可调整温度的范围。
5.系统程序设计
程序清单 :
#include <AT89X51.H>
#include <intrins.h>
#include<absacc.h>
#define uint unsigned int
#define unchar unsigned char
unchar templ,temph,i,y,z,n;
unchar a,b;//LCD的变量
unchar sign=0;//标志变量
bit k; //判断正负变量
sbit dq=P3^5;
sbit rs=P2^0;//LCD显示的定义取值
sbit rw=P2^1;
sbit e=P2^2;
sbit bf=P0^7;
sbit DQ=P2^5;
//键盘定义
sbit read=P3^0;
sbit incH=P3^2;
sbit desH=P3^3;
sbit reset=P3^4;
//蜂鸣器
sbit BUZZER=P2^6;
float t4,t5,t6,t7,tt;//温度转换的变量
uint tp;
unchar temperature,Htemp,Ltemp;
unchar D1,D2,D3;
uint D4,D5,D6,D9,D7,D8;
unchar code dis1[]={"0123456789"};
unchar code dis2[]={"temp:"};
unchar code dis3[]={"WARN"};
unchar code dis4[]={"Htemp:"};
unchar code dis5[]={"working"};
unchar code dis6[]={"Ltemp:"};
bit flag_1820_1;
bit flag_1820_2;
void delay_ms(unsigned char time);
void ledshow(void);
void keypress(void);
void init(void);
void gettemp();
void init1820(void);
void write1820(unchar);
unsigned char read1820(void);
void delay_us(unchar);
void delay3(unchar);
/* 延时*/
void delay(uint t)
{ uint i;
while(t--)
{ for(i=0;i<125;i++)
{}
}
}
//LCD显示函数
void delay1(unchar time)
{ unchar n;
n=0;
while(n<time)
{n++;}
return;
}
void delay3(unchar x)
{ for(y=x;y>0;y--)
for(z=x;z>0;z--);
}
unchar testBF()
{ bit result;
rs=0;rw=1;e=1;
_nop_();_nop_();_nop_();_nop_();
result=bf;e=0;
return result;
}
void writecmd(unchar ZL)
{ while(testBF()==1);
rs=0;rw=0;e=0;
_nop_();_nop_();
P0=ZL;e=1;
_nop_();_nop_();_nop_();_nop_();
e=0;
}
void pos(unchar pos)
{ writecmd(pos|0x80);
}
void writedate(unchar date)
{while(testBF()==1);
rs=1;rw=0;e=0;
_nop_();_nop_();
P0=date;e=1;
_nop_();_nop_();_nop_();_nop_();
e=0;
}
void init()
{ delay3(20);
writecmd(0x38);
delay3(30);
writecmd(0x0d);
delay3(30);
writecmd(0x06);
delay3(30);
writecmd(0x01);
delay3(30);
}
//键盘程序
//主程序
void main(void)
{
TMOD=0x01;
TH0=50000/256;
TL0=50000%256;
Htemp=124;Ltemp=-24;
P3=0xFF;
init();
if(sign==0)
{
EA=1;TR0=1;ET0=1;
EX0=0; //关闭外部中断0
EX1=0; //关闭外部中断1
while(1)
{
if(read==0)
{
delay3(2000);
if(read==0)
{
sign++;
}
}
}
}
if(sign==1)
{
BUZZER=1; //关闭蜂鸣器
EX0=1; //开启外部中断0
EX1=1; //开启外部中断1
init();
pos(0);
for(i=0;i<6;)
{ writedate(dis4[i]);i++;
}
D6=Htemp%10;
D7=Htemp%100/10;
D8=Htemp/100;
pos(0x6);
writedate(dis1[D8]);
writedate(dis1[D7]);
}
if(sign==2)
{
BUZZER=1; //关闭蜂鸣器
EX0=1; //开启外部中断0
EX1=1; //开启外部中断1
init();
pos(0);
for(i=0;i<6;)
{ writedate(dis6[i]);i++;}
D6=Htemp%10;
D7=Htemp%100/10;
D8=Htemp/100;
pos(0x6);
writedate(dis1[D8]);
writedate(dis1[D7]);
writedate(dis1[D6]);
}
if(sign>2)
{ sign=0;}
}
//中断程序
void int0(void) interrupt 0
{
EX0=0; //关外部中断0
if(desH==0&&sign==1)
{
Htemp--;
if(Htemp<Ltemp)
Htemp=Ltemp;
}
else if(desH==0&&sign==2)
{
Ltemp--;
}
}
/*****外部中断1服务程序*****/
void int1(void) interrupt 2
{
EX1=0; //关外部中断1
if(incH==0&&sign==1)
{
Htemp++;
}
else if(incH==0&&sign==2)
{
Ltemp++;
if(Ltemp>Htemp)
Ltemp=Htemp;
}
}
//定时器T0服务程序
void isr_t0(void) interrupt 1
{ TH0=50000/256;
TL0=50000%256;
TMOD=0x10;
TH1=50000/256;
TL1=50000%256;
gettemp();
delay(50);
if (tp<Htemp)
{ BUZZER=1;
pos(0x04);
for(i=0;i<7;)
{
writedate(dis5[i]);
i++;
}
pos(0x40);
for(i=0;i<5;)
{writedate(dis2[i]);
i++;}
D1=(unchar)(tp%10);
D2=(unchar)(tp%100/10);
D3=(unchar)(tp/100);
D4=(uint)(tt*10);
D5=((uint)(tt*100))%10;
if(k==1)
{pos(0x46);
writedate('-');}
else
{pos(0x46);
writedate();}
pos(0x47);
writedate(dis1[D3]);
writedate(dis1[D2]);
writedate(dis1[D1]);
writedate('.');
writedate(dis1[D4]);
writedate(dis1[D5]);
writedate(0xdf);
writedate('C');
}
else
{ init();
pos(0x04);
for(i=0;i<4;)
{
writedate(dis3[i]);
i++;}
BUZZER=0;
}
}
//DS18B20读取温度
void gettemp()
{
init1820();
write1820(0xcc);
write1820(0x44);
init1820();
write1820(0xcc);
write1820(0xbe);
templ=read1820();//低8位(其中的第四位是小数点后的)
temph=read1820();//高8位(其中前五位是符号值)
z=temph;//把符号位留下判断正负
k=(bit)(z>>7);
if(k==1) //负数就取反加一
{ templ=~templ;
templ=templ+1;
temph=~temph;
}
else
{templ=templ;
temph=temph;}
n=templ;
y=n&0x01;
t7=y*0.0625;
n>>=1;
y=n&0x01;//小数点最后的数
t4=y* 0.125;
n>>=1;
y=n&0x01;
t5=y* 0.25;
n>>=1;
y=n&0x01;
t6=y*0.5;
tt=t4+t5+t6+t7;
init1820();
tp=temph*256+templ;
temperature=tp;
tp=tp>>4;
}
//1820初始化
void init1820()
{
DQ = 1; _nop_();
DQ = 0;
delay_us(125); //延时510us,
delay_us(125);
DQ = 1;
delay_us(15);
while(DQ)
{ _nop_(); }
delay_us(60);
DQ = 1;
}
//******write********
void write1820(unchar a)
{
unchar i;
for(i=0;i<8;i++)
{if(a & 0x01) //低位在前;
{DQ = 0;
_nop_();_nop_();_nop_();
DQ = 1; }
else
DQ = 0;
_nop_();_nop_();_nop_();
delay_us(30);
DQ = 1;
_nop_();
a >>= 1;
}
}
//*******read************
unsigned char read1820(void)
{
unsigned char i;
unsigned char tmp=0;
DQ = 1; _nop_();
for(i=0;i<8;i++)
{
tmp >>= 1;
DQ = 0;
_nop_();
DQ = 1;
delay_us(2);
_nop_();
if(DQ)
tmp |= 0x80;
delay_us(30);
DQ = 1; _nop_();
}
return tmp; }
void delay_us(unchar a)
{
while(--a);
}
void delay_ms(unchar a)
{
unchar i,j;
for(i=0;i<a;i++)
for(j=0;j<200;j++)
{
_nop_();
_nop_();
}
}
6.总结
1)在编写程序的过程中,遇到一些C语言的语法问题,需要查找资料或者咨询同学才能完成。
2)在连接电路图时会时常将接口的位置混淆,记清每个接口的位置十分重要。
3)蜂鸣器偶尔一直响,偶尔一直不响。需用一个三极管解决。
参考文献
51单片机C语言教程 郭天祥 电子工业出版社
展开阅读全文