#define DO P3_7
#define SEG P0 //数码管自左至右依次为1234位
#define MS2L 0x18 //1ms的延时参数
#define MS2H 0xfc
#define uchar unsigned char
#define uint unsigned int
uchar code comm[4] = {0x01,0x02,0x04,0x08};
uchar code seg[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar code seg_add_dicimal[10] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
uchar code seg_dicimal[2] ={0xc0, 0x92};
uchar k = 0;
uchar temp_l = 0;
uchar temp_h = 0;
uchar tempsign = 0;
uchar hundreds = 0;
uchar tens = 0;
uchar ones = 0;
uchar low_four = 0;
/*延时以ms单位t时间*/
void Delay(uint t)
{
uint i;
while(t--)
{
for(i=0; i<125; i )
{ }
}
}
/*us延迟时间约为4+2*i*/
void Delayus(uchar i)
{
while(--i);
}
/*产生复位脉冲,等待响应信号*/
void Resetpaulse()
{
DO = 0; //拉低约600us
Delayus(150);
Delayus(150);
DO = 1;//产生上升沿,延迟约15~60us
Delayus(30);
while(~DO); //等待响应信号
}
/*读取一个数据*/
bit Readbit()
{
uint i = 0;
bit b = 0;
DO = 0; //产生读时间隙
i ; ///至少保持低电平us
DO = 1; //1us以上后拉高
Delayus(2); //延时8us,DO下降沿15内ds18b20输出的数据是有效的
b = DO; ///读取数据
Delayus(40); ///每个阅读间隙至少持续60次us
return(b);
}
/*读一个字节*/
uchar Readbyte()
{
uchar byte_read = 0;
uchar i, j;
for(i=0; i<8; i )
{
j = Readbit();
byte_read = (j<> 1;
}
}
/*配置ds18b20,9位分辨率 */
void Configurate()
{
EA = 0;
Resetpaulse(); ///发出复位脉冲,每次操作从复位开始
Delay(1);
Writebyte(0xcc); //skip room命令
Writebyte(0x4e);
Writebyte(0x7f);
Writebyte(0x80);
Writebyte(0x1f);
EA = 1;
}
/*启动温度转换*/
void StartConvert()
{
Resetpaulse(); // 发出复位脉冲,每次操作从复位开始
Delay(1);
EA = 0;
Writebyte(0xcc); //skip room命令
Writebyte(0x44); ///启动温度转换命令
EA = 1;
}
/*读取温度值*/
void ReadTempreture()
{
EA = 0;
Resetpaulse(); // 发出复位脉冲,每次操作从复位开始
Delay(1);
Writebyte(0xcc); //skip room命令
Writebyte(0xbe); //读取暂存器命令
temp_l = Readbyte(); //存储温度低字节值 (低四位和小数部分的整数部分)
temp_h= Readbyte(); ///存储温度高字节值 (高五位为符号位)
EA = 1;
}
/*数据转换*/
void DigitalConvert()
{
uchar total = 0;
tempsign = (temp_h >> 7) & 0x01; ///得出符号位
if(tempsign == 0) ///正数处理方法
{
total = ((temp_h << 4)&0xf0) | ((temp_l >> 4)&0x0f); //取整数位
low_four = (temp_l>>3) & 0x01; //取小数位,9位分辨率,低字节第三位为小数位,只有0和1两个值
hundreds = total / 100; //计算百,十,个位
tens = (total0)/10;
ones = (total0);
}
else ///负处理 负数补码规则是按位取反,得到反码,加1即得补码(符号位不变)
{
tempsign = 1;
total = ((temp_l >> 4) & 0x0f); ///整数部分低4位
total |= ((temp_h << 4) & 0xf0); ///整数部分高三位和符号位
low_four = (temp_l >> 3) & 0x01; //取小数位
if(low_four == 0) //这里total位uchar因此,整数补偿规则是根据最低水平确定的
total = ~total 1; //最低位为0时,取反加1后有进位,所以这里total要取反加1
else
total = ~total;//当最低位为1时,取反加1没有进位,因此total可以直接取反
tens = (total0)/10;
ones = (total0);
}
}
/*中断处理*/
void Display()interrupt 1
{
EA = 0;
TL0 = MS2L;
TH0 = MS2H;
DigitalConvert(); ///数据转换
if(tempsign == 0)//正数
{
if(k == 0)
{
if(hundreds == 0) //高位0消隐
{P1 = 0;}
else
{
P1 = comm[k];
SEG = seg[hundreds];
}
}
else if(k == 1)
{
if(tens == 0 && hundreds == 0) //高位0消隐
{P1 = 0;}
else
{
P1 = comm[k];
SEG = sg[tens];
}
}
else if(k == 2)//显示个位,因为个位有小数点,所以又定义了一个数组分开来显示
{
P1 = comm[k];
SEG = seg_add_dicimal[ones]; //要加上小数点
}
else //显示小数,0或5
{
P1 = comm[k];
SEG = seg_dicimal[low_four];
}
}
else if(tempsign == 1) //负数
{
if(k == 0)//显示符号位
{
P1 = comm[k];
SEG = 0xbf;
}
else if(k == 1)
{
if(tens == 0)
{P1 = 0;}
else
{
P1 = comm[k];
SEG = seg[tens];
}
}
else if(k == 2)//显示个位,因为各位有小数点,所以分开来显示
{
P1 = comm[k];
SEG = seg_add_dicimal[ones]; //要加上小数点
}
else //显示小数,0或5
{
P1 = comm[k];
SEG = seg_dicimal[low_four];
}
}
k++;
if(k == 4)
k = 0;
EA = 1;
}
/*主函数部分*/
void main()
{
TMOD = 0x01;
TL0 = MS2L;
TH0 = MS2H;
TF0 = 0;
EA = 1;
ET0 = 1;
TR0 = 1;
Configurate();
do{
Delay(1);
StartConvert();
Delay(100);
ReadTempreture();
}
while(1);
}