工业控制 | 能源技术 | 汽车电子 | 通信网络 | 安防监控 | 智能电网 | 移动手持 | 无线技术 | 家用电器 | 数字广播 | 消费电子 | 应用软件 | 其他方案

基于D18B20的数字温度计

作者:dolphin时间:2011-04-21

以前做过的东西都放在了电脑上或传给自己的朋友参考,想到还有很多不相识的朋友还在单片机的门前徘徊,基于此想法,有必要将我的入门级作品粘到这里与大家分享,让我们在嵌入式技术的道路上走的更远些,年轻人将自己的爱好变为自己的事业应该是一件很幸福的事情..... 由于有仿真图形,各个管脚的配置情况是很清楚地,也就不说了,先把仿真图发上:

下面是源代码,注释也算详尽,我还会在最后附上作品实物,其实仿真通过了,一般情况下就通过了:
//=======================================================================================
// 作者: li ran
// 描述:数字温度计
//日期:2009、x、x
//=======================================================================================
#include "reg52.h"
#include "intrins.h" //_nop_();延时函数用
#define uchar unsigned char
#define uint unsigned int
uint count;
sbit DQ=P3^2; //温度输入口
sbit DIN=P0^7; //LED小数点控制
sbit aa=P2^0;
sbit bb=P2^1;
sbit cc=P2^2;
sbit dd=P2^3;
sbit ee=P2^4;
uchar code tab1[12]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40}; //共阳LED段码表 "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "不亮" "-"
uchar code tab2[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
uchar data temp_data[2]={0x00,0x00}; // 读出温度低8位,高8位
uchar t0,t1,t2,t3,t4;//显示单元数据,共4个数据,t4运算暂存用
/***********11us延时函数**********/
void delay1(uint t)
{
for(;t0;t--);
}
/***********显示扫描函数**********/
void scan()
{
P0=tab1[t3];
aa=0;
delay1(90);
P2=0xff;
P0=tab1[t2];
bb=0;
delay1(90);
P2=0xff;
P0=tab1[t1];
DIN=1;
cc=0;
delay1(90);
P2=0xff;
P0=tab1[t0];
dd=0;
delay1(90);
P2=0xff;
}
/***********18B20复位函数**********/
void ow_reset(void)
{
char presence=1;
while(presence)
{
while(presence)
{
DQ=1;_nop_();_nop_();
DQ=0; //
delay1(50); // 550us
DQ=1; //
delay1(6); // 66us
presence=DQ; //
}
delay1(45); //延时500us
presence = ~DQ;
}
DQ=1;
}
/**********18B20写命令函数*********/
//向总线上写一个字节
void write_byte(uchar val)
{ uchar i;
for (i=8; i0; i--) //
{
DQ=1;_nop_();_nop_();
DQ = 0;
_nop_();_nop_();_nop_();_nop_();_nop_();//5us
DQ = val&0x01; //最低位移出
delay1(6); //66us
val=val/2; //右移一位
}
DQ = 1;
delay1(1);
}
/*********18B20读1个字节函数********/
//从总线上读取一个字节
uchar read_byte(void)
{ uchar i;
uchar value = 0;
for (i=8;i0;i--)
{ DQ=1;_nop_();_nop_();
value=1;
DQ = 0; //
_nop_();_nop_();_nop_();_nop_(); //4us
DQ = 1;_nop_();_nop_();_nop_();_nop_(); //4us
if(DQ)value|=0x80; delay1(6); //66us
}
DQ=1;
return(value);
}
/***********读出温度函数**********/
void read_temp()
{ ow_reset(); //总线复位
write_byte(0xCC); // 跳过Skip ROM命令
write_byte(0xBE); // 发读命令
temp_data[0]=read_byte(); //温度低8位
temp_data[1]=read_byte(); //温度高8位
ow_reset();
write_byte(0xCC); // 跳过
write_byte(0x44); // 发转换命令
}
/***********温度数据处理函数**********/
void work_temp()
{ uchar n=0; //
if(temp_data[1]127)
{
temp_data[1]=(255-temp_data[1]);//我也不明白为啥256就不行,但是用255显示负温度的时候有点误差
temp_data[0]=(255-temp_data[0]);
n=1;
}//负温度求补码
t4=temp_data[0]&0x0f;
t0=tab2[t4]; //小数部分
t4=((temp_data[0]&0xf0)4)|((temp_data[1]&0x0f)4);// 整数部分
t3=t4/100; //百位
t1=t4%100;
t2=t1/10; //十位
t1=t1%10; //个位
if(!t3)
{
t3=0x0A;
if(!t2)
{
t2=0x0A;
}
}//最高位为0时都不显示
if(n)
{
t3=0x0B;//负温度时最高位显示"-"
}
}
/**************主函数****************/
void main()
{
uint h;
TMOD=0X01; //定时器的设置
TH0=(65536-1000)/256; //
TL0=(65536-1000)%256; //
EA=1; //
ET0=1; //
TR0=1; //
//EA=0;
ow_reset(); // 开机先转换一次
write_byte(0xCC); // Skip ROM
write_byte(0x44); // 发转换命令
for(h=0;h33000;h++)
{P0=0xbf;P2=0x00;P1=0xbf;P2=0x00;} //开机显示"0000"2秒
while(1)
{

read_temp(); //读出18B20温度数据 ??
work_temp(); //处理温度数据 ??
for(h=0;h300;h++)
{scan();} //显示温度值1秒
}
}
//定时中断函数的入口
void time0() interrupt 1
{
TH0=(65536-1400)/256;
TL0=(65536-1400)%256;
count++;
if(count700){P1=0x6f;ee=0;} //这些if语句是用来控制最左边数码管的闪烁速度的
//(一个女孩名字的第一个字母)O(∩_∩)O哈哈~
if((700count)&&(count=1400)){P1=0x00;ee=0;}
if((1400count)&&(count=2100)){P1=0x67;ee=0;}
if((2100count)&&(count=2800)){P1=0x00;ee=0;}
if((2800count)&&(count3500)){P1=0x67;ee=0;}
if((4200count)&&(count=4900)){P1=0x00;ee=0;}
if(count5000){count=0;}

}



评论

技术专区