远程温度测量分析.docx
《远程温度测量分析.docx》由会员分享,可在线阅读,更多相关《远程温度测量分析.docx(33页珍藏版)》请在冰点文库上搜索。
远程温度测量分析
2015-2016学年第一学期
微机原理(单片机)课程设计
总结报告
项目名称:
远程温度测量
班级:
姓名:
学号:
微机原理(单片机)课程设计任务书
项目名称:
远程温度测量
内容与要求:
上位机:
完成界面设计与通讯程序
(1)能够显示温度值,能够设定报警温度阈值上限、下限,当超出报警温度阈值上限、下限时,温度值后又HIGH或LOW提示字母。
(2)能够发送短信,显示出收信人姓名,收信人电话,当前测得温度值;能够定时发送温度测量情况短信。
(3)每隔1秒将测得的温度值保存至文档中,如超过阈值,温度值后又HIGH或LOW提示字母
(4)可以对串口进行设置
下位机:
完成电路设计与控制程序
(1)采用DS18B20采集温度,采用GSM模块发送短信。
(2)通过串口与上位机通讯,并传输温度值,接受阈值设置。
(3)发送短信成功时,蜂鸣器鸣叫提示。
并将短信内容显示在LCD屏第2行
(4)将当前温度显示在LCD液晶屏上,当超出报警温度阈值上限、下限时,温度值后又HIGH或LOW提示字母。
项目组任务分担评价表
姓名
分担任务
组内评价
陈墨
LCD显示模块设计与编程,下位机串口通讯程序,DS18B20模块及单片机下位机编程
5
张新宇
上位机温度显示与设置,上位机串口路通讯程序,上位机文件保存及温度判断程序
5
课程设计报告评分表
内容
总体方案
硬件设计
软件设计
结果分析
明细清单
问题分析
心得体会
参考文献
程序代码
格式规范
总分
陈墨得分
张新宇得分
一、总体方案
远程温度测量总体框图如图1-1所示。
图1-1远程温度测量总体功能模块示意图
图中,温度测量模块是利用DS18B20进行温度的测量和采集,并直接传递给控制器51单片机。
同时控制器也可以控制温度测量模块的状态。
LCD模块可以显示由控制器得到的温度值,并根据上位机给出的阈值上下限显示出HIGH或者LOW。
上位机不但可以通过串口改变控制器参数,而且可以利用GSM模块直接发送短信。
同时下位机控制器也可以命令GSM模块发送短信。
上位机还可以将温度值和是否超过阈值情况打印在txt文档中。
二、硬件设计
本项目下位机控制器采用的是51系列单片机STC80C52RC型号。
其内置8位中央处理单元、256字节内部数据存储器RAM、8k片内程序存储器(ROM)32个双向输入/输出(I/O)口、3个16位定时/计数器和5个两级中断结构,一个全双工串行通信口,片内时钟振荡电路,属于80C51增强型单片机版本。
其价格低廉,低功耗,基本符合经济、环保需求。
本项目温度测量传感器采用的DS18B20。
DS18B20是常用的温度传感器,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。
三个引脚中间为温度传输接口,其余两个分别为VCC和地。
本项目LCD显示模块采用LCD1602液晶屏,它由若干个5X7点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用。
其成本低廉,字符显示效果好,经济效果好。
本项目硬件电路连接图如图2-1所示。
图2-1硬件电路连接图
温度模块的DS18B20中间的2号引脚接单片机P32,1接地3接VCC。
LCD1602直接插在扩展插针接口即可,即1接地,2接VCC,3接地(带保护电阻),7-14依次接P0-P7,15接VCC,16接地,其余悬空。
具体接线如图2-1所示。
三、软件设计
本项目下位机采用51单片机做控制器。
由DS18B20得到温度数据后,传递给51单片机,然后单片机根据得到的数据,在LCD液晶屏上显示出相应的数值和符号。
同时,上位机和下位机进行串口通信,上位机改变下位机参数设定,下位机的温度数据也传递到上位机。
(1)主程序流程图如3-1所示。
图3-1主程序流程图
(2)读取温度值模块流程图如图3-2所示。
图3-2读取温度值模块流程图
本项目串行通信采用的波特率为19200,串口采用方式2的工作方式,其计算公式如下:
波特率=(2SMOD/32)*(T1溢出率)
考虑电源管理寄存器PCON,取PCON为0x80,所以波特率加倍,令TH1=0xFD,最终得到波特率为19200.
四、结果分析或项目所实现的功能、指标
本项目可实现温度测量功能,可以在LCD液晶屏和上位机上同时显示温度值。
同时还具有远程阈值上下限设置功能,可以在上位机设置温度阈值上下限,超过上限上下位机同时会有HIGH的显示,低于下限上下位机也同时又LOW的显示。
如图4-1和图4-2所示,测量温度值为25.7度,高于温度上限0度,则上位机和下位机都会显示HIGH字样。
(由于拍照时间差会导致温度有微小变化)
图4-1上位机显示结果
(1)
图4-2下位机显示结果
(1)
当温度低于温度下限时,如图4-3和4-4所示,上位机和下位机都会显示LOW字样。
图4-3上位机显示结果
(2)
图4-4下位机显示结果
(2)
当温度在设置的温度阈值上下限之间时,下位机只显示温度,上位机会显示NORMAL,证明温度正常。
五、明细清单
明细及价格清单如表5-1所示
序号
名称
型号/规格
数量
价格(元)
1
单片机最小系统板
STC89C52RC
1
70
2
温度传感器
DS18B20
1
1
3
液晶显示屏
LCD1602
1
3
4
GSM模块
GTM900
1
110
表5-1明细及价格清单
价格总计70+1+3+110=184(元)。
六、设计调试中遇到的疑难问题及解决方法
张新宇:
1、Labview将温度保存在txt文件中,文件名义一定要和Labview程序里面的txt文件命名一致,否则不但不能实现存储其他功能也会出现错误。
2、Labview即使内有Visa模板,但是也必须安装Visa驱动才能正常使用,不安装该驱动串口永远无法读取。
3、Labview不能将主体时序调的太慢,由于是串口通信,太慢会出现错误,“等待下一个整数倍毫秒”函数毫秒倍数设置为10~100为宜。
陈墨:
1、电源管理寄存器PCON最高位为1时波特率要乘2,所以设置TH1为0xFD波特率才为19200。
2、DS18B20要考虑好延时,以保证温度读取完成,避免温度读取失败。
3、温度低于0度时是要将数值取反加1,转换成补码。
七、心得体会与建议
备注:
正式成稿时,删除此备注。
每位小组成员需分别说明对知识的深度认识,和学习方法的总结;对项目的进一步展望,可作哪些方面的改进;对老师教学有哪些建议。
如:
张新宇:
本次课设我学习了之前从未用过的Labview软件,了解了该如何用Labview进行串口通讯,以及制作一个上位机程序。
它独特的图形编程方法让我受益颇多。
软件中的帮助功能也非常强大,往往根本不需要上网搜索打开帮助查阅即可知道问题出在哪里。
对于本课题希望老师能够将GSM收发短信和温度测量分开,6天时间要完成这两个任务真的压力很大,也希望能够更换GSM模块,华为公司的GTM900B不但已经停产,而且网上资料少,大部分人都采用西门子公司的产品,我想换用西门子公司的产品有助于同学们的学习。
陈墨:
本次课设我结合了上学期所学的51单片机理论知识,第一次完成了一个完整的项目。
我学会了该如何写一个完整的代码,该如何将程序烧进单片机,该如何进行单片机程序的调试。
在课设中我发现了查阅资料的重要性,初始化程序,中断,以及LCD输出程序都可以通过参考资料来完善。
课程建议希望以后能够在理论学习时增加单片机的学习课时,让我们对于单片机有更多的了解和认识,这样才能更科学,更容易地完成本次课设。
参考文献
[1]周月霞,孙传友.DS18B20硬件连接及软件编程[J].传感器世界.2001(12)
[2]农静,郑宗亚,刘志杰.单总线数字温度传感DS18B20原理及应用[J].贵州师范大学学报(自然科学版).2007(03)
[3]易丽华,黄俊.基于AT89C51单片机与DS18B20的温度测量系统[J].电子与封装.2009(05)
[4]周青云,王建勋.基于USB接口与LabVIEW的数据采集系统设计[J].实验室研究与探索.2011(08)
[5]王建勋,周青云.基于DS18B20和LabVIEW的温度监测系统[J].实验室研究与探索.2012(03)
[6]吕向锋,高洪林,马亮,王新华.基于LabVIEW串口通信的研究[J].国外电子测量技术.2009(12)
附录A.下位机程序
#include"Reg52.H"//调用MCS51寄存器头文件
#include"intrins.H"
#include"LCD1602.H"
#include"DS18B20B.H"
#include"stdio.h"
#include
#defineucharunsignedchar
#defineuintunsignedint
#defineSKIP_ROM_COMMAND0xCC//跳过ROM匹配操作
#defineCONVERT_TEMPERATURE0x44//启动温度转换
#defineREAD_SCRATCHPAD0xBE//读温度中间暂存寄存器
#defineN45872//N=50ms/1.09us
UINT8PresencePlusA;//DS18B20A应答脉冲
/*定义引脚
单片机DS18B20
P16DQA
*/
sbitDQA=P3^2;//定义DS18B20A数据线
longVoltage_value;
inty=0,z=0;
ucharflag,b,t_cnt;
floata[4];
intt,z;
union{
intt;
ucharc[2];
}temp2;
floatTemp1,aa=30,bb=26;
uchartt[2];
ucharrxbuf[5];
ucharrbi=0;
uintTTT;
/*初始化DS18B20A.*/
voidDS18B20A_Init(void)
{
DQA=0;//MCU产生复位信号
DelayUs(130);//低电平至少保持480Us
DelayUs(130);
DQA=1;//MCU释放信号线
DelayUs(40);//延时15-60us,等待DS18B20A应答,为了保证准确,最好在60US以后再采集数据
PresencePlusA=DQA;//接收应答,返回0为成功,1为失败
DelayUs(30);//延时
}
/*向DS18B20A发送一个字节数据.*/
voidDS18B20A_WiteData(UINT8mByte)
{
UINT8i;
for(i=0;i<8;i++)
{
DQA=0;//MCU拉低信号线,启动传输
DQA=mByte&0x01;//发送数据到信号线上
DelayUs(50);//延时至少大于60us,小于120us
DQA=1;//MCU释放信号线
mByte>>=1;//数据右移一位
}
DelayUs(10);//连续写的话,稍微延时
}
/*从DS18B20读取数据,返回读取到的数据*/
UINT8DS18B20A_ReadData(void)
{
UINT8i;
UINT8Data=0;
for(i=0;i<8;i++)
{
DQA=0;//MCU拉低信号线,启动传输,低电平需大于1us
Data>>=1;//数据右移一位
DQA=1;//MCU释放信号线
if(DQA==1)//单片机读取信号线上数据,需要在15US以内采集完
{
Data|=0x80;
}
DelayUs(40);//延时45us
}
return(Data);//返回读取到的数据
}
/*DS18B20A温度转换.返回UINT16Temp:
返回读出的温度.*/
UINT16TemperatureA_Conversion()
{
UINT8HighByte;
UINT8LowByte;
UINT16Temp;//温度
DS18B20A_Init();//初始化DS18B20A
if(PresencePlusA==0)
{
DS18B20A_WiteData(SKIP_ROM_COMMAND);//跳过ROM匹配操作
DS18B20A_WiteData(CONVERT_TEMPERATURE);//启动温度转换
}
while(!
DS18B20A_ReadData());//等待转换完成
DS18B20A_Init();//再次初始化DS18B20A
if(PresencePlusA==0)
{
DS18B20A_WiteData(SKIP_ROM_COMMAND);//跳过ROM匹配操作
DS18B20A_WiteData(READ_SCRATCHPAD);//读取温度
}
LowByte=DS18B20A_ReadData();
HighByte=DS18B20A_ReadData();
Temp=((UINT16)HighByte<<8)|LowByte;//计算温度
returnTemp;//返回读出的温度
}
/*串口部分声明*/
voidUart_init(void);
voidSend_data(void);
unsignedintSenData;//用来存接收与发送的值
voidchange(floatx);
/*串口程序发送*/
voidSend_data(void)
{
SBUF=SenData;//SUBF接受/发送缓冲器
while(TI==0);
TI=0;
}
/*串口初始化*/
voidUart_init(void)//串口初始化
{
SCON=0x50;//REN=1允许串行接受状态,串口工作模式1
TMOD|=0x20;//定时器工作方式2
PCON|=0x80;
TH1=0xFD;//baud*2reloadvalue19200、数据位8、停止位1。
效验位无(11.0592)
TL1=0xF3;
TR1=1;
ES=1;//开串口中断
EA=1;//开总中断
//IE=0x0;
}
voiduartSend(uchars[]){
uchari;
for(i=0;i<2;i++){
SBUF=s[i];
while(!
TI);
TI=0;
}
}
/*主函数*/
voidmain(void)
{
UINT8DisplayBuf[16];//存储转换后的温度数据
intTemp0;
UINT8MinusTempFlag=0;//负数温度标志
/*timer0*/
TMOD=0x21;
TH0=(65536-N)/256;
TL0=(65536-N)%256;
ET0=1;
TR0=1;
t_cnt=0;
/*uart*/
TMOD=0x20;
TH1=0xFD;//波特率19200
TL1=0xFD;
TR1=1;
SM0=0;
SM1=1;
REN=1;
ES=1;
/*******************/
DelayMs(200);//上电延时
LCD1602_Init();
DelayMs(200);
LCD1602_WriteUSerCode();//写入用户自定义字符
DQA=1;
LCD1602_SetDisplayPosition(0,1);//显示显示位置
LCD1602_WriteString("YQ516BoardV2.2");//显示字符
DelayMs(2000);
Uart_init();
while
(1)
{
Temp0=TemperatureA_Conversion();//DB18B20A温度转换并显示
temp2.t=Temp0;
if(Temp0&0x8000)//如果温度为负数
{
MinusTempFlag=1;
Temp0=~Temp0;//取反
Temp0+=1;//取反后加1
}
else
{
MinusTempFlag=0;
}
Temp1=(float)Temp0*0.0625;//计算温度
if(MinusTempFlag)//如果是负温度
{
sprintf(DisplayBuf,"-%7.3f",Temp1);//将Temp1的数据打印到DisplayBuf中,浮点数,7位,3位小数点
}
else
{
sprintf(DisplayBuf,"%7.3f",Temp1);//将Temp1的数据打印到DisplayBuf中,浮点数,7位,3位小数点
}
LCD1602_SetDisplayPosition(0,1);//显示显示位置
LCD1602_WriteString(DisplayBuf);//显示温度
LCD1602_SetDisplayPosition(9,1);//设置自定义字符位置
LCD1602_WriteData(0x00);//写入温度左上角点
LCD1602_SetDisplayPosition(10,1);
LCD1602_WriteData('C');//写入温度C
if(Temp1>aa)
{LCD1602_SetDisplayPosition(12,1);
LCD1602_WriteData('H');
LCD1602_SetDisplayPosition(13,1);
LCD1602_WriteData('I');
LCD1602_SetDisplayPosition(14,1);
LCD1602_WriteData('G');
LCD1602_SetDisplayPosition(15,1);
LCD1602_WriteData('H');
}
if(Temp1{
LCD1602_SetDisplayPosition(12,1);
LCD1602_WriteData('L');
LCD1602_SetDisplayPosition(13,1);
LCD1602_WriteData('O');
LCD1602_SetDisplayPosition(14,1);
LCD1602_WriteData('W');
LCD1602_SetDisplayPosition(15,1);
LCD1602_WriteData('');
}
if((Temp1>bb)&&(Temp1{
LCD1602_SetDisplayPosition(12,1);
LCD1602_WriteData('');
LCD1602_SetDisplayPosition(13,1);
LCD1602_WriteData('');
LCD1602_SetDisplayPosition(14,1);
LCD1602_WriteData('');
LCD1602_SetDisplayPosition(15,1);
LCD1602_WriteData('');
}
t=(int)Temp1;
}
}
voidT0_time()interrupt1
{
TH0=(65536-45872)/256;
TL0=(65536-45872)%256;
t_cnt++;
if(t_cnt==20){
//TTT=(uint)Temp1;
//tt[0]=(uchar)temp2;
//tt[1]=(uchar)(TTT&0x0F);
uartSend(temp2.c);
t_cnt=0;
}
}/*主函数结束*/
/*中断4*/
voidserial()interrupt4
{
if(RI){
rxbuf[rbi]=SBUF;
RI=0;
rbi++;
if(rxbuf[0]!
=0xff)rbi=0;
elseif(rbi==5){
bb=(rxbuf[1]*255+rxbuf[2])/100;
aa=(rxbuf[3]*255+rxbuf[4])/100;
rbi=0;
}
}elseTI=0;
}
/*LCD1602接口子程序.*/
#include"reg52.h"//调用头文件,单片机内部寄存器都定义在此,用的时候需要先调用
typedefunsignedcharUINT8;//给unsignedchar重新定义一个别名UINT8,用的时候直接写UINT8就可以
typedefunsignedintUINT16;//给unsignedint重新定义一个别名UINT16,用的时候直接写UINT16就可以
/*引脚定义
单片机LCD1602
P24RS
P25RW
P26EN
P0D0-D7
*/
sbitLCD_RS=P1^0;//数据、指令选择信号
sbitLCD_RW=P1^1;//读写选择信号
sbitLCD_EN=P1^2;//读写使能信号
#defineDATA_PORTP0//数据端口
/*
1.RS=1为数据操作;
RS=0为写指令或读状态.
2.RW=1为读选通;
RW=0为写选通.
3.在EN下降沿,数据被锁存到LCD1602,在EN高电平期间,数据被读出.
4.D0-D7,数据总线.
*/
/*命令码*/