📄 13.c
字号:
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P3^6;
sbit BEEP=P3^7;
sbit HI_LED=P1^4;
sbit LO_LED=P1^5;
//共阴数码管段码及空白显示
uchar code DSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
//温度小数位对照表
uchar code df_Table[]={0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9};
//报警温度上下限,为进行正负数比较,此处注意设为char型
//取值范围为-128~+127,DS18B20支持范围为-50~+125
char Alarm_Temp_HL[2]={40,-20};
uchar CurrentT=0; //当前读取的温度整数部分
uchar Temp_Value[]={0x00,0x00}; //从DS18B20读取的温度值
uchar Display_Digit[]={0,0,0,0}; //待显示的各温度数位
bit HI_Alarm=0,LO_Alarm=0; //高低温报警标志
bit DS18B20_IS_OK=1; //传感器正常标志
uint Time0_Count=0; //定时器延时累加
//延时
void Delay(unsigned int x)
{
while(--x);
}
//初始化SD18B20
uchar Init_DS18B20( )
{
uchar status;
DQ=1;Delay(8);
DQ=0;Delay(90);
DQ=1;Delay(8);
status=DQ;
Delay(100);
DQ=1;
return status; //初始化成功时返回0
}
//读一字节
uchar ReadOneByte( )
{
uchar i,dat=0;
DQ=1;_nop_( );
for(i=0;i<8;i++)
{
DQ=0;dat>>=1;DQ=1;_nop_( );_nop_( );
if(DQ)dat|=0x80;Delay(30);DQ=1;
}
return dat;
}
//写一字节
void WriteOneByte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
DQ=0;DQ=dat&0x01;Delay(5);DQ=1;dat>>=1;
}
}
//读取温度值
void Read_Temperature( )
{
if(Init_DS18B20()==1) //DS18B20故障
DS18B20_IS_OK=0;
else
{
WriteOneByte(0xcc); //跳过序列号
WriteOneByte(0x44); //启动温度转换
Init_DS18B20( );
WriteOneByte(0xcc); //跳过序列号
WriteOneByte(0xbe); //读取温度寄存器
Temp_Value[0]=ReadOneByte( ); //温度低八位
Temp_Value[1]=ReadOneByte( ); //温度高八位
Alarm_Temp_HL[0]=ReadOneByte( ); //报警温度TH
Alarm_Temp_HL[1]=ReadOneByte( ); //报警温度TL
DS18B20_IS_OK=1;
}
}
//设置DS18B20温度报警值
void Set_Alarm_Temp_Value( )
{
Init_DS18B20( );
WriteOneByte(0xcc); //跳过序列号
WriteOneByte(0x4e); //将设定的温度报警值写入DS18B20
WriteOneByte(Alarm_Temp_HL[0]); //写HL
WriteOneByte(Alarm_Temp_HL[1]); //写TL
WriteOneByte(0x7f); //12为精确度
Init_DS18B20( );
WriteOneByte(0xcc); //跳过序列号
WriteOneByte(0x48); //温度报警值存入DS18B20
}
//在数码管上显示温度
void Display_Temperature( )
{
uchar i;
uchar t=150; //延时值
uchar ng=0,np=0; //负数标识及负号显示位置
char Signed_Current_Temp; //注意类型为char
//如果为负数则取反加1,并设置负号标识及负号显示位置
if((Temp_Value[1]&0xf8)==0xf8)
{
Temp_Value[1]=~Temp_Value[1];
Temp_Value[0]=~Temp_Value[0]+1;
if(Temp_Value[0]==0x00)Temp_Value[1]++;
ng=1;np=0xfd; //默认负号显示在左边第2位
}
//查表得到温度小数部分
Display_Digit[0]=df_Table[Temp_Value[0]&0x0f];
//获取温度整数部分(无符号)
CurrentT=((Temp_Value[0]&0xf0)>>4)|((Temp_Value[1]&0x07)<<4);
//有符号的当前温度值,注意定义为char,其值可以为-128~+127
Signed_Current_Temp=ng?-CurrentT:CurrentT;
//高低温报警标志设置(与定义为char类型的Alarm_Temp_HL比较,这样可区分正负比较)
HI_Alarm=Signed_Current_Temp>=Alarm_Temp_HL[0]?1:0;
LO_Alarm=Signed_Current_Temp<=Alarm_Temp_HL[1]?1:0;
//将整数部分分解为三位待显示数字
Display_Digit[3]=CurrentT/100;
Display_Digit[2]=CurrentT%100/10;
Display_Digit[1]=CurrentT%10;
if(Display_Digit[3]==0) //高位为0则不显示
{
Display_Digit[3]=10;
np=0xfb; //调整负号位置
if(Display_Digit[2]==0)
{
Display_Digit[2]=10;
np=0xf7; //调整负号位置
}
}
//刷新显示若干时间
for(i=0;i<30;i++)
{
P0=0x39;P2=0x7f;Delay(t);P2=0xff; //显示C
P0=0x63;P2=0xbf;Delay(t);P2=0xff; //显示°
P0=DSY_CODE[Display_Digit[0]]; //小数位
P2=0xdf;Delay(t);P2=0xff;
P0=(DSY_CODE[Display_Digit[1]])|0x80; //个位及小数
P2=0xef;Delay(t);P2=0xff;
P0=DSY_CODE[Display_Digit[2]]; //十位
P2=0xf7;Delay(t);P2=0xff;
P0=DSY_CODE[Display_Digit[3]]; //百位
P2=0xfb;Delay(t);P2=0xff;
if(ng) //如果为负则在调整后的位置显示"-"
{
P0=0x40;P2=np;Delay(t);P2=0xff;
}
}
}
//定时器中断,控制警报声音
void T0_INT( )interrupt 1
{
TH0=-1000/256;
TL0=-1000%256;
BEEP=!BEEP;
if(++Time0_Count==400)
{
Time0_Count=0;
if(HI_Alarm)HI_LED=~HI_LED;else HI_LED=1;
if(LO_Alarm)LO_LED=~LO_LED;else LO_LED=1;
}
}
//主程序
void main(void)
{
IE=0x82;
TMOD=0x01;
TH0=-1000/256;
TL0=-1000%256;
TR0=0;
HI_LED=1;
LO_LED=1;
Set_Alarm_Temp_Value( );
Read_Temperature( );
Delay(50000);
Delay(50000);
while(1)
{
Read_Temperature( );
if(DS18B20_IS_OK)
{
if(HI_Alarm==1||LO_Alarm==1)TR0=1;
else TR0=0;
Display_Temperature( );
}
else
{
P0=P2=0x00;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -