📄 ds18b20温度处理.txt
字号:
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit ds18b20=P2^2; //DS18B20端口设置
sbit en_573=P2^1; //74H573
sbit _595dat=P2^5;
sbit _595loc=P2^4;
sbit _595clk=P2^3; //74H595
uchar num,dat,flag,tt,count;
uint temper;
bit presence;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,};
/****************不同级别的延时函数,对于延时函数来说(--n)是在毫秒级较准确的运算大约为3us,且有(2n+1)us运算。
其它大都不太准确,当然这又要考虑到单片机晶振的问题。频率不同延时也有差别**********************************/
void delus(uint num) //us级延时函数
{
while( --num ) ;
}
void delay(uchar t) //ms级别延时
{
uchar i,j;
for(j=t;j>0;j--)
for(i=110;i>0;i--);
}
/*******************数码管(ssled)显示部分
包括74HC573数据锁存部分和74HC595地址为锁存部分
SSLED地址位为595高三位**********************/
/**********调用函数,指定SSLED显示数据********************/
void hc_573(uchar dat) //573数据锁存
{
en_573=0; //使能端开
P0=dat; //录入数据
delay(5); //延时,时数据写入完整
en_573=1; //锁存
}
/**********调用函数,指定SSLED显示地址,595中高三位控制了数码管位选择,
故需要移位处理,同时又要兼顾其它位上数字不变之后才能录入锁存器********************/
void led_595(uchar add)
{
uchar i=0,temp;
temp=dat; //SSLED地址为变换位595高三位
add=add<<5;
temp=temp&0x1f;
temp=temp|add;
_595loc=0; //595移位锁存使能开,八位移位锁存
for(i=0;i<8;i++)
{
_595clk=0; //一个上升脉冲录入一位
if((temp<<i)&0x80)
_595dat=1;
else
_595dat=0;
_595clk=1;
}
_595loc=1; //锁存数据
delay(5);
}
/**********调用函数,指定SSLED地址并显示为了后面显示没有将table表格写入更多情况是
hc_573(table【dat】);代替hc_573(dat);当然前面要加上十六位数表格********************/
void dis_led(uchar add,uchar dat) //指定SSLED地址并显示
{
led_595(add); //录入数据
hc_573(dat); //录入地址
delay(5); //延时,保证录入完整
P0=0x00; //消隐
}
/**********
DS18B20温度测量并显示在八位数码管上
DS18B20是单总线控制数字温度传感器,控制过程完全是对时序的控制和掌握
因此它对时间(毫秒级:us)要求时非常严格的,少一点误差就无法准确测量出温度示数
这就又要考虑到单片机晶振的问题。(--n:适毫秒级大约3u时间,且有(2n+1)us运算。
其它大都不太准确)
********************/
/*************DS18B20的复位初始化及返回存在***************/
tem_reset(void)
{
ds18b20 = 1 ; //ds18b20复位
delus(8) ; //稍做延时
ds18b20 = 0 ; //单片机将ds18b20拉低
delus(90) ; //精确延时 大于 480us
ds18b20 = 1 ; //拉高总线
delus(8) ;
presence = ds18b20 ; //如果=0则初始化成功 =1则初始化失败
delus(100) ;
ds18b20 = 1 ;
return(presence) ; //返回信号,0=presence,1= no presence
}
/*******************读取一个字*******************/
tem_read(void)
{
uchar i = 0, dat = 0 ;
for (i = 8 ; i > 0 ; i--)
{
ds18b20 = 0 ; // 给脉冲信号
dat >>= 1 ; //数据右移一位
ds18b20 = 1 ; // 给脉冲信号
if(ds18b20) //判断为=1保存1到高位,=0忽略(保存为0)
dat |= 0x80 ;
delus(4) ; //稍作延时
}
return (dat) ;
}
/*************************写入一个字节 *********************/
void tem_write(uchar com)
{
unsigned char i = 0 ;
for (i = 8 ; i > 0 ; i--)
{
ds18b20 = 0 ; //给脉冲信号
ds18b20 = com&0x01 ; //判断并发送字节
delus(5) ;
ds18b20 = 1 ;
com>>=1 ; //数据右移,并保存
}
}
/********************读取十六位字节温度表示*******************************/
uint read_tem()
{
uchar temh,teml;
uint temp;
while(tem_reset()); //总线复位,响应存在
tem_write(0xcc); //发跳跃ROM命令
tem_write(0x44); //发温度转换命令
while(tem_reset()); //总线复位,响应存在
tem_write(0xcc); //发跳跃ROM命令
tem_write(0xbe); //读取暂存储器温度
teml=tem_read(); //读温度值的第字节
temh=tem_read(); //读温度值的高字节
temp=temh;
temp<<=8;
temp=temp|teml; // 两字节合成一个整型变量。
return temp; //返回温度值
}
/*******************
*读取八位字节温度表示,在处理数据时要先读低八位,再读高八位。型如{dsl=read_tem;dsh=read_tem;}
由于处理八位数显示较麻烦所以大都作者会选择合并再处理如{uint temper;temper=dsh;tesmper=(dsh<<8)|dsl;}
之后的处理是十六位数读取
**********************************/
/*
uchar read_tem(void)
{
uchar tem;
uint temp;
tem_reset(); //总线复位
tem_write(0xcc); //发跳跃ROM命令
tem_write(0x44); //发温度转换命令
tem_reset();
em_write(0xcc); //发跳跃命令
tem_write(0xbe); //读取暂存储器温度
tem=tem_read(); //读温度值的八位字节
return temp; //返回温度值
}
*/
/********************处理十六位读数并在数码管上显示,
数据关系:低四位乘以625(12位分频)是小数部分,中间八位是整数部分,高四位是符号位。
负数时取补码[取反加一(tem=~tem+1)处理与正数相同。十六位数据处理优点在于处理负数部分:
取反加一时会有遇到进位问题。这一进位将直接加到整数位,不再而外处理。********************************/
void dis_tem(uint ds_tem)
{
char i,tem;
int dsh,dsl,ds;
ds=(uchar)(ds_tem>>8);
ds=ds&0xf0;
if(ds==0xf0) //负数的处理
{
ds_tem=~ds_tem+1; //取负数补码
dis_led(7,0x40);
}
dsl=ds_tem&0x0f; //整理得到可显示小数部分
dsh=(ds_tem>>4)&0x0ff; //得到可显示整数部分
dsl=dsl*625;
for(i=0;i<4;i++) //小数部分
{
dis_led(i,table[dsl%10]);
dsl=dsl/10;
}
dis_led(i++,table[dsh%10]|0x80); //个位数显示,带小数点
dsh=dsh/10;
tem=dsh/10; //百位数显示,0不显示,否则显示
if(tem==0)
dis_led(6,0x00);
else
dis_led(6,table[tem]);
tem=dsh%10; //十位数显示,0不显示,否则显示
if(tem==0)
dis_led(5,0x00);
else
dis_led(5,table[tem]);
}
/********************主函数********************************/
main()
{
while(tem_reset()); //总线复位
tem_write(0xcc); //发命令
tem_write(0x44); //发转换命令
delay(1000); //延时使温度转化完整
while(1)
{
dis_tem(read_tem()); //显示温度读数,
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -