基于51单片机温度检测LCD显示课程设计报告
- 格式:doc
- 大小:358.00 KB
- 文档页数:22
大连民族学院单片机系统课程设计题目:温度计的设计班级:电子105姓名:赵萌同组人:张瑛笛指导教师:李绍民设计日期:一 设计内容及要求设计内容:基于单片机的室内温度检测LCD 显示 要求:测量温度 55℃—125℃温度上下限 TH:32℃ TL:16℃温度报警:超出温度上下限BEEP 报警 二 设计方案测温部分:采用18B20作为温度传感器,有一个由高低电平触发的且不因掉电而丢失的报警功能。
控制部分:89S52最小系统显示部分:1602液晶显示,模块内的字符发生存储器存储了160个不同的点阵图形,先是方便,同时好可以进行时间的显示。
三 硬件系统设计电源时钟晶振原理图AT89S52是一个低功耗,高性能CMOS 8位单片机,片内含8k Bytes ISP(In-systemprogrammable)的可反复擦写1000次的Flash 只读程序存储器,器件采用ATMEL 公司的高密度、非易失性存储技术制造,兼容标准MCS -51指令系统及80C51引脚结构,芯片内集成了通用8位中央处理器和ISP Flash 存储单元,功能强大的微型计算机的AT89S52可为许多嵌入式控制应用系统提供高性价比的解决方案。
AT89S52具有如下特点:40个引脚,8k Bytes Flash 片内程序存储器,256 bytes 的随机存取数据存储器(RAM ),32个外部双向输入/输出(I/O )口,5个中断优先级2层中断嵌套中断,2个16位可编程定时计数器,2个 全双工串行通信口,看门狗(WDT )电路,片内时钟振荡器。
I/O接口外围电路工作原理及硬件图四软件系统设计软件流程框图五 仿真调试(1)Keil C51单片机软件开发系统的整体结构C51工具包的整体结构,uVision 与Ishell 分别是C51 for Windows 和for Dos 的集成开发环境(IDE),可以完成编辑、编译、连接、调试、仿真等整个开发流程。
开发人员可用IDE 本身或其系统设计原理:本次课程设计是基于单片机的数字温度计设计,在开始课程设计的时候我们要理解并掌握对单片机的开发,学会使用KEIL 及Proteus 等仿真软件。
根据设计任务要求选择好器件,编写好程序运行成功之后进行软件联调,验证系统是否正确。
通过筛选,我们组选用单片机AT89S52作为主控制系统;用1602液晶显示模块芯片作为温度数据显示装置;智能温度传感器采用DS18B20器件作为测温电路主要组成部分。
它编辑器编辑C或汇编源文件。
然后分别由C51及C51编译器编译生成目标文件(.OBJ)。
目标文件可由LIB51创建生成库文件,也可以与库文件一起经L51连接定位生成绝对目标文件(.ABS)。
ABS文件由OH51转换成标准的Hex文件,以供调试器dScope51或tScope51使用进行源代码级调试,也可由仿真器使用直接对目标板进行调试,也可以直接写入程序存贮器如EPROM中。
(2)使用独立的Keil仿真器时,注意事项●仿真器标配11.0592MHz的晶振,但用户可以在仿真器上的晶振插孔中换插其他频率的晶振。
●仿真器上的复位按钮只复位仿真芯片,不复位目标系统。
●仿真芯片的31脚(/EA)已接至高电平,所以仿真时只能使用片内ROM,不能使用片外ROM;但仿真器外引插针中的31脚并不与仿真芯片的31脚相连,故该仿真器仍可插入到扩展有外部ROM(其CPU的/EA引脚接至低电平)的目标系统中使用。
●调试结果●(3)结果分析在运行仿真结果时通过改变温度传感器DS18B20的温度,然后调用各种子函数,可以改变液晶显示1602的第二行显示数据,说明程序编写正确。
(4)系统设计电路的特点和方案的优缺点我们组设计的数字温度计系统知识运用简单的AT89S52芯片的I/O口传输功能,通过几个小的读数据、传递数据、延时子函数实现温度的读取传输功能,是比较简单,容易实现的,所以我们的系统只是实现了一些简单的功能,系统整体来说比较简易,但好像这个温度计没有多大的应用价值,所以我们后续分析觉得这个系统可以加一个温度复位系统提高AT89S52芯片的功能价值,也提高数字温度计的智能价值,还可以增加一个报警子函数,实现智能数字温度计更高的应用价值。
六结论虽然基本功能已经做好了,但还可以有很多的扩展功能,如串口设计和时钟显示,由于时间有限,但对于单片机的设计还在继续…参考文献附录一程序代码:#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intsbit DQ = P2^2; //定义DS18B20端口DQsbit BEEP=P2^3 ; //蜂鸣器驱动线bit presence,flag;bit compare_th,compare_tl,alarm_on_off=0,temp_th,temp_tl;sbit LCD_RS = P3^5;sbit LCD_RW = P3^6;sbit LCD_EN = P3^4;uchar code cdis1[ ] = {" READ_ROMCORD "};uchar code cdis2[ ] = {" "};uchar code cdis3[ ] = {" DS18B20 ERR0R "};uchar code cdis4[ ] = {" PLEASE CHECK "};uchar code cdis5[ ] = {" TEMP: "};uchar code cdis6[ ] = {"TH: TL: "};unsigned char data temp_data[2] = {0x00,0x00};unsigned char data temp_alarm[2] = {0x20,0x10};unsigned char data display[5] = {0x00,0x00,0x00,0x00,0x00}; //温度值显示unsigned char data display1[3] = {0x00,0x00,0x00}; //温度报警值显示unsigned char data RomCode[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; unsigned char code mytab1[8] = {0x0C,0x12,0x12,0x0C,0x00,0x00,0x00,0x00};#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};unsigned char Temp,temp_comp,timecount,count;unsigned char crc;void Disp_Temp_alarm(uchar addr,uchar num);void spk(uchar addr);void set_temp_alarm();void temp_compare();void beep();/*******************************************************************/ void delay1(int ms){unsigned char y;while(ms--){for(y = 0; y<250; y++){_nop_();_nop_();_nop_();_nop_();}}}/******************************************************************/ /* */ /*检查LCD忙状态*/ /*lcd_busy为1时,忙,等待。
lcd-busy为0时,闲,可写指令与数据。
*/ /* */ /******************************************************************/ bit lcd_busy(){bit result;LCD_RS = 0;LCD_RW = 1;LCD_EN = 1;delayNOP();result = (bit)(P0&0x80);LCD_EN = 0;return(result);}/*******************************************************************/ /* */ /*写指令数据到LCD *//*RS=L,RW=L,E=高脉冲,D0-D7=指令码。
*/ /* */ /*******************************************************************/ void lcd_wcmd(uchar cmd){delay1(10);LCD_RS = 0;LCD_RW = 0;LCD_EN = 0;_nop_();_nop_();P0 = cmd;delayNOP();LCD_EN = 1;delayNOP();LCD_EN = 0;}/*******************************************************************/ /* */ /*写显示数据到LCD *//*RS=H,RW=L,E=高脉冲,D0-D7=数据。
*/ /* */ /*******************************************************************/ void lcd_wdat(uchar dat){delay1(10);LCD_RS = 1;LCD_RW = 0;LCD_EN = 0;P0 = dat;delayNOP();LCD_EN = 1;delayNOP();LCD_EN = 0;}/*******************************************************************/ /* */ /*自定义字符写入CGRAM *//* */ /*******************************************************************/ void writetab(){unsigned char i;lcd_wcmd(0x40); //写CGRAMfor (i = 0; i< 8; i++)lcd_wdat(mytab1[i]);for (i = 0; i< 8; i++)lcd_wdat(mytab2[i]);}/*******************************************************************/ /* */ /* LCD初始化设定*//* */ /*******************************************************************/ void lcd_init(){delay1(15);lcd_wcmd(0x01); //清除LCD的显示内容lcd_wcmd(0x38); //16*2显示,5*7点阵,8位数据delay1(5);lcd_wcmd(0x38);delay1(5);lcd_wcmd(0x38);delay1(5);lcd_wcmd(0x0c); //显示开,关光标delay1(5);lcd_wcmd(0x06); //移动光标delay1(5);lcd_wcmd(0x01); //清除LCD的显示内容delay1(5);writetab(); //自定义字符写入CGRAM}/*******************************************************************/ /* */ /* 设定显示位置*/ /* */ /*******************************************************************/ void lcd_pos(uchar pos){lcd_wcmd(pos | 0x80); //数据指针=80+地址变量}/*******************************************************************/ /* */ /*us级延时函数*/ /* */ /*******************************************************************/ void Delay(unsigned int num){while( --num );}/*******************************************************************/ /* */ /*初始化ds1820 */ /* */ /*******************************************************************/ Init_DS18B20(void){DQ = 1; //DQ复位Delay(8); //稍做延时DQ = 0; //单片机将DQ拉低Delay(90); //精确延时大于480usDQ = 1; //拉高总线Delay(8);presence = DQ; //如果=0则初始化成功=1则初始化失败Delay(100);DQ = 1;return(presence); //返回信号,0=presence,1= no presence}/*******************************************************************/ /* */ /* 读一个字节*/ /* */ /*******************************************************************/ ReadOneChar(void){unsigned char i = 0;unsigned char dat = 0;for (i = 8; i > 0; i--){DQ = 0; // 给脉冲信号dat >>= 1;DQ = 1; // 给脉冲信号if(DQ)dat |= 0x80;Delay(4);}return (dat);}/*******************************************************************/ /* */ /* 写一个字节*/ /* */ /*******************************************************************/ WriteOneChar(unsigned char dat){unsigned char i = 0;for (i = 8; i > 0; i--){DQ = 0;DQ = dat&0x01;Delay(5);DQ = 1;dat>>=1;}}/*******************************************************************/ /* */ /* 温度报警值写入DS18B20 *//* */ /*******************************************************************/ Write_Temperature_alarm(void){Init_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0x4e); //将设定的温度报警值写入DS18B20WriteOneChar(temp_alarm[0]); //写THWriteOneChar(temp_alarm[1]); //写TLWriteOneChar(0x7f); //12位精确度Init_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0x48); //把暂存器里的温度报警值拷贝到EEROM }/*******************************************************************/ /* */ /* 读取64位序列码*/ /* */ /*******************************************************************/ Read_RomCord(void){unsigned char j;Init_DS18B20();WriteOneChar(0x33); // 读序列码的操作for (j = 0; j < 8; j++){RomCode[j] = ReadOneChar() ;}}/*******************************************************************/ /* */ /*DS18B20的CRC8校验程序*//* *//*******************************************************************/ uchar CRC8(){uchar i,x; uchar crcbuff;crc=0;for(x = 0; x <8; x++){crcbuff=RomCode[x];for(i = 0; i < 8; i++){if(((crc ^ crcbuff)&0x01)==0)crc >>= 1;else {crc ^= 0x18; //CRC=X8+X5+X4+1crc >>= 1;crc |= 0x80;}crcbuff >>= 1;}}return crc;}/*******************************************************************/ /* */ /* 数据转换与显示*/ /* */ /*******************************************************************/ Disp_RomCode(uchar H_num){uchar j;if(H_num==1)lcd_pos(0x00);if(H_num==2)lcd_pos(0x40);for(j=0;j<8;j++){Temp = RomCode[j];display[0]=((Temp&0xf0)>>4);if(display[0]>9){ display[0]=display[0]+0x37;}else{display[0]=display[0]+0x30;}lcd_wdat(display[0]); //高位数显示display[1]=(Temp&0x0f);if(display[1]>9){display[1]=display[1]+0x37;}else {display[1]=display[1]+0x30;}lcd_wdat(display[1]); //低位数显示}}/*******************************************************************/ /* */ /* 读取温度*/ /* */ /*******************************************************************/ Read_Temperature(void){uchar i;TR0=0; //关中断,防止读数错误Init_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0x44); //启动温度转换Init_DS18B20();WriteOneChar(0x55); //匹配ROM命令for(i=0;i<8;i++)WriteOneChar(RomCode[i]);WriteOneChar(0xBE); //读取温度寄存器temp_data[0] = ReadOneChar(); //温度低8位temp_data[1] = ReadOneChar(); //温度高8位temp_alarm[0] = ReadOneChar(); //温度报警THtemp_alarm[1] = ReadOneChar(); //温度报警TLtemp_comp=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4);//取温度整数值TR0=1; //开中断}/*******************************************************************//* */ /* 数据转换与温度显示*/ /* */ /*******************************************************************/ Disp_Temperature(){uchar s=0;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];s=1;}display[4]=temp_data[0]&0x0f;display[0]=(display[4]*10/16)+0x30;display[4]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4);display[3]=display[4]/100+0x30;display[1]=display[4]%100;display[2]=display[1]/10+0x30;display[1]=display[1]%10+0x30;if(display[3]==0x30) //高位为0,不显示{display[3]=0x20;if(display[2]==0x30) //次高位为0,不显示display[2]=0x20;}if(s)display[3]=0x2d; //显示负号lcd_pos(0x07);lcd_wdat(display[3]); //百位数显示lcd_wdat(display[2]); //十位数显示lcd_wdat(display[1]); //个位数显示lcd_wdat('.');lcd_wdat(display[0]); //小数位数显示lcd_wdat(0x00); //显示自定义字符lcd_wdat('C'); //显示C}/*******************************************************************/ /* */ /* 蜂鸣器响一声*/ /* */ /*******************************************************************/ void beep(){unsigned char y;for (y=0;y<100;y++){Delay(70);BEEP=!BEEP; //BEEP取反}BEEP=1; //关闭蜂鸣器Delay(25000);}/*******************************************************************/ /* */ /* ROMCORD 显示菜单*//* */ /*******************************************************************/ void RomCode_Menu (){uchar m;lcd_init(); //初始化LCDlcd_pos(0); //设置显示位置为第一行for(m=0;m<16;m++) //显示字符lcd_wdat(cdis1[m]);Read_RomCord(); //读取64位序列码CRC8(); //CRC效验if(crc==0) //CRC效验正确{Disp_RomCode(2); //显示64位序列码}}/*******************************************************************/ /* */ /* DS18B20 ERROR 显示菜单*//* */ /*******************************************************************/ void Error_Menu (){uchar m;lcd_init(); //初始化LCDlcd_pos(0); //设置显示位置为第一行的第1个字符for(m=0;m<16;m++)lcd_wdat(cdis3[m]); //显示字符lcd_pos(0x40); //设置显示位置为第二行第1个字符for(m=0;m<16;m++)lcd_wdat(cdis4[m]); //显示字符}/*******************************************************************/ /* */ /* DS18B20 正常显示菜单*/ /* */ /*******************************************************************/ void Natural_Menu (){uchar m;lcd_init(); //初始化LCDlcd_pos(0); //设置显示位置为第一行的第1个字符for(m=0;m<16;m++)lcd_wdat(cdis5[m]); //显示字符lcd_pos(0x40); //设置显示位置为第二行第1个字符for(m=0;m<16;m++)lcd_wdat(cdis6[m]); //显示字符Read_Temperature();Disp_Temp_alarm(0x43,0); //显示TH值Disp_Temp_alarm(0x4b,1); //显示TL值Disp_Temperature(); //显示实时温度值}/*********************************************************/// 显示报警温度/*********************************************************/void Disp_Temp_alarm(uchar addr,uchar num){ //0=TH,1=TLdisplay1[2]=temp_alarm[num]/100+0x30;display1[0]=temp_alarm[num]%100;display1[1]=display1[0]/10+0x30;display1[0]=display1[0]%10+0x30;if(display1[2]==0x30) //高位为0,不显示{display1[2]=0x20;if(display1[1]==0x30) //次高位为0,不显示display1[1]=0x20;}lcd_pos(addr);lcd_wdat(display1[2]); //百位数显示lcd_wdat(display1[1]); //十位数显示lcd_wdat(display1[0]); //个位数显示}/**********************************************************/ // Time0中断函数/**********************************************************/ void Time0(void) interrupt 1 using 0{TH0=0x4c; //50ms定时TL0=0x00;timecount++;if(timecount>9){timecount=0;flag=~flag;}}/*********************************************************/ // 温度比较函数/*********************************************************/ void temp_compare(){if(temp_comp >= temp_alarm[0]) //比较TH 值{compare_th=1;}else compare_th=0;if(temp_comp < temp_alarm[1]) //比较TL 值{compare_tl=1;}else compare_tl=0;if(compare_th){spk(0x46); //小喇叭闪动if(!alarm_on_off) //静音选择beep();count=temp_alarm[0];}else{lcd_pos(0x46);lcd_wdat(0x20);}if(compare_tl){spk(0x4e); //小喇叭闪动if(!alarm_on_off) //静音选择beep();count=temp_alarm[1];}else{lcd_pos(0x4e);lcd_wdat(0x20);}}/*******************************************************************/ /* */ /* 主函数*/ /* */ /*******************************************************************/ void main(){uchar m;TMOD=0x01; TH0=0x4c; TL0=0x00; //50ms定时EA=1; ET0=1; TR0=1;P0=0;P2&=0x1F;Init_DS18B20();Write_Temperature_alarm(); //设定报警上下限温度值if(presence){Error_Menu ();do{Init_DS18B20();beep();}while(presence);}RomCode_Menu (); //显示RomCodefor(m=0;m<10;m++)Delay(50000);Natural_Menu (); //正常显示界面Delay(50000);while(1){Read_Temperature(); //读取当前温度Delay(50000);Disp_Temperature(); //更新当前温度temp_compare(); //温度上下限比较if(compare_th){Set_tempalarm_Flash(0x43,0); //上限报警}if(compare_tl){Set_tempalarm_Flash(0x4b,1); //下限报警}}//end of while(1)} //end of main()。