单片机原理及系统课程设计专业:电气工程及其自动化班级:电气1101姓名:学号:指导教师:兰州交通大学自动化与电气工程学院2014 年 1 月 17 日1设计题目基于单片机的数字温度计设计。
2设计方案2.1设计目的单片机是单片微型计算机的简称,其具有体积小、可靠性高、功能强、灵活方便等优点,故可以广泛应用于各种领域。
其中数字温度计就是一个典型的例子。
本设计所介绍的数字温度计与传统的温度计相比,具有读数方便,测温范围广,测温准确等特点,其输出温度采用数字显示,主要用于对测温要求较高的场所,该设计主要使用的元件有单片机AT89C52,测温传感器使用DS18B20和LCD1602液晶显示器。
2.2性能指标(1) 基本范围-50℃-110℃;(2) 精度为0.5℃;(3) 液晶LCD显示;(4) 可以设定温度的上下限以及报警功能。
3数字温度计系统的硬件设计3.1数字温度计硬件框图数字温度计系统硬件框图如图1所示。
图1 系统的硬件框图3.2AT89C52单片机AT89C52单片机引脚配置图,如图2所示。
图2 AT89C52引脚配置图3.3外围电路AT89C52的时序就是CPU在执行指令时所需控制信号的时间顺序。
选择了内部时钟方式,即利用芯片内部的振荡器,然后在引脚XTAL1和XTAL两端跨接晶体或陶瓷谐振器,就构成了稳定的自激振荡器,其发出的脉冲直接送入内部时钟电路。
外接晶振时,C1和C2值通常选择为30PF左右。
C1和C2对频率有微调作用。
晶体的频率范围可在1.2~12MHZ之间选择。
AT89C52的复位电路是按键电平复位电路,相当于按复位键后复位端通过电阻与Vcc电源接通。
复位是单片机的初始化操作。
单片机在启动运行时,都需要先复位,其作用是使CPU和系统中其他部件都处于一个确定的初始状态,并从这个状态开始工作。
显示电路采用LCD1602液晶显示器显示。
故障状态指示电路采用发光二级管以及蜂鸣器对运行方式进行指示,可清楚看到系统的故障状态。
测温传感器DS18B20可以直接读出被测温度值,采用三线制和单片机相连,少了外部的硬件电路,具有低成本和易使用的特点。
3.4 总设计图数字温度计系统的硬件总设计图如图3所示。
图3 总设计图4 数字温度计系统的软件设计及系统整体流程整个系统的功能是由硬件电路配合软件来实现的,从软件的功能不同,可以分为两类:主程序和子程序。
主程序是整个软件的核心,专门用来协调各个执行模块和操作者的联系。
子程序是用来完成各种实质性的工作的,如读温度子程序、转换温度子程序、计算温度子程序等。
各执行模块规划好以后,就可以规划监控软件了。
首先要根据系统的总体功能选择一种最合适的主程序结构,然后根据实时性的条件,合理安排监控软件和执行软件之间的调度关系。
4.1总体流程图数字温度计系统总体流程图如图4所示。
图4主流序流程图4.2 子程序流程图数字温度计系统子程序主要包含:读温度子程序、转换温度子程序、计算温度子程序。
(1)读温度子程序流程图读温度子程序流程图如图5所示。
图5 读温度子程序流程图(2)转换温度子程序流程图转换温度子程序流程图如图6所示。
图6 转换温度子程序流程图(3)计算温度子程序流程图计算温度子程序流程图如图7所示。
图7 计算温度子程序流程图5 仿真结果(1) 正常温度显示温度计正常温度显示如图8所示。
p 27p 26p 25p 24p 23p 22p 21p 20p 30D 714D 613D 512D 411D 310D 29D 18D 07E 6R W 5R S 4V S S 1V D D 2V E E3LCD1LM016LD1LED-GREENp 27p 26p 25p 24p 23p 22p 21p 20p 30D 714D 613D 512D 411D 310D 29D 18D 07E 6R W 5R S 4V S S 1V D D 2V E E3LCD1LM016LD1LED-GREEN参考文献1.王思明. 单片机原理及应用系统设计[M]. 北京:科学出版社, 2012.2.李广弟. 单片机基础[M]. 北京:北京航空航天大学出版社, 1994.3.艾德才. pentium/80486实用汇编语言程序设计[M]. 北京:清华大学出版社, 1997.附录源程序//使用1602LCD显示DS18B20转换的温度值#include <reg52.H>#include <intrins.H>#include <math.H>#define uchar unsigned char#define uint unsigned intsbit RS = P3^0; //数据/命令选择端(H/L)sbit LCDEN = P3^2; //使能端sbit deng=P1^6; //超过温度限制指示灯sbit beep=P1^7; //超过温度限制报警器uchar high=30; //最高温度uchar low=10; //最低温度unsigned char r;void delayUs() //短延时{_nop_();}void delayMs(uint a) //长延时{uint i, j;for(i = a; i > 0; i--)for(j = 100; j > 0; j--);}//第一行开始地址为0x80, 第二行开始地址为0xc0;//写命令:RS=0, RW=0;void writeComm(uchar comm){RS = 0;P2 = comm;LCDEN = 1;delayUs();LCDEN = 0;delayMs(1);}//写数据:RS=1, RW=00void writeData(uchar dat){RS = 1;P2 = dat;LCDEN = 1;delayUs();LCDEN = 0;delayMs(1);}//初始化函数//显示模式, 固定指令为00111000=0x38, 16*2显示, 5*7点阵,8位数据接口//显示开/关及光标设置00001100=0x0c//指令1: 00001DCB : D:开显示/关显示(H/L); C:显示光标/不显示(H/L), B:光标闪烁/不闪烁(H/L)//指令2: 000001NS ://N=1, 当读/写一个字符后地址指针加1, 且光标也加1; N=0则相反//S=1, 当写一个字符, 整屏显示左移(N=1)或右移(N=0), 但光标不移动; S=0, 整屏不移动void init(){writeComm(0x38); //显示模式writeComm(0x0c); //开显示, 关光标writeComm(0x06); //写字符后地址加1, 光标加1writeComm(0x01); //清屏}void writeString(uchar * str, uchar length){uchar i;for(i = 0; i < length; i++){writeData(str[i]);}}/*****************************DS18B20*******************************/sbit ds = P3^7;//初始化DS18B20//让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动void dsInit(){//对于11.0592MHz时钟, unsigned int型的i, 作一个i++操作的时间大于为8us unsigned int i;ds = 0;i = 100; //拉低约800us, 符合协议要求的480us以上while(i>0) i--;ds = 1; //产生一个上升沿, 进入等待应答状态i = 4;while(i>0) i--;}void dsWait(){unsigned int i;while(ds);while(~ds); //检测到应答脉冲i = 4;while(i > 0) i--;}//向DS18B20读取一位数据//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平,//之后DS18B20则会输出持续一段时间的一位数据bit readBit(){unsigned int i;bit b;ds = 0;i++; //延时约8us, 符合协议要求至少保持1usds = 1;i++; i++; //延时约16us, 符合协议要求的至少延时15us以上b = ds;i = 8;while(i>0) i--; //延时约64us, 符合读时隙不低于60us要求return b;}//读取一字节数据, 通过调用readBit()来实现unsigned char readByte(){unsigned int i;unsigned char j, dat;dat = 0;for(i=0; i<8; i++){j = readBit();//最先读出的是最低位数据dat = (j << 7) | (dat >> 1);}return dat;}//向DS18B20写入一字节数据void writeByte(unsigned char dat){unsigned int i;unsigned char j;bit b;for(j = 0; j < 8; j++){b = dat & 0x01;dat >>= 1;//写"1", 将DQ拉低15us后, 在15us~60us内将DQ拉高, 即完成写1if(b){ds = 0;i++; i++; //拉低约16us, 符号要求15~60us内ds = 1;i = 8; while(i>0) i--; //延时约64us, 符合写时隙不低于60us要求}else //写"0", 将DQ拉低60us~120us{ds = 0;i = 8; while(i>0) i--; //拉低约64us, 符号要求ds = 1;i++; i++; //整个写0时隙过程已经超过60us, 这里就不用像写1那样, 再延时64us了}}}//向DS18B20发送温度转换命令void sendChangeCmd(){dsInit(); //初始化DS18B20, 无论什么命令, 首先都要发起初始化dsWait(); //等待DS18B20应答delayMs(1); //延时1ms, 因为DS18B20会拉低DQ 60~240us作为应答信号writeByte(0xcc); //写入跳过序列号命令字Skip RomwriteByte(0x44); //写入温度转换命令字Convert T}//向DS18B20发送读取数据命令void sendReadCmd(){dsInit();dsWait();delayMs(1);writeByte(0xcc); //写入跳过序列号命令字Skip RomwriteByte(0xbe); //写入读取数据令字Read Scratchpad}//获取当前温度值int getTmpValue(){unsigned int tmpvalue;int value; //存放温度数值float t;unsigned char low, high;sendReadCmd();//连续读取两个字节数据low = readByte();high = readByte();//将高低两个字节合成一个整形变量//计算机中对于负数是利用补码来表示的//若是负值, 读取出来的数值是用补码表示的, 可直接赋值给int型的valuetmpvalue = high;tmpvalue <<= 8;tmpvalue |= low;value = tmpvalue;//使用DS18B20的默认分辨率12位, 精确度为0.0625度, 即读回数据的最低位代表0.0625度t = value * 0.0625;//将它放大10倍, 使显示时可显示小数点后一位, 并对小数点后第二位进行4舍5入//如t=11.0625, 进行计数后, 得到value = 111, 即11.1 度//如t=-11.0625, 进行计数后, 得到value = -111, 即-11.1 度value = t * 10 + (value > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5return value;}//显示温度void display(int v){unsigned char count;unsigned char datas[] = {0, 0, 0, 0};unsigned int tmp = abs(v);datas[0] = tmp / 1000;datas[1] = tmp % 1000 / 100;datas[2] = tmp % 100 / 10;datas[3] = tmp % 10;r= tmp/10;writeComm(0xc0+3);if(v < 0){writeString("- ", 2);}else{writeString("+ ", 2);}if(datas[0] != 0){writeData('0'+datas[0]);}for(count = 1; count != 4; count++){writeData('0'+datas[count]);if(count == 2){writeData('.');}}}/******************************报警*******************************/ void BEEP()//报警{if((r>=high&&r<129)||r<low){beep=!beep;deng=1;}else{beep=1;deng=0;}}/******************************DS18B20*******************************/void main(){uchar table[] = "Now Temperature ";delayMs(1);sendChangeCmd();init();writeComm(0x80);writeString(table, 16);while(1){delayMs(1000); //温度转换时间需要750ms以上writeComm(0xc0);display(getTmpValue());sendChangeCmd();BEEP();}}。