基于单片机的数字温度测量系统设计报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数字温度测量系统
一、实习目的与要求
1、目的及意义
课题是数字温度测量系统的设计,利用数单片机测量温度信号,计算后在LED数码管上显示相应的温度值。
通过本次实习使学生了解和掌握工程设计所应遵循的步骤和程序,实习结束时,同学应具有以下的能力:
(一)综合应用的能力。
(二)应用参考文献的能力。
(三)电路设计能力。
(四)分析问题的能力。
(五)创新能力。
2、总体设计方案
本设计采用一只温度传感器DS18B20,此传感器,可以很容易直接读取被测温度值,进行转换,就可以满足设计要求。
而且此方案电路比较简单,软件设计也比较容易实现。
DS18B20可以直接温度转换为串行数字信号,供单片机进行处理,具有低功耗、商性能、抗干扰能力强等优点。
本设计采用STC89C52RC单片机实现。
单片机软件编程的自由度大,可通过编程实现各种各样的算术算法和逻辑控制。
而且体积小,硬件实现简单,安装方便。
既可以单独对多DS18B20控制工作,还可以与PC机通信。
另外STC89C52RC在工业控制上也有着广泛的应用,编程技术及外围功能电路的配合使用都很成熟。
单总线数字温度计DS1820采用基板专利技术来测量温度,温度传感器及各种数字转换电路都集成在一起,由总线串行输出测量值(9位二进制编码)。
测温范围从- 55~+125℃,还可以读内部计数器,获得较高的分辨率。
本课题主要研究如何利用DS18B20智能温度传感器实时显示温度,并将其与LED显示键盘合并使用,制成一个能实时显示温度的数字温度计。
本设计将利用DS18B20智能温度传感器和单片小系统,设计一个数字温度采集系统。
并设计一个人机接口电路:键盘采用独立按键(功能自定义),显示器采用共阴极4位LED显示。
系统的总体设计方案框图如图1所示:
图1 总体设计方案框图
按照系统设计功能的要求,系统主要由单片机、温度传感器DS18B20、LED数码显示管和PC机组成。
系统的硬件电路主要由复位电路、测温电路、显示电路、晶振电路组成,系统总体结构方框图如图2所示:
图2 系统总体结构框图
二、单片机开发板原理及各部分功能说明
1、整体功能:
(1)八个数码管显示(数字和字母显示)
(2)20个按键:包括4个独立按键和4*4矩阵键盘(人机接口输入)
(3)8个发光二极管(流水灯、指示灯、红灯)
(4)USB打印口(串口通信、USB供电)
(5)红外接收头(高灵敏度,可做红外遥控器解码)
(6)蜂鸣器(报警和音乐播放)
(7)EEPROM 24C02(数据存储)
(8)DS18B20(精密温度检测)
(9)晶振采用焊接方式,可以使用不同频率的晶振
(10)DS1302实时时钟
(11)标准1602和12864液晶接口
2、开发板总原理图如图3所示:
图3 开发板总原理图3、DS18B20原理图如图4所示:
图4 DS18B20原理图4、数码管原理图如图5所示:
图5 数码管原理图
三、软件编程
1、程序流程图
主程序是系统的监控系统,在程序运行的过程中必须先经过初始化,包括键盘程序,
中断程序,以及各个控制端口的初始化程序。
系统在初始或完成之后进入温度测量程序,实时的测量当前的温度通过电路在数码管上显示。
程序中已中断的方式来重新设定温度上下限。
根据温度传感器度温度的的测量。
按下键盘上的A 键可以设定温度上限,按下B 键可以设定温度下线,流程图如6所示。
是
否
图6 流程图
开始
系统初始化
Int0=0
温度上下限设定
温度测量
数码管显示系统
温度测量
四、系统调试
1、系统硬件调试
系统软硬件调试的目的是通过控制程序和硬件电路的配合工作,进行一些操作,以验证系统的软、硬件是否能够完成设计的功能。
调试的过程是按照系统的设计功能来划分的。
硬件电路系统测试首先是保证各个元件之间以及各个模块之间的连接正确并且接触良好,这是整个硬件电路系统正常工作的前提。
接着分别测试各个硬件模块的性能。
按照测试性质的不同可分为电压测试和信号测试两种。
电源模块主要是电压测试。
测试结果为:小型变压器输出为18v和8v的交流电,经过二极管整流桥整流,再通过稳压芯片7805和7815、7915输出的电压分别是+5v和+15v、-15v,电压测试的结果与预期目的一致,从而确保了提供给其它模块电压的稳定性。
单片机输入输出接口主要是信号测试。
根据理论计算和软件仿真的预期结果,再通过对响应的信号进行测试。
测试结果与预期结果基本一致,保证了系统按照设计的思路正常运行。
通过测试硬件电路系统中的几个测试点,确保关键的电压信号满足要求,确保系统正常运行。
2、系统软件调试
系统的软件调试借助于TKS仿真器,在进行系统软件的连续调试之前要先进行软件的初调,就是要使各个子程序模块运行正确,程序的运行流程正确。
软件调试主要分以下几个步骤进行:
1.功能子程序的调试
功能子程序的调试包括运算、采样、数字滤波以及PID运算等子程序的调试。
在调试功能子程序时,许多参数都是未知的,要根据其所需的条件,给出假定的数据,使其运行,如果能完成预定的处理功能或与手工计算的结果相符,就说明该子程序己调试通过。
调试时由小到大,由里到外。
例如,调试PID算法子程序时,先调通其包含的各个运算子程序和参数处理子程序,然后将它们连起来进行通调。
通调时,也是假定一些数据、参数和初始条件,然后运行程序。
当运算结果与手工计算的结果相同时,该算法子程序则调试完成,反之,就要进行相应的修改。
其它子程序的调试同理。
2.程序流程的调试
程序流程的调试主要是查看程序运行的步骤是否正确,在某时刻程序运行所处的位置是否正确,是否能正确运行各个中断服务程序。
在调试过程中,先将PID算法子程序屏蔽,输出可控硅导通时间用一个固定的常数代替,在各个中断服务子程序设置断点,然后运行程序,查看程序是否能运行到所有的断点,若所有断点都能运行到,则程序流程基本正确。
去掉所有断点,再一次运行程序,查看可控硅状态,从而判断程序流程正
确,反之,若程序流程不正确,做相应的修改后,重新调试。
3.功能程序与算法程序的通调
在完成整个程序流程的调试后,将PID等算法子程序加入,在算法子程序前或后设置断点,运行整个程序。
当程序在断点处暂停时,查看PID计算的控制量与手工计算的值是否相同。
多运行几次,若每次的结果都正确,则说明程序各个部分互相没有矛盾,反之,则说明算法子程序和其它子程序之间有影响,需要做相应的修改后重新调试四、总结及体会
本文重点介绍了单片机和数字传感器DS18B20的原理和功能,并用DS18B20与STC89C52单片机组成数字温度计。
在本次设计的过程中,我发现很多的问题,虽然以前还做过这样的设计,但这次设计真的让我长进了很多,单片机设计重点就在于软件程序的设计,需要有很巧妙的程序算法,虽然以前写过几次程序,但我觉的写好一个程序并不是一件简单的事,举个例子,以前写的那几次,数据加减时,我用的都是BCD码,这一次,我全部用的都是16进制的数直接加减,显示处理时在用除法去删分,感觉效果比较好,有好多的东西,只有我们去试着做了,才能真正的掌握,只学习理论有些东西是很难理解的,更谈不上掌握。
五、附录:
#include <reg52.h>
#include <intrins.h>
sbit DQ = P2^0; //定义DS18B20端口DQ
bit presence;
unsigned char code LEDData[] =
{
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82,
0xF8, 0x80, 0x90, 0xff, 0xc6, 0x9c, 0xbf
};
unsigned char data temp_data[2];
unsigned char data display[7] =
{
0x0b, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d
};
char code reserve[3]_at_ 0x3b; //保留0x3b开始的3个字节
/**********************************************************
us延时函数(8*1.085)*num
**********************************************************/
void Delay(unsigned int num) //延时函数
{
while (--num)
;
}
/********************************************************** 延时子程序
**********************************************************/ void delayms(unsigned int ms)
{
unsigned char k;
while (ms--)
{
for (k = 0; k < 114; k++)
;
}
}
/********************************************************** DS18B20初始化
presence=0 OK presence=1 ERROR
**********************************************************/ unsigned char Init_DS18B20(void)
{
DQ = 0; //单片机发出低电平复位信号
Delay(60); //延时>480us
DQ = 1; //释放数据线
Delay(8); //延时>64us,等待应答
presence = DQ; //接收应答信号
Delay(50); //延时>400us,等待数据线出现高电平
DQ = 1; //释放数据线
return (presence); //返回presence信号
}
/********************************************************** 读一个字节数据
**********************************************************/ unsigned char ReadOneChar(void)
{
unsigned char i = 0;
unsigned char dat = 0;
DQ = 1;
for (i = 0; i < 8; i++)
//一个字节8个bit
{
DQ = 0; //给低脉冲信号
dat >>= 1;
DQ = 1; //释放总线
_nop_();
_nop_();
if (DQ)
//读总线电平状态
dat |= 0x80;
//最高位置1
Delay(6); //延时>45us
DQ = 1; //释放总线,表示此次读操作完成
}
return (dat); //返回所读得数据
}
/********************************************************** 写一个字节数据
**********************************************************/ void WriteOneChar(unsigned char dat)
{
unsigned char i = 0;
for (i = 0; i < 8; i++)
//一个字节8个bit
{
DQ = 0; //给低脉冲信号
Delay(1); //延时<15us
dat >>= 1; //数据右移一位,最低位移入CY
DQ = CY; //写1bit数据
Delay(6); //延时>45us
DQ = 1; //释放总线,表示此次写操作完成
}
}
/********************************************************** 温度数据转换子程序
**********************************************************/ void Temperature_conver()
{
unsigned char minus = 0;
// display[0]=0x0b; //显示C
// display[1]=0x0c; //显示°
if (temp_data[1] > 127)
//温度为负值
{
temp_data[0] = (~temp_data[0]) + 1; //取反加一,将补码变成原码
if ((~temp_data[0]) >= 0xff)
temp_data[1] = (~temp_data[1]) + 1;
else
temp_data[1] = ~temp_data[1];
minus = 1; //温度为负值标志
}
display[6] = temp_data[0] &0x0f; //取小数位数据
display[2] = (display[6] *10) / 16; //保留一位小数
display[6] = ((temp_data[0] &0xf0) >> 4) | ((temp_data[1] &0x0f) << 4);
//取整数
display[5] = display[6] / 100; //百位
display[4] = (display[6] % 100) / 10; //十位
display[3] = display[6] % 10; //个位
if (!display[5])
//高位为0,不显示
{
display[5] = 0x0a;
if (!display[4])
//次高位为0,不显示
display[4] = 0x0a;
}
if (minus)
{
display[5] = 0x0d; //显示负号
}
}
/**********************************************************
数码管显示子函数
**********************************************************/ void ledplay()
{
unsigned char n, shift;
shift = 0xfe; //位码初值
for (n = 0; n < 6; n++)
//6位数码管显示
{
if (n == 3)
P0 = (LEDData[display[n]]) &0x7f;
//加小数点显示
else
P0 = LEDData[display[n]];
//输出段码
P1 = shift; //输出位码
shift = (shift << 1) | 0x01; //修改位码
delayms(1);
}
P1 = 0xff; //关闭显示
delayms(1);
}
/********************************************************** 主函数
**********************************************************/ void main(void)
{
unsigned char m;
P0 = 0xff;
P1 = 0xff;
while (1)
{
Init_DS18B20();
if (presence == 0)
{
WriteOneChar(0xCC); //跳过ROM匹配操作
WriteOneChar(0x44); //启动温度转换
for (m = 0; m < 120; m++)
//数码管初始化显示
ledplay();
//等待数据转换完成
}
Init_DS18B20();
if (presence == 0)
{
WriteOneChar(0xCC); //跳过ROM匹配操作
WriteOneChar(0xBE); //读取温度寄存器
temp_data[0] = ReadOneChar(); //温度低8位
temp_data[1] = ReadOneChar(); //温度高8位
Temperature_conver(); //数据转换
for (m = 0; m < 120; m++)
ledplay();
//温度显示
}
}
}
10。