在单片机的学习开发版上可以运行,但是到了proteus就仿真不出来了,好急好急。。。
#include <reg52.h>
#include <intrins.h>
#include <math.H>
#include <stdio.h>
#define uint unsigned int
#define uchar unsigned char
#define _Nop() _nop_()
#define lcd_data_port P0//液晶数据口
unsigned int temp_setH=400;
unsigned int temp_setL=200;
unsigned char s1,s2,s3,s4,s5,s6;
unsigned char NGflag=0;//负温度标志位
sbit DQ =P3^3; //定义DS18B20通信端口
sbit RS = P2^0; //定义LCD控制端口
sbit RW = P2^1;
sbit LCDEN = P2^2;
sbit beep = P3^6;
sbit Key1 = P1^6;//增加按键
sbit Key2 = P1^5;//减小按键
sbit Set = P1^4;//设置按键
int set(); //声明温度设置子程序
/*1MS为单位的延时程序*/
void delay_1ms(uint x)
{
uchar j;
while(x--){
for(j=0;j<125;j++)
{;}
}
}
void delay500us()
{
unsigned char j;
for(j=0;j<57;j++) //500us基准延时程序
{
;
}
}
void beep1()//产生1KHZ频率声音的函数
{
beep=0;
delay500us();
beep=1;
delay500us();
}
//////////////以下是LCD1602驱动程序////////////////
void lcd_delay(uchar ms) /*LCD1602 延时*/
{
uchar j;
while(ms--){
for(j=0;j<250;j++)
{;}
}
}
void lcd_busy_wait() /*LCD1602 忙等待*/
{
RS = 0;
RW = 1;
LCDEN = 1;
lcd_data_port = 0xff;
while (lcd_data_port&0x80);
LCDEN = 0;
}
void lcd_command_write(uchar command) /*LCD1602 命令字写入*/
{
lcd_busy_wait();
RS = 0;
RW = 0;
LCDEN = 0;
lcd_data_port = command;
LCDEN = 1;
LCDEN = 0;
}
void lcd_system_reset() /*LCD1602 初始化*/
{
lcd_delay(20);
lcd_command_write(0x38);
lcd_delay(100);
lcd_command_write(0x38);
lcd_delay(50);
lcd_command_write(0x38);
lcd_delay(10);
lcd_command_write(0x0c);
lcd_command_write(0x06);
lcd_command_write(0x01);
lcd_command_write(0x80);
}
void lcd_char_write(uchar x_pos,y_pos,lcd_dat) /*LCD1602 字符写入*/
{
x_pos &= 0x0f; /* X位置范围 0~15 */
y_pos &= 0x01; /* Y位置范围 0~ 1 */
if(y_pos==1) x_pos += 0x40;
x_pos += 0x80;
lcd_command_write(x_pos);
lcd_busy_wait();
RS = 1;
RW = 0;
LCDEN = 0;
lcd_data_port = lcd_dat;
LCDEN = 1;
LCDEN = 0;
}
//////////////////以上是LCD1602驱动程序////////////////
//////////////////以下是DS18B20驱动程序////////////////
//延时函数
void delay(unsigned int i)
{
while(i--);
}
//初始化函数
Init_DS18B20(void)
{
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);
}
//读一个字节
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;
}
}
//读取温度
ReadTemperature(void)
{
unsigned char a=0;
char b=0;
int t=0;
float tt=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
a=ReadOneChar();//读取温度值低位
b=ReadOneChar(); //读取温度值高位
if(b&0x80) //判断温度是否是负值//
{
b=~b;
a=~a+1;
NGflag=1;//负温度标志位置一
}else NGflag=0;
t=b;
t<<=8;
t=t|a;
tt=t*0.0625; //将温度的高位与低位合并
t= tt*10+0.5; //对结果进行4舍5入
return(t);
}
//////////////////以上是DS18B20驱动程序////////////////
/***********************************下面是按键音程序********************************/
void di()
{
unsigned long ul;
unsigned int n;
for(ul=0;ul<700;ul++)
{
for(n=0;n<20;n++);
beep =~beep ;
}
}
/***********************************以上是按键音程序********************************/
/*定义数字ascii编码*/
unsigned char mun_char_table[]={"0123456789abcdef- "};
unsigned char temp_table[] ={"TempNow: . 'C"};
unsigned char temp_set_table[]={"H . 'C L . 'C"};
void main()
{
unsigned int i=0,j=0;
ReadTemperature(); //读取当前温度
lcd_system_reset(); //LCD1602 初始化
for (i=0;i<16;i++) lcd_char_write(i,0,temp_table[i]);
for (j=0;j<16;j++) lcd_char_write(j,1,temp_set_table[j]);
while(1)
{
i=ReadTemperature(); //读取当前温度
set();//运行温度设置子程序
lcd_char_write(10,0,mun_char_table[i%1000/100]); //把温度显示出来
lcd_char_write(11,0,mun_char_table[i%1000%100/10]);
lcd_char_write(13,0,mun_char_table[i%1000%100%10]);
if(i>temp_setH)//比较程序!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
{ //在这里写程序
for(i=0;i<1000;i++)
{
beep1();
}
}
if(i<temp_setL)
{
for(i=0;i<1000;i++)
{
beep1();
}
}
if(i/1000==0) //最高位为零不显示
{
lcd_char_write(9,0,mun_char_table[17]);
}
if((i/100!=0)&&(NGflag==1))
{lcd_char_write(8,0,mun_char_table[16]); }//若温度低于0度且最高位为零,在合适的位置显示符号
else lcd_char_write(8,0,mun_char_table[17]);
if((i/100==0)&&(NGflag!=1))
{lcd_char_write(9,0,mun_char_table[17]); }
if((i/100==0)&&(NGflag==1))
{lcd_char_write(9,0,mun_char_table[16]); }
}
}
int set() //温度设置子程序
{
uchar count=0;
s1=temp_setH/100;//取出数值
s2=temp_setH%100/10;
s3=temp_setH%100%10;
s4=temp_setL/100;//取出数值
s5=temp_setL%100/10;
s6=temp_setL%100%10;
if(Set==0)
{
delay_1ms(3);
if(Set==0)
{
while(!Set);
count++;
while(1)
{
if(Set==0)
{
delay_1ms(3);
di();
if(Set==0)
{
while(!Set);
di();
count++;
}
}
lcd_command_write(0x0f);//光标闪烁
if(count==1) //按键计数1,温度设置十位
{
lcd_command_write(0x40+1); //光标在上限十位闪烁
if(Key1==0)
{
delay_1ms(5);
if(!Key1)
{
s1++;
if(s1==10)
s1=0;
di();
}
lcd_char_write(1,1,mun_char_table[s1]);//显示温度设置值十位
}
if(Key2==0)
{
delay_1ms(5);
if(!Key2)
{
s1--;
if(s1==-1)
s1=9;
di();
}
lcd_char_write(1,1,mun_char_table[s1]);//显示温度设置值十位
}
}
if(count==2) //按键计数2,温度在上限设置个位
{
lcd_command_write(0x40+2); //光标在个位闪烁
if(Key1==0)
{
delay_1ms(5);
if(!Key1)
{
s2++;
if(s2==10)
s2=0;
di();
}
lcd_char_write(2,1,mun_char_table[s2]);//显示温度设置值个位
}
if(Key2==0)
{
delay_1ms(5);
if(!Key2)
{
s2--;
if(s2==-1)
s2=9;
di();
}
lcd_char_write(2,1,mun_char_table[s2]);//显示温度设置值个位
}
}
if(count==3) //按键计数3,温度设置上限小数点后一位
{
lcd_command_write(0x40+4); //光标在小数点后一位闪烁
if(Key1==0)
{
delay_1ms(5);
if(!Key1)
{
s3++;
if(s3==10)
s3=0;
di();
}
lcd_char_write(4,1,mun_char_table[s3]);//显示温度设置值小数点后一位
}
if(Key2==0)
{
delay_1ms(5);
if(!Key2)
{
s3--;
if(s3==-1)
s3=9;
di();
}
lcd_char_write(4,1,mun_char_table[s3]);//显示温度设置值小数点后一位
}
}
if(count==4) //按键计数4,到下限的十位数
{
lcd_command_write(0x40+10); //光标在下限的十位数闪烁
if(Key1==0)
{
delay_1ms(5);
if(!Key1)
{
s4++;
if(s4==10)
s4=0;
di();
}
lcd_char_write(10,1,mun_char_table[s4]);//显示温度设置值小数点后一位
}
if(Key2==0)
{
delay_1ms(5);
if(!Key2)
{
s4--;
if(s4==-1)
s4=9;
di();
}
lcd_char_write(10,1,mun_char_table[s4]);//显示温度设置值小数点后一位
}
}
if(count==5) //按键计数5,温度设置下限的个位
{
lcd_command_write(0x40+11); //光标在下限的个位数闪烁
if(Key1==0)
{
delay_1ms(5);
if(!Key1)
{
s5++;
if(s5==10)
s5=0;
di();
}
lcd_char_write(11,1,mun_char_table[s5]);//显示温度设置值小数点后一位
}
if(Key2==0)
{
delay_1ms(5);
if(!Key2)
{
s5--;
if(s5==-1)
s5=9;
di();
}
lcd_char_write(11,1,mun_char_table[s5]);//显示温度设置值小数点后一位
}
}
if(count==6) //按键计数5,温度设置下限小数点后的位
{
lcd_command_write(0x40+13); //光标在下限的小数点后的位闪烁
if(Key1==0)
{
delay_1ms(5);
if(!Key1)
{
s6++;
if(s6==10)
s6=0;
di();
}
lcd_char_write(13,1,mun_char_table[s6]);//显示温度设置值小数点后一位
}
if(Key2==0)
{
delay_1ms(5);
if(!Key2)
{
s6--;
if(s6==-1)
s6=9;
di();
}
lcd_char_write(13,1,mun_char_table[s6]);//显示温度设置值小数点后一位
}
}
if(count>6)
{
temp_setH=s1*100+s2*10+s3;//还原上限数值
temp_setL=s4*100+s5*10+s6;//还原下限数值
count=0;//清零
lcd_command_write(0x0c);//关光标
break;
}
}
}
}
return 0;
}
#include <reg52.h>
#include <intrins.h>
#include <math.H>
#include <stdio.h>
#define uint unsigned int
#define uchar unsigned char
#define _Nop() _nop_()
#define lcd_data_port P0//液晶数据口
unsigned int temp_setH=400;
unsigned int temp_setL=200;
unsigned char s1,s2,s3,s4,s5,s6;
unsigned char NGflag=0;//负温度标志位
sbit DQ =P3^3; //定义DS18B20通信端口
sbit RS = P2^0; //定义LCD控制端口
sbit RW = P2^1;
sbit LCDEN = P2^2;
sbit beep = P3^6;
sbit Key1 = P1^6;//增加按键
sbit Key2 = P1^5;//减小按键
sbit Set = P1^4;//设置按键
int set(); //声明温度设置子程序
/*1MS为单位的延时程序*/
void delay_1ms(uint x)
{
uchar j;
while(x--){
for(j=0;j<125;j++)
{;}
}
}
void delay500us()
{
unsigned char j;
for(j=0;j<57;j++) //500us基准延时程序
{
;
}
}
void beep1()//产生1KHZ频率声音的函数
{
beep=0;
delay500us();
beep=1;
delay500us();
}
//////////////以下是LCD1602驱动程序////////////////
void lcd_delay(uchar ms) /*LCD1602 延时*/
{
uchar j;
while(ms--){
for(j=0;j<250;j++)
{;}
}
}
void lcd_busy_wait() /*LCD1602 忙等待*/
{
RS = 0;
RW = 1;
LCDEN = 1;
lcd_data_port = 0xff;
while (lcd_data_port&0x80);
LCDEN = 0;
}
void lcd_command_write(uchar command) /*LCD1602 命令字写入*/
{
lcd_busy_wait();
RS = 0;
RW = 0;
LCDEN = 0;
lcd_data_port = command;
LCDEN = 1;
LCDEN = 0;
}
void lcd_system_reset() /*LCD1602 初始化*/
{
lcd_delay(20);
lcd_command_write(0x38);
lcd_delay(100);
lcd_command_write(0x38);
lcd_delay(50);
lcd_command_write(0x38);
lcd_delay(10);
lcd_command_write(0x0c);
lcd_command_write(0x06);
lcd_command_write(0x01);
lcd_command_write(0x80);
}
void lcd_char_write(uchar x_pos,y_pos,lcd_dat) /*LCD1602 字符写入*/
{
x_pos &= 0x0f; /* X位置范围 0~15 */
y_pos &= 0x01; /* Y位置范围 0~ 1 */
if(y_pos==1) x_pos += 0x40;
x_pos += 0x80;
lcd_command_write(x_pos);
lcd_busy_wait();
RS = 1;
RW = 0;
LCDEN = 0;
lcd_data_port = lcd_dat;
LCDEN = 1;
LCDEN = 0;
}
//////////////////以上是LCD1602驱动程序////////////////
//////////////////以下是DS18B20驱动程序////////////////
//延时函数
void delay(unsigned int i)
{
while(i--);
}
//初始化函数
Init_DS18B20(void)
{
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);
}
//读一个字节
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;
}
}
//读取温度
ReadTemperature(void)
{
unsigned char a=0;
char b=0;
int t=0;
float tt=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
a=ReadOneChar();//读取温度值低位
b=ReadOneChar(); //读取温度值高位
if(b&0x80) //判断温度是否是负值//
{
b=~b;
a=~a+1;
NGflag=1;//负温度标志位置一
}else NGflag=0;
t=b;
t<<=8;
t=t|a;
tt=t*0.0625; //将温度的高位与低位合并
t= tt*10+0.5; //对结果进行4舍5入
return(t);
}
//////////////////以上是DS18B20驱动程序////////////////
/***********************************下面是按键音程序********************************/
void di()
{
unsigned long ul;
unsigned int n;
for(ul=0;ul<700;ul++)
{
for(n=0;n<20;n++);
beep =~beep ;
}
}
/***********************************以上是按键音程序********************************/
/*定义数字ascii编码*/
unsigned char mun_char_table[]={"0123456789abcdef- "};
unsigned char temp_table[] ={"TempNow: . 'C"};
unsigned char temp_set_table[]={"H . 'C L . 'C"};
void main()
{
unsigned int i=0,j=0;
ReadTemperature(); //读取当前温度
lcd_system_reset(); //LCD1602 初始化
for (i=0;i<16;i++) lcd_char_write(i,0,temp_table[i]);
for (j=0;j<16;j++) lcd_char_write(j,1,temp_set_table[j]);
while(1)
{
i=ReadTemperature(); //读取当前温度
set();//运行温度设置子程序
lcd_char_write(10,0,mun_char_table[i%1000/100]); //把温度显示出来
lcd_char_write(11,0,mun_char_table[i%1000%100/10]);
lcd_char_write(13,0,mun_char_table[i%1000%100%10]);
if(i>temp_setH)//比较程序!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
{ //在这里写程序
for(i=0;i<1000;i++)
{
beep1();
}
}
if(i<temp_setL)
{
for(i=0;i<1000;i++)
{
beep1();
}
}
if(i/1000==0) //最高位为零不显示
{
lcd_char_write(9,0,mun_char_table[17]);
}
if((i/100!=0)&&(NGflag==1))
{lcd_char_write(8,0,mun_char_table[16]); }//若温度低于0度且最高位为零,在合适的位置显示符号
else lcd_char_write(8,0,mun_char_table[17]);
if((i/100==0)&&(NGflag!=1))
{lcd_char_write(9,0,mun_char_table[17]); }
if((i/100==0)&&(NGflag==1))
{lcd_char_write(9,0,mun_char_table[16]); }
}
}
int set() //温度设置子程序
{
uchar count=0;
s1=temp_setH/100;//取出数值
s2=temp_setH%100/10;
s3=temp_setH%100%10;
s4=temp_setL/100;//取出数值
s5=temp_setL%100/10;
s6=temp_setL%100%10;
if(Set==0)
{
delay_1ms(3);
if(Set==0)
{
while(!Set);
count++;
while(1)
{
if(Set==0)
{
delay_1ms(3);
di();
if(Set==0)
{
while(!Set);
di();
count++;
}
}
lcd_command_write(0x0f);//光标闪烁
if(count==1) //按键计数1,温度设置十位
{
lcd_command_write(0x40+1); //光标在上限十位闪烁
if(Key1==0)
{
delay_1ms(5);
if(!Key1)
{
s1++;
if(s1==10)
s1=0;
di();
}
lcd_char_write(1,1,mun_char_table[s1]);//显示温度设置值十位
}
if(Key2==0)
{
delay_1ms(5);
if(!Key2)
{
s1--;
if(s1==-1)
s1=9;
di();
}
lcd_char_write(1,1,mun_char_table[s1]);//显示温度设置值十位
}
}
if(count==2) //按键计数2,温度在上限设置个位
{
lcd_command_write(0x40+2); //光标在个位闪烁
if(Key1==0)
{
delay_1ms(5);
if(!Key1)
{
s2++;
if(s2==10)
s2=0;
di();
}
lcd_char_write(2,1,mun_char_table[s2]);//显示温度设置值个位
}
if(Key2==0)
{
delay_1ms(5);
if(!Key2)
{
s2--;
if(s2==-1)
s2=9;
di();
}
lcd_char_write(2,1,mun_char_table[s2]);//显示温度设置值个位
}
}
if(count==3) //按键计数3,温度设置上限小数点后一位
{
lcd_command_write(0x40+4); //光标在小数点后一位闪烁
if(Key1==0)
{
delay_1ms(5);
if(!Key1)
{
s3++;
if(s3==10)
s3=0;
di();
}
lcd_char_write(4,1,mun_char_table[s3]);//显示温度设置值小数点后一位
}
if(Key2==0)
{
delay_1ms(5);
if(!Key2)
{
s3--;
if(s3==-1)
s3=9;
di();
}
lcd_char_write(4,1,mun_char_table[s3]);//显示温度设置值小数点后一位
}
}
if(count==4) //按键计数4,到下限的十位数
{
lcd_command_write(0x40+10); //光标在下限的十位数闪烁
if(Key1==0)
{
delay_1ms(5);
if(!Key1)
{
s4++;
if(s4==10)
s4=0;
di();
}
lcd_char_write(10,1,mun_char_table[s4]);//显示温度设置值小数点后一位
}
if(Key2==0)
{
delay_1ms(5);
if(!Key2)
{
s4--;
if(s4==-1)
s4=9;
di();
}
lcd_char_write(10,1,mun_char_table[s4]);//显示温度设置值小数点后一位
}
}
if(count==5) //按键计数5,温度设置下限的个位
{
lcd_command_write(0x40+11); //光标在下限的个位数闪烁
if(Key1==0)
{
delay_1ms(5);
if(!Key1)
{
s5++;
if(s5==10)
s5=0;
di();
}
lcd_char_write(11,1,mun_char_table[s5]);//显示温度设置值小数点后一位
}
if(Key2==0)
{
delay_1ms(5);
if(!Key2)
{
s5--;
if(s5==-1)
s5=9;
di();
}
lcd_char_write(11,1,mun_char_table[s5]);//显示温度设置值小数点后一位
}
}
if(count==6) //按键计数5,温度设置下限小数点后的位
{
lcd_command_write(0x40+13); //光标在下限的小数点后的位闪烁
if(Key1==0)
{
delay_1ms(5);
if(!Key1)
{
s6++;
if(s6==10)
s6=0;
di();
}
lcd_char_write(13,1,mun_char_table[s6]);//显示温度设置值小数点后一位
}
if(Key2==0)
{
delay_1ms(5);
if(!Key2)
{
s6--;
if(s6==-1)
s6=9;
di();
}
lcd_char_write(13,1,mun_char_table[s6]);//显示温度设置值小数点后一位
}
}
if(count>6)
{
temp_setH=s1*100+s2*10+s3;//还原上限数值
temp_setL=s4*100+s5*10+s6;//还原下限数值
count=0;//清零
lcd_command_write(0x0c);//关光标
break;
}
}
}
}
return 0;
}