《单片机原理及应用》课程设计实验报告学年学期:2014-2015第1学期专业班级:12级自动化B指导教师:徐敏、关健生设计时间:第17周学时周数:每班/周一、设计目的(基于ds18b20的数字温度计设计)课程设计是单片机课程教学的最后一个环节,是对学生进行全面的系统的训练,让学生把学过的比较零碎的知识系统化,真正的能够把学过的知识落到实处,能够开发简单的系统,也进一步激发了学生再深一步学习的热情,进一步掌握和利用C语言进行单片机程序设计的能力,熟练掌握键盘、显示、单总线,温度传感器DS18B20等知识点。二、设计任务及要求本课程设计的题目设计内容自选,学生可以根据平时的观察,了解单片机实验的应用系统,弄清其结构和功能,结合单片机课程及其相关的知识,充分发挥自身的想象力和创造力,自行选定设计项目,但总体应达到以下要求:1、用89C51CPU,12M时钟,常规的上电和手动复位电路2、包括3×4矩阵键盘3、LCD显示显示器及接口4、一路蜂鸣器输出5.至少有1路输入信号,可以是模拟量或数字量三、设计项目简介本设计以检测温度并显示温度提供上下限报警为目的,按照系统设计功能的要求,确定系统由5个模块组成:单片机主控器,测温电路,按键电路,显示电路,报警电路。1.单片机模块:主要实现数据的处理,输出执行,报警设置功能以及矩阵键盘的使用。通过从DS18b20读取的温度超过上下限的初始值时候,调用报警程序进行报警。通过按键来改变上下限的初始值;2.温度传感模块:主要功能是通过DS18B20对温度的采集及将测量的温度值读到单片机内,并在LCD1602上显示出来。3.显示模块:可以显示实时的温度值以及设置的上下限。四、电路原理图(1)仿真电路图(2)实际电路图五、系统功能描述1.运用DS18B20将测量温度值读到单片机内,将其在LCD1602上显示出来。2.利用3*4矩阵键盘设定温度值的上下限,并在LCD上显示出来。3.将读进来的温度和设置的上下限值进行比较,若测量温度值超出上下限,就调用报警程序进行报警;若测量温度值在设定范围之内,则不报警。4.当温度变化时,读取温度值并在LCD上显示。六、程序框图(1)系统框图按键输入电路温度检查复位电路STC89C51单片机LCD显示器蜂鸣器电路LCD驱动电路(2)主程序流程图开始初始化读取测量温度值读取按键值键盘处理温度比较处理温度大于上限值?温度小于下限值?温度显示结束蜂鸣器报警YYNN(2)LCD初始化程序框图开始初始化LCD是否忙?写指令数据复位LCD是否忙?写显示数据复位读完数据?结束NNYUYYN(4)温度传感器DS18B20初始化程序框图七、程序清单#includereg51.h#includeintrins.h#defineucharunsignedchar开始初始化延时复位读取温度显示温度温度值超出上下限范围?结束蜂鸣器报警YN温度转换#defineuintunsignedintucharbuf1;ucharbuf2;ucharbuf3;uchartt;ucharn=0;//键顺序吗uchardis_buf;//显示缓存uchartemp;ucharkey;ucharenter;voiddelay0(ucharx);//x*0.14MSsbitLCD_RW=P2^5;sbitLCD_RS=P2^6;sbitLCD_EN=P2^7;sbitDQ=P3^7;sbitRQ=P1^5;uchardatadisdata[5];uinttvalue;//温度值uchartflag;//温度正负标志ucharcdis1[16]={TEMP:C};ucharcdis2[16]={H:CL:C};ucharcdis3[16];#definedelayNOP();{_nop_();_nop_();_nop_();_nop_();};/*延时子程序*/voiddelay(ucharx){ucharj;while((x--)!=0){for(j=0;j125;j++){;}}}/*检查LCD忙状态*/bitlcd_busy(){bitresult;LCD_RS=0;LCD_RW=1;LCD_EN=1;delayNOP();result=(bit)(P0&0x80);LCD_EN=0;return(result);}/*写指令数据到LCD*/voidlcd_wcmd(ucharcmd){while(lcd_busy());LCD_RS=0;LCD_RW=0;LCD_EN=0;_nop_();_nop_();P0=cmd;delayNOP();LCD_EN=1;delayNOP();LCD_EN=0;}/*写显示数据到LCD*/voidlcd_wdat(uchardat){while(lcd_busy());LCD_RS=1;LCD_RW=0;LCD_EN=0;P0=dat;delayNOP();LCD_EN=1;delayNOP();LCD_EN=0;}/*LCD初始化设定*/voidlcd_init(){delay(15);lcd_wcmd(0x38);//16*2显示,5*7点阵,8位数据delay(5);lcd_wcmd(0x38);delay(5);lcd_wcmd(0x38);delay(5);lcd_wcmd(0x0C);//显示开,关光标delay(5);lcd_wcmd(0x06);//移动光标delay(5);lcd_wcmd(0x01);//清除LCD的显示内容delay(5);}/*设定显示位置*/voidlcd_pos(ucharpos){lcd_wcmd(pos|0x80);//数据指针=80+地址变量}/*键扫描子程序*/voidkeyscan(void){P1=0xF0;//高四位输入行为低电平列为高电平delay(1);temp=P1;//读P1口temp=temp&0xF0;//屏蔽低四位temp=~((temp4)|0xF0);if(temp==1)//p1.4被拉低key=0;elseif(temp==2)//p1.5被拉低key=1;elseif(temp==4)//p1.6被拉低key=2;elseif(temp==8)//p1.7被拉低key=3;P1=0x0F;//低四位输入列为低电平行为高电平delay(1);temp=P1;//读P1口temp=temp&0x0F;temp=~(temp|0xF0);if(temp==2)//p1.1被拉低key=key+0;elseif(temp==4)//p1.2被拉低key=key+4;elseif(temp==8)//p1.3被拉低key=key+8;dis_buf=key;//键值入显示缓存if(dis_buf9)//转换为ASCII码dis_buf=dis_buf+0x37;elsedis_buf=dis_buf+0x30;}/*判断键是否按下*/voidkeydown(void){P1=0xF0;if(P1!=0xF0)//判断按键是否按下如果按钮按下会拉低P1其中的一个端口{delay(10);if(P1!=0xF0){keyscan();P1=0xF0;while(P1!=0xF0);if(dis_buf=='A')enter=1;if(enter==0){if(n==4)n=0;if(dis_buf!='B'){cdis3[n]=dis_buf;n++;}}if(dis_buf=='B')enter=0;}}}/*****ds1820程序*****/voiddelay_18B20(unsignedinti)//延时1微秒{while(i--);}voidds1820rst()/*ds1820复位*/{unsignedcharx=0;DQ=1;//DQ复位delay_18B20(4);//延时DQ=0;//DQ拉低delay_18B20(100);//精确延时大于480usDQ=1;//拉高delay_18B20(40);}uchards1820rd()/*读数据*/{unsignedchari=0;unsignedchardat=0;for(i=8;i0;i--){DQ=0;//给脉冲信号dat=1;DQ=1;//给脉冲信号if(DQ)dat|=0x80;delay_18B20(10);}return(dat);}voidds1820wr(ucharwdata)/*写数据*/{unsignedchari=0;for(i=8;i0;i--){DQ=0;DQ=wdata&0x01;delay_18B20(10);DQ=1;wdata=1;}}read_temp()/*读取温度值并转换*/{uchara,b;ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0x44);//*启动温度转换*/ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0xbe);//*读取温度*/a=ds1820rd();b=ds1820rd();tvalue=b;tvalue=8;tvalue=tvalue|a;if(tvalue0x0fff)tflag=0;else{tvalue=~tvalue+1;tflag=1;}tvalue=tvalue*(0.625);//温度值扩大10倍,精确到1位小数return(tvalue);}voidds1820disp()//温度值显示{ucharflagdat;disdata[0]=tvalue/1000+0x30;//百位数disdata[1]=tvalue%1000/100+0x30;//十位数disdata[2]=tvalue%100/10+0x30;//个位数disdata[3]=tvalue%10+0x30;//小数位if(tflag==0)flagdat=0x20;//正温度不显示符号elseflagdat=0x2d;//负温度显示负号:-if(disdata[0]==0x30){disdata[0]=0x20;//如果百位为0,不显示if(disdata[1]==0x30){disdata[1]=0x20;//如果百位为0,十位为0也不显示}}lcd_pos(5);lcd_wdat(flagdat);//显示符号位lcd_pos(6);lcd_wdat(disdata[1]);//显示十位lcd_pos(7);lcd_wdat(disdata[2]);//显示个位lcd_pos(8);lcd_wdat(0x2e);//显示小数点lcd_pos(9);lcd_wdat(disdata[3]);//显示小数位}/*************蜂鸣器************/voidfengming1(uchartt){if(tt!=1){tt--;RQ=1;delay(1);RQ=0;delay(1);}}voidfengming2(uchartt){if(tt!=1){tt--;RQ=1;delay(100);RQ=0;delay(100);}}/*主程序*/main(){ucharm;enter=0;P0=0xFF;//置P0口P1=0xFF;//置P1口delay(10);//延时lcd_init();//初始化LCDlcd_pos(0);//设置显示位置为第一行的第1个字符m=0;while(cdis1[m]!='\0'){//显示字符lcd_wdat(cdis1[m]);m++;}lcd_pos(0x40);//设置显示位置为第二行第1个字符m=0;while(cdis2[m]!='\0'){lcd_wdat(cdis2[m]);//显示字符m++;}dis_buf=0x2d;//显示字符-while(1){read_temp();//读取温度ds1820disp();//显示keydown();lcd_pos(0x43);for(m=0;m2;m+