STC52单片机控制温度在LCD1602上显示,并且可以控制上下限温度报警,报警提示有灯光和蜂鸣器。开机后有屏幕滚动动态显示,随后进入温度实时监测和上下限设置菜单。并且还有时间显示功能
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include <reg52.H>
- #include <intrins.H>
- #include <math.h>
- #include "eeprom52.h"
- #define uchar unsigned char
- #define uint unsigned int
- uchar a[16]="perchin designed" ;
- uchar b[27]="welcome to the world of mcu";
- uchar dis_time_buf[16]={1,2,3,4,6,7};
- static yemian=0;//(定义变量)
- static unsigned char second,minute,hour;
- static unsigned char day=1;
- unsigned int tcount;
- uchar flat=1;
- uchar WenDuS,WenDuX;//报警的温度和湿度
- bit flag_300ms ;
- uchar TH,TL;
- static zd=1;
- sbit RS = P0^5;
- sbit LCDEN = P0^7;
- sbit rw=P0^6;
- sbit BEEP=P3^6;
- sbit led1=P1^0;
- sbit led2=P1^1;
- sbit K1=P1^2; //菜单
- sbit K2=P1^4; //上
- sbit K3=P1^3; //下
- /*********************************************************
- 500us延时函数
- 晶振:11.0592MHz
- *********************************************************/
- void delay500(void)
- {
- uchar i;
- for(i=230;i>0;i--);
- }
- void delayUs()
- {
- _nop_();
- }
- void delayMs(uint a)
- {
- uint i, j;
- for(i = a; i > 0; i--)
- for(j = 100; j > 0; j--);
- }
- /******************把数据保存到单片机内部eeprom中******************/
- void write_eeprom()
- {
- SectorErase(0x2000);
- byte_write(0x2000, WenDuS);
- byte_write(0x2001, WenDuX);
- byte_write(0x2060, a_a);
- }
- /******************把数据从单片机内部eeprom中读出来*****************/
- void read_eeprom()
- {
- WenDuS = byte_read(0x2000);
- WenDuX = byte_read(0x2001);
- a_a = byte_read(0x2060);
- }
- /**************开机自检eeprom初始化*****************/
- void init_eeprom()
- {
- read_eeprom(); //先读
- if(a_a != 2) //新的单片机初始单片机内问eeprom
- {
- WenDuS = 33;
- WenDuX = 18;
- a_a = 2;
- write_eeprom();
- }
- }
- // lcd配置
- int lcd_bz()//测试LCD忙碌状态
- {
- int result ;
- RS = 0 ;
- rw = 1 ;
- LCDEN = 1 ;
- result = (int)(P2 & 0x80) ;
- LCDEN = 0 ;
- return result ;
- }
- void write_cmd(uchar cmd)// 写指令
- {
- while(lcd_bz()) ;
- RS = 0 ;
- rw = 0 ;
- LCDEN = 0 ;
- P2 = cmd ;
- LCDEN = 1 ;
- LCDEN = 0 ;
- }
- void write_addr(uchar addr)//写地址
- {
- write_cmd(addr|0x80) ;
- }
- void write_byte(uchar dat)//写字节
- {
- while(lcd_bz()) ;
- RS = 1 ;
- rw = 0 ;
- LCDEN = 0 ;
- P2 = dat ;
- LCDEN = 1 ;
- LCDEN = 0 ;
- }
- void lcd_init()// 初始化
- {
- write_cmd(0x38) ;
- delayMs(1);
- write_cmd(0x08) ;
- delayMs(1);
- write_cmd(0x01) ;
- delayMs(1);
- write_cmd(0x06) ;
- delayMs(1);
- write_cmd(0x0c) ;
- delayMs(1);
- }
- void writeComm(uchar comm)
- {
- RS = 0;
- P2 = comm;
- LCDEN = 1;
- delayUs();
- LCDEN = 0;
- delayMs(1);
- }
- //写数据:RS=1, RW=0;
- void writeData(uchar dat)
- {
- RS = 1;
- P2 = dat;
- LCDEN = 1;
- delayUs();
- LCDEN = 0;
- delayMs(1);
- }
- void init()
- {
- rw=0;
- writeComm(0x38);
- writeComm(0x0c);
- writeComm(0x06);
- writeComm(0x01);
- }
- void writeString(uchar * str, uchar length)
- {
- uchar i;
- for(i = 0; i < length; i++)
- {
- writeData(str[i]);
- }
- }
- /**//*****************************DS18B20*******************************/
- sbit ds = P3^7;
- void dsInit()
- {
-
- unsigned int i;
- ds = 0;
- i = 100;
- 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--;
- }
- bit readBit()
- {
- unsigned int i;
- bit b;
- ds = 0;
- i++;
- ds = 1;
- i++; i++;
- b = ds;
- i = 8;
- while(i>0) i--;
- return b;
- }
- 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;
- }
- void writeByte(unsigned char dat)
- {
- unsigned int i;
- unsigned char j;
- bit b;
- for(j = 0; j < 8; j++)
- {
- b = dat & 0x01;
- dat >>= 1;
-
- if(b)
- {
- ds = 0; i++; i++;
- ds = 1;
- i = 8; while(i>0) i--;
- }
- else
- {
- ds = 0;
- i = 8; while(i>0) i--;
- ds = 1;
- i++; i++;
- }
- }
- }
- void sendChangeCmd()
- {
- dsInit();
- dsWait();
- delayMs(1);
- writeByte(0xcc);
- writeByte(0x44);
- }
- void sendReadCmd()
- {
- dsInit();
- dsWait();
- delayMs(1);
- writeByte(0xcc);
- writeByte(0xbe);
- }
- int getTmpValue()
- {
- unsigned int tmpvalue;
- int value;
- float t;
- unsigned char low, high;
- sendReadCmd();
-
- low = readByte();
- high = readByte();
-
- tmpvalue = high;
- tmpvalue <<= 8;
- tmpvalue |= low;
- value = tmpvalue;
-
- \
- t = value * 0.0625;
- \
- value = t * 100 + (value > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5
- return value;
- }
- void display(int v)
- {
- unsigned char count;
- unsigned char datas[] = {0, 0, 0, 0, 0};
- unsigned int tmp = abs(v);
- datas[0] = tmp / 10000;
- datas[1] = tmp % 10000 / 1000;
- datas[2] = tmp % 1000 / 100;
- datas[3] = tmp % 100 / 10;
- datas[4] = 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 != 5; count++)
- {
- writeData('0'+datas[count]);
- if(count == 2)
- {
- writeData('.');
- }
- }
- }
- /**//*****************************DS18B20*******************************/
- //屏幕初始化滚动
- void dis_play()
- {
- uint i;
- uint j;
- writeComm(0x00+0x80);
- for(i=0;i<16;i++)
- {
- writeData(a[i]);
- }
- writeComm(0x40+0x80);
- for(i=0;i<27;i++)
- {
- writeData(b[i]);
- }
- writeComm(0x07); //每写一个数据屏幕就要右移一位,就相对于数据来说就是左移了;
- delayMs(1000) ;
- for(j=0;j<1;j++) //首页动态显示
- {
-
- writeComm(0x00+0x80);
- for(i=0;i<16;i++)
- {
- writeData(a[i]);
- delayMs(500); //如果不加这条延时语句的话滚动会非常快。
- }
- }
- }
- void displaysx(uchar addr, uchar q)//在某一地址上显示一字节
- {
- delayMs(1) ;
- write_addr(addr) ;
- write_byte(q) ;
- delayMs(1) ;
-
- }
- /********************报警程序部分*******************/
- void warn(int t) //报警函数
- {
- int x;
- int j;
- x=t/100;
- if(x>=WenDuS) //检测的温度高于设定温度报警值
-
- {
- for(j=200;j>0;j--)
- {
- BEEP=~BEEP; //输出频率1KHz
- delay500(); //延时500us
- led1=~led1;
- }
- }
-
- if(x<=WenDuX) //检测的温度低于设定的温度值
-
- {
- for(j=200;j>0;j--)
- {
- BEEP=~BEEP; //输出频率1KHz
- delay500(); //延时500us
- led2=~led2;
- }
- }
-
- if( x<WenDuS && x>WenDuX )
- {
- BEEP=1; //停止报警
- led1=0;
- led2=0;
- }
-
-
- }
- ////*****时间********//////////
- void LCD_write_char(uchar X,uchar Y,uchar Wdata)
- {
- uchar address;
- if(Y==0)
- address=0x80+X;//Y=0,表示在第一行显示,地址基数为0x80
- else
- address=0xc0+X;//Y非0时,表时在第二行显示,地址基数为0xC0
- write_cmd(address);//写指令,设置显示初始地址
- write_byte(Wdata);//写入当前字符并显示
- }
- void Display_sj(void)
- {
- if(tcount==10)
- {tcount=0;
- second++;
- if(second==60)
- {second=0;
- minute++;
- if(minute==60)
- {minute=0;
- hour++;
- if(hour==24)
- {hour=0;
- day++;
- }
- if(day==7)
- {
- day=0;
- }
- }
- }
- }
- LCD_write_char(10,0,day+'0');
- //第1行显示
- LCD_write_char(0,0,hour/10+'0');
- LCD_write_char(1,0,hour%10+'0'); //时
- LCD_write_char(2,0,':');
- LCD_write_char(3,0,minute/10+1+'0');
- LCD_write_char(4,0,minute%10+'0'); //分
- LCD_write_char(5,0,':');
- LCD_write_char(6,0,second/10+'0');
- LCD_write_char(7,0,second%10+'0'); //秒
-
- }
-
- void main()
- {
-
- int i;//i储存转换后的温度值
- sendChangeCmd();
- init();
- writeComm(0x80);
- dis_play(); //屏幕滚动
- init();
- writeComm(0x80);
- init_eeprom(); //读取EEPROM
- led1=0;
- led2=0;
-
-
- while(1)
- {
- Display_sj();
- tcount++;
- delayMs(70); //温度转换和时间需要 延时确定秒钟时间符合要求
- writeComm(0xc0);
- i = getTmpValue();
- lcd_init(); //初始化
- display(i); //显示温度
- sendChangeCmd();
- warn(i); //报警函数
-
- //====================进入工作状态=======显示温度----时间==========================
- displaysx(0x0c,'H'); //报警最高温度
- displaysx(0x0d,':');
- displaysx(0x0e,WenDuS/10+0x30);
- displaysx(0x0f,WenDuS%10+0x30);
-
- displaysx(0x4c,'L'); //报警最低温度
- displaysx(0x4d,':');
- displaysx(0x4e,WenDuX/10+0x30);
- displaysx(0x4f,WenDuX%10+0x30);
- //时间显示
- //====================K2==0 温度报警上限设置=====进入中断======================
- if(K2==0) //温度
- {
- led1=1;
- BEEP=1;
- led2=0;
- delayMs(20);
- while(led1==1)
- {
- if(K1==0) //按键响应结束
- {
- led1=0;
- led2=0;
- BEEP=1;
- }
- init();
- writeComm(0x80);
- WenDuS= byte_read(0x2000); //读取EEPROM
- displaysx(0x0c,'h'); //报警最高温度
- displaysx(0x0d,':');
- displaysx(0x0e,WenDuS/10+0x30);
- displaysx(0x0f,WenDuS%10+0x30);
- delayMs(10);
- if(K2==0)
- { delayMs(20);
- if(K2==0)
- { WenDuS+=1;
- byte_write(0x2000, WenDuS);
- if(WenDuS>99) { WenDuS=99; } //温度上限报警加
- }
- }
- if(K3==0)
- {
- delayMs(20);
- if(K3==0)
- WenDuS-=1;
- byte_write(0x2000, WenDuS);
- if(WenDuS<1) { WenDuS=1; } //温度下限报警加
- }
- byte_write(0x2000, WenDuS); //保存数据
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
温度计.zip
(129.69 KB, 下载次数: 148)
|