资源描述
单片机课程设计
DS18B20数字温度计设计
专业 电子信息科学与技术
班级 11级2班
学号
姓名
目录
一. 课题的设计目的。
------------------------------------------------------------------------
二. 对于课题的总体构想。
------------------------------------------------------------------------
三. DS18B20温度传感器简介。
------------------------------------------------------------------------
四. STC89C51单片机简介。
------------------------------------------------------------------------
五. 系统总仿真电路。
------------------------------------------------------------------------
六. 总程序。
------------------------------------------------------------------------
七. 心得体会。
------------------------------------------------------------------------
八. 参考文献。 ---------------------------------------------------
一.课题的设计目的
1. 巩固、加深和扩大单片机应用的知识面,提高综合及灵活运用所学知识解决工业控制的能力。
2. 培养针对课题需要,选择和查阅有关手册、图表及文献资料的自学能力,提高组成系统、编程、调试的动手能力。
3. 通过对课题设计方案的分析、选择、比较、熟悉单片机用系统开发、研制的过程,软硬件设计的方法、内容及步骤。
二. 对课题的总体构想
采用数字温度芯片DS18B20 测量温度,输出信号全数字化。便于单片机处理及控制,省去传统的测温方法的很多外围电路。DS18B20 的最大特点之一采用了单总线的数据传输,由数字温度计DS18B20和微控制器STC89C52构成的温度测量装置,它直接输出温度的数字信号,可直接与计算机连接。
采用51 单片机控制,软件编程的自由度大,可通过编程实现各种各样的算术算法和逻辑控制,而且体积小,硬件实现简单,安装方便。既可以单独对多DS18B20控制工作,还可以与PC 机通信上传数据,另外STC89C52 在工业控制上也有着广泛的应用,编程技术及外围功能电路的配合使用都很成熟。
三. DS18B20温度传感器简介
DS18B20功能特点:
1. 采用单总线技术,与单片机通信只需要一根I/O线,在一根线上可以挂接多个DS18B20。
2. 每只DS18B20具有一个独有的,不可修改的64位序列号,根据序列号访问地应的器件。
3. 低压供电,电源范围从3~5V,可以本地供电,也可以直接从数据线上窃取电源(寄生电源方式)。
4. 测温范围为-55℃~+125℃,在-10℃~85℃范围内误差为±0.5℃。
5. 可编辑数据为9~12位,转换12位温度时间为750ms(最大)。
6. DS18B20可将检测到温度值直接转化为数字量,并通过串行通信的方式与主控制器进行数据通信。
DS18B20引脚如图所示。
四.DS18B20时序图
1.初始化时序
2.写时序
3.读时序
五.STC89C51单片机简介。
89C52单片机主要特性
1. 一个8 位的微处理器(CPU)。
2. 片内数据存储器RAM(128B),用以存放可以读/写的数据,如运算的中间结果、最终结果以及欲显示的数据等,SST89 系列单片机最多提供1K 的RAM。
3. 片内程序存储器ROM(4KB),用以存放程序、一些原始数据和表格。但也有一些单片机内部不带ROM/EPROM,如8031,8032,80C31 等。目前单片机的发展趋势是将RAM 和ROM 都集成在单片机里面,这样既方便了用户进行设计又提高了系统的抗干扰性。SST 公司推出的89 系列单片机分别集成了16K、32K、64K Flash 存储器,可供用户根据需要选用。
4. 四个8 位并行I/O 接口P0~P3,每个口既可以用作输入,也可以用作输出。
5. 两个定时器/计数器,每个定时器/计数器都可以设置成计数方式,用以对外部事件进行计数,也可以设置成定时方式,并可以根据计数或定时的结果实现计算机控制。为方便设计串行通信,目前的52 系列单片机都会提供3 个16 位定时器/计数器。
6. 五个中断源的中断控制系统。现在新推出的单片机都不只5 个中断源,例如SST89E58RD 就有9 个中断源。
7. 一个全双工UART(通用异步接收发送器)的串行I/O 口,用于实现单片机之间或单机与微机之间的串行通信。
8. 片内振荡器和时钟产生电路,但石英晶体和微调电容需要外接。最高允许振荡频率为12MHz。SST89V58RD 最高允许振荡频率达40MHz,因而大大的提高了指令的执行速度。
五. 系统总仿真电路。
六. 总程序 (分模块写)
1.main.c
#include<reg51.h>
#include"lcd.h"
#include"temp.h"
void LcdDisplay(int);
sbit K1=P2^0;
sbit K2=P2^1;
sbit K3=P2^2;
sbit K4=P2^3;
extern int th=20;
extern int tl=-10;
sbit beep=P1^0;
void main()
{
LcdInit();
LcdWriteCom(0xc7);
LcdWriteData('C');
while(1)
{
if(K1==0)
{
Delay1ms(500);
if(K1==0);
th++;
}
if(K2==0)
{
Delay1ms(500);
if(K2==0);
th--;
}
if(K3==0)
{
Delay1ms(500);
if(K3==0);
tl++;
}
if(K4==0)
{
Delay1ms(500);
if(K4==0);
tl--;
}
LcdDisplay(Ds18b20ReadTemp());
}
}
void LcdDisplay(int temp)
{
int i,tt,rr,mm;
unsigned char datas[] = {0, 0, 0, 0},datas1[] = {0, 0, 0},datas2[] = {0, 0, 0};
float tp;
if(temp< 0)
{
LcdWriteCom(0xc0);
LcdWriteData('-');
i=1;
temp=temp-1;
temp=~temp;
tp=temp;
temp=tp*0.0625*10+0.5;
mm=-temp;
}
else
{
LcdWriteCom(0xc0);
LcdWriteData('+');
tp=temp;
temp=tp*0.0625*10+0.5;
mm=temp;
}
datas[0] = temp / 1000;
datas[1] = temp % 1000 / 100;
datas[2] = temp % 100 / 10;
datas[3] = temp% 10;
if(th < 0)
{
LcdWriteCom(0x89);
LcdWriteData('-');
tt=-th;
}
else
{
LcdWriteCom(0x89);
LcdWriteData('+');
tt=th;
}
datas1[0] = tt / 100;
datas1[1] = tt% 100 / 10;
datas1[2] = tt % 10;
LcdWriteCom(0x87);
LcdWriteData('H');
LcdWriteCom(0x88);
LcdWriteData(':');
LcdWriteCom(0x8a);
LcdWriteData('0'+datas1[0]);
LcdWriteCom(0x8b);
LcdWriteData('0'+datas1[1]);
LcdWriteCom(0x8c);
LcdWriteData('0'+datas1[2]);
if(tl < 0)
{
LcdWriteCom(0x90);
LcdWriteData('-');
rr=-tl;
}
else
{
LcdWriteCom(0x90);
LcdWriteData('+');
rr=tl;
}
datas2[0] = rr / 100;
datas2[1] = rr% 100 / 10;
datas2[2] = rr % 10;
LcdWriteCom(0x8e);
LcdWriteData('L');
LcdWriteCom(0x8f);
LcdWriteData(':');
LcdWriteCom(0x91);
LcdWriteData('0'+datas2[0]);
LcdWriteCom(0x92);
LcdWriteData('0'+datas2[1]);
LcdWriteCom(0x93);
LcdWriteData('0'+datas2[2]);
if(mm>=(th*10)||mm<=(tl*10)||th<=tl)
beep=0;
else
beep=1;
LcdWriteCom(0x80);
LcdWriteData('T');
LcdWriteCom(0x81);
LcdWriteData('A');
LcdWriteCom(0x82);
LcdWriteData('I');
LcdWriteData(' ');
LcdWriteCom(0x84);
LcdWriteData('A');
LcdWriteCom(0x85);
LcdWriteData('N');
LcdWriteCom(0xc1);
LcdWriteData('0'+datas[0]);
LcdWriteCom(0xc2);
LcdWriteData('0'+datas[1]);
LcdWriteCom(0xc3);
LcdWriteData('0'+datas[2]);
LcdWriteCom(0xc4);
LcdWriteData('.');
LcdWriteCom(0xc5);
LcdWriteData('0'+datas[3]);
LcdWriteCom(0xc6);
LcdWriteData('"');
}
2.lcd.h
#ifndef __LCD_H_
#define __LCD_H_
/**********************************
当使用的是4位数据传输的时候定义,
使用8位取消这个定义
**********************************/
#define LCD1602_4PINS
/**********************************
包含头文件
**********************************/
#include<reg51.h>
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
/**********************************
PIN口定义
**********************************/
#define LCD1602_DATAPINS P0
sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;
sbit LCD1602_RS=P2^6;
/**********************************
函数声明
**********************************/
/*在51单片机12MHZ时钟下的延时函数*/
void Lcd1602_Delay1ms(uint c); //误差 0us
/*LCD1602写入8位命令子函数*/
void LcdWriteCom(uchar com);
/*LCD1602写入8位数据子函数*/
void LcdWriteData(uchar dat) ;
/*LCD1602初始化子程序*/
void LcdInit();
#endif
3.temp.h
#ifndef __TEMP_H_
#define __TEMP_H_
#include<reg51.h>
sbit DSPORT=P3^7;
void Delay1ms(unsigned int );
unsigned char Ds18b20Init();
void Ds18b20WriteByte(unsigned char com);
unsigned char Ds18b20ReadByte();
void Ds18b20ChangTemp();
void Ds18b20ReadTempCom();
int Ds18b20ReadTemp();
#endif
4.lcd.c
#include"lcd.h"
void Lcd1602_Delay1ms(uint c) //延时
{
uchar a,b;
for (; c>0; c--)
{
for (b=19;b>0;b--)
{
for(a=1;a>0;a--);
}
}
}
#ifndef LCD1602_4PINS //当没有定义这个LCD1602_4PINS时
void LcdWriteCom(uchar com) //写入一个字节命令
{
LCD1602_E = 0;
LCD1602_RS = 0;
LCD1602_RW = 0;
LCD1602_DATAPINS = com;
Lcd1602_Delay1ms(1);
LCD1602_E = 1;
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#else
void LcdWriteCom(uchar com)
{
LCD1602_E = 0;
LCD1602_RS = 0;
LCD1602_RW = 0;
LCD1602_DATAPINS = com; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1;
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
LCD1602_DATAPINS = com << 4; //发送低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1;
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
#ifndef LCD1602_4PINS
void LcdWriteData(uchar dat) //写入一个字节数据
{
LCD1602_E = 0;
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_DATAPINS = dat;
Lcd1602_Delay1ms(1);
LCD1602_E = 1;
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#else
void LcdWriteData(uchar dat)
{
LCD1602_E = 0;
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_DATAPINS = dat; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
LCD1602_DATAPINS = dat << 4; //写入低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
#ifndef LCD1602_4PINS
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x38);
LcdWriteCom(0x0c);
LcdWriteCom(0x06);
LcdWriteCom(0x01);
LcdWriteCom(0x80);
}
#else
void LcdInit()
{
LcdWriteCom(0x32);
LcdWriteCom(0x28);
LcdWriteCom(0x0c);
LcdWriteCom(0x06);
LcdWriteCom(0x01);
LcdWriteCom(0x80);
}
#endif
5.temp.c
#include"temp.h"
void Delay1ms(unsigned int y) //延时
{
unsigned int x;
for(y;y>0;y--)
for(x=110;x>0;x--);
}
unsigned char Ds18b20Init() //初始化
{
unsigned int i;
DSPORT=0;
i=70;
while(i--);
DSPORT=1;
i=0;
while(DSPORT)
{
i++;
if(i>5000)
return 0;//失败
}
return 1;//成功
}
void Ds18b20WriteByte(unsigned char dat) //写字节
{
unsigned int i,j;
for(j=0;j<8;j++)
{
DSPORT=0; //每写入一位数据之前先把总线拉低1us (数据手册上模糊)
i++;
DSPORT=dat&0x01;
i=6;
while(i--);
DSPORT=1;
dat>>=1;
}
}
unsigned char Ds18b20ReadByte()
{
unsigned char byte,bi;
unsigned int i,j;
for(j=8;j>0;j--)
{
DSPORT=0;
i++;
DSPORT=1;
i++;
i++;
bi=DSPORT;
byte=(byte>>1)|(bi<<7);
i=4;
while(i--);
}
return byte;
}
void Ds18b20ChangTemp() //温度转换
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc);
Ds18b20WriteByte(0x44);
}
void Ds18b20ReadTempCom() //读取温度命令
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc);
Ds18b20WriteByte(0xbe);
}
int Ds18b20ReadTemp() //读取温度
{
int temp=0;
unsigned char tmh,tml;
Ds18b20ChangTemp();
Ds18b20ReadTempCom();
tml=Ds18b20ReadByte();
tmh=Ds18b20ReadByte();
temp=tmh;
temp<<=8;
temp|=tml;
return temp;
}
七. 心得体会
通过两个星期的努力,我的单片机课程设计基于DS18B20的温度显示系统,终于完成了。虽然功能还不是很完善但却让我通过此次设计学会了不少东西。学会了keil和proteus软件的使用,从原本的生涩到现在的纯熟,是一个进步的过程!并且自己用C语言来编写代码,又通过这次课程设计学到了很多东西,部分跟C不太一样,通过网络的查找与应用,取得了不错的成效!
这次课程设计让我清楚的认识到只有理论与实践相结合才是真正的学习!为了自己的将来,我定会认真学好大学课程,在图书馆与网络上拓宽自己的知识(网络对我们的帮助很大),努力进取,实现自己的抱负与理想!
八. 参考文献
1. 张俊谟著 《单片机中级教程》,(第二版)。
2. 《C语言课程设计》,山东农业大学版。
仿真的最终效果图如上
34
展开阅读全文