1、温度可通过调整DS18B20“+”“-”进行调整。
2、当温度超出范围,会有声光报警
3、因为在proteus中找不到三极管8550,所以拿了NPN管MSP8098代替,其原理是相同的,但程序稍做修改,位选本来用低电平,现在高电平位选。
4、如何装载程序?双击单片机—program file—找到相应的hex文件。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
- #include<math.h>
- #include<INTRINS.H>
- #define uchar unsigned char
- #define uint unsigned int
- /******************************************************************/
- /* 定义端口 */
- /******************************************************************/
- sbit buzzer=P1^0;//蜂鸣器端口
- sbit led1=P1^1; //led指示灯,当前温度高于设置的最高温度时点亮
- sbit led2=P1^2; //led指示灯,当前温度低于设置的最低温度时点亮
- sbit DQ=P1^4; //ds18b20 端口
- sbit key1=P3^4; //按键
- sbit key2=P3^5;
- sbit key3=P3^6;
- sbit key4=P3^7;
- /******************************************************************/
- /* 全局变量 */
- /******************************************************************/
- uint temp;//当前温度值
- uchar TempH=0,TempL=0;
- int temp_max,temp_min;//设定温度的最大值和最小值
- uchar flag_get,count,num;
- uchar tab[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //0~~9段码
- uchar str[4];//四位数码管显示字符
- uchar display_mod;//数码管显示模式
- /******************************************************************/
- /* 函数声明 */
- /******************************************************************/
- unsigned int ReadTemperature(void);//读取温度函数
- void Init_DS18B20(void);//18b20初始化函数
- unsigned char ReadOneChar(void);//18B20读一个字节
- void WriteOneChar(unsigned char dat);//18B20写一个字节
- void delay(unsigned int i);//短延时
- void delay_ms(uint z);//长延时
- void alarm();//报警
- void keyscan();//键盘扫描
- /******************************************************************/
- /* 主函数 */
- /******************************************************************/
- main()
- {
- uchar buzzer_delay=0;//蜂鸣器延时计数
- uchar buzzer_work=0;//蜂鸣器开始工作
- display_mod=0;//显示当前温度
- temp_min=10;//设置最低温
- temp_max=40;//设置最高温
- TMOD|=0x01;//定时器设置
- TH0=0xef; //定时器初值
- TL0=0xf0;
- IE=0x82;//EA=1,ET0=1
- TR0=1; //开定时器
- P2=0xff;
- count=0;
- buzzer=0;
- while(1)
- {
- keyscan();//独立按键扫描
-
- if(flag_get==1)
- { buzzer_delay++;
- flag_get=0;// 获取温度标志清零
- temp=ReadTemperature();//读温度值
- }
- if(display_mod==0)
- {
- if(temp&0x8000)
- {
- str[0]=0xbf;//负号标志
- temp=~temp; //取反加1
- temp +=1;
- }
- else
- {
- str[0]=0xff;
- }
- TempH=temp>>4;
- TempL=temp&0x0F;
- TempL=TempL*6/10;//小数近似处理
-
- str[1]=tab[(TempH%100)/10]; //十位温度
- str[2]=tab[(TempH%100)%10]&0x7f; //个位温度,带小数点
- str[3]=tab[TempL];
- }
- else if(display_mod==1)//显示最低温
- {
- str[0]=0xc7;//显示L
- str[1]=tab[temp_min/100]; //温度百位
- str[2]=tab[(temp_min%100)/10]; //温度十位
- str[3]=tab[temp_min%10];//温度个位
- }
- else if(display_mod==2)//显示最高温
- {
- str[0]=0x89;//显示H
- str[1]=tab[temp_max/100]; //温度百位
- str[2]=tab[(temp_max%100)/10]; //温度十位
- str[3]=tab[temp_max%10];//温度个位
- }
- if(buzzer_delay>5)//为了防止温度获取前就会出现报警
- {
- buzzer_work=1;
- }
- if(buzzer_work==1)
- alarm();
- }
- }
- /******************************************************************/
- /* 定时器中断 */
- /******************************************************************/
- void tim(void) interrupt 1 using 1//中断,用于数码管扫描和温度检测间隔
- {
- TH0=0xea;//定时器重装值
- TL0=0xf0;
- num++;
- if (num==100)
- {
- num=0;
- flag_get=1;//获取温度标志位有效
- }
- count++;
- if(count==1)
- {
- //P2=0Xfe;
- P2=0x01;
- P0=str[0];
- }//数码管扫描
- if(count==2)
- {
- if(str[1]==tab[0])
- str[1]=0xff;//显示为空
- //P2=0Xfd;
- P2=0x02;
- P0=str[1];
- }
- if(count==3)
- {
- //P2=0Xfb;
- P2=0x04;
- P0=str[2];
- }
- if(count==4)
- {
- //P2=0Xf7;
- P2=0x08;
- P0=str[3];
- count=0;
- }
- }
- /******************************************************************/
- /* 长延时函数 */
- /******************************************************************/
- void delay_ms(uint z) //长延时函数
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- /******************************************************************/
- /* 短延时函数 */
- /******************************************************************/
- void delay(unsigned int i)//短延时函数
- {
- while(i--);
- }
- /******************************************************************/
- /* 初始化 */
- /******************************************************************/
- void Init_DS18B20(void)
- {
- /*unsigned char x=0;
- DQ = 1; //DQ复位
- delay(8); //稍做延时
- DQ = 0; //单片机将DQ拉低
- delay(80); //精确延时 大于 480us
- DQ = 1; //拉高总线
- delay(10);
- x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
- delay(5);*/
- unsigned char x=0;
- DQ = 1; //DQ复位
- delay(8); //稍做延时
- DQ = 0; //单片机将DQ拉低
- delay(80); //精确延时 大于 480us
- DQ = 1; //拉高总线
- delay(14);
- x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
- delay(20);
- }
- /******************************************************************/
- /* 读一个字节 */
- /******************************************************************/
- unsigned char 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(5);
- }
- return(dat);
- }
- /******************************************************************/
- /* 写一个字节 */
- /******************************************************************/
- void 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;
- }
- delay(5);
- }
- /******************************************************************/
- /* 读取温度 */
- /******************************************************************/
- unsigned int ReadTemperature(void)
- {
- unsigned char a=0;
- unsigned int b=0;
- unsigned int t=0;
- Init_DS18B20();
- WriteOneChar(0xCC); // 跳过读序号列号的操作
- WriteOneChar(0x44); // 启动温度转换
- delay(200);
- Init_DS18B20();
- WriteOneChar(0xCC); //跳过读序号列号的操作
- WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
- a=ReadOneChar(); //低位
- b=ReadOneChar(); //高位
- b<<=8;
- t=a+b;
- return(t);
- }
- /******************************************************************/
- /* 独立键盘扫描函数并显示设定的温度 */
- /******************************************************************/
- void keyscan()
- {
- static uchar keynum;//用于切换界面时按键计数
- P3=0xff;//拉高P3口,以读取P3口的值
- if(key4==0)//设置键
- {
- delay_ms(5);//延时消抖
- if(key4==0)
- {
- keynum++;
- keynum%=2;//在0、1间变化
- if(keynum==1)
- {
- display_mod=1;
- }
- else
- {
- display_mod=2;
- }
- }
- while(!key4);//松手检测
- }
- if(key3==0)//确定键
- {
- delay_ms(5);
- if(key3==0)
- {
- keynum=0;
- display_mod=0;
- }
- while(!key3);
- }
- if(key2==0)//加键
- {
- delay_ms(5);//延时消抖
- if(key2==0)
- {
- if(display_mod==2)
- {
- temp_max++;
- if(temp_max>=99)
- temp_max=99;
- }
- if(display_mod==1)
- {
- temp_min++;
- if(temp_min>=temp_max)
- temp_min=temp_max;
- }
-
- }
- while(!key2);//松手检测
- }
- if(key1==0)//减键
- {
- delay_ms(5);
- if(key1==0)
- {
- if(display_mod==2)
- {
- temp_max--;
- if(temp_max<=temp_min)
- temp_max=temp_min;
- }
- if(display_mod==1)
- {
- temp_min--;
- if(temp_min<=0)
- temp_min=0;
- }
- }
- while(!key1);//松手检测
- }
- }
- /******************************************************************/
- /* 蜂鸣器报警程序 */
- /******************************************************************/
- void alarm()
- {
- if(display_mod==0)//在显示当前温度时报警才会动作
- {
- if(TempH<(temp_min))
- {
- led1=0;
- led2=1;
- buzzer=~buzzer;
- }
- else if(TempH>=(temp_max))
- {
- led1=1;
- led2=0;
- buzzer=~buzzer;
- }
- else
- {
- led1=1;
- led2=1;
- buzzer=0;
- }
- }
- }
复制代码
所有资料51hei提供下载:
3 protues仿真.zip
(71.5 KB, 下载次数: 308)
|