📄 ds18b20.c
字号:
//文件名:ds18b20.c
//功能:实现温度显示
//硬件连接:外部电源供电,且只有1个DS18B20
//原理:单总线协议(读取温度七步骤,如程序注释)
//注意:此程序晶振为12M,其他晶振需跟据DS18B20资料修改
//编写:王晓荣
//日期:20070626
////////////////////////////////////////////////////////////////////////////
#include <REGX51.H>
#include <intrins.h> // 声明_nop_() 便于实现延时
#define DS18B20 P1_0
unsigned char xdata LEDSEG _at_ 0xfeff; //P2.0
unsigned char xdata LEDBIT _at_ 0xfdff; //P2.1
unsigned char code LEDMAP[] =
{
0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d,
0x07, 0x7f, 0x6f, 0x00, 0x79, 0x46, 0x40,
// 灭 "E" "+" "-"
};
bit DS18B20_FLG = 0; //“1”:DS18B20存在 ;“0”:不存在
bit TEMP_FLG = 0; //“1”:温度为负
bit T1S_FLG = 0; //“1”:1秒钟到
unsigned int t1s;
unsigned char LEDBuf[6];
//定时中断
Timer0() interrupt 1
{
t1s++;
if(4000 == t1s)
{
t1s =0;
T1S_FLG = 1;
}
}
void delay(unsigned int i)
{
while(i--);
}
//显示子函数
display()
{
unsigned char i;
unsigned char outbit;
outbit = 0x01; // 从右边开始显示
for (i = 0; i < 4; i++)
{
LEDBIT = 0x00; // 关所有LED
LEDSEG = LEDMAP[LEDBuf[i]];
LEDBIT = outbit;
delay(100);
outbit <<= 1; // 显示下一位
}
}
/////////////////////////////////////////////////////////////////////////////
//DS18B20驱动
//初始化DS18B20步骤:
// 1)总线拉低,并延时480us-960us
// 2)总线拉高,等待回应,如DS18B20为“0”则初始化成功,
// 如等待60us仍无回应,则DS18B20不存在
Init_DS18B20(void)
{
bit re = 0;
unsigned char temp = 30;
DS18B20 = 1;
_nop_(); //无需精确
_nop_();
DS18B20 = 0; //拉低
delay(80); // ★务必在480us-960us之间
DS18B20 = 1; //拉高总线
delay(1); //无需精确
while(temp--) //等待60us以上
{
re = DS18B20; //如果x=0则初始化成功
if(0 == re)
{
DS18B20_FLG = 1;
delay(20); //无需精确
return(0);
}
}
}
//读DS18B20一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i = 0;
unsigned char d = 0;
for (i=8;i>0;i--)
{
DS18B20 = 0; // 给脉冲信号
d >>= 1;
_nop_();
DS18B20 = 1; // 给脉冲信号
_nop_(); // 需延时10us-14us
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
if(DS18B20 == 1)
{
d = d | 0x80;
}
delay(10); // 需延时60us以上
}
delay(10);
return(d);
}
//写一个字节
Write_DS18B20(unsigned char d)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DS18B20 = 1;
_nop_();
_nop_();
DS18B20 = 0;
_nop_(); // 需延时15us-60us
_nop_();
_nop_();
_nop_(); // ?奇怪:当此处延时超过30us时,会出错
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
DS18B20 = d & 0x01;
delay(7); // 需延时60us-120us
d >>= 1;
}
DS18B20 = 1;
delay(7);
}
//温度返回值被放大100倍
unsigned int TurnTemp(unsigned int temp)
{
int t;
if(temp > 32768) //当读取的温度为负时
{
t = (~temp + 1) * 25 / 4;
TEMP_FLG = 1;
}
else //当读取的温度为正时
{
t = temp * 25 / 4;
TEMP_FLG = 0;
}
return(t);
}
//读取温度
int ReadTemp(void)
{
unsigned char tempLowChar = 0;
unsigned char tempHighChar = 0;
unsigned int tempInt = 0;
int temp = 0;
DS18B20_FLG = 0;
Init_DS18B20(); //步骤1:初始化
if(DS18B20_FLG == 0) //如果没有检测到DS18B20返回
{
return(0);
}
Write_DS18B20(0xCC); //步骤2:跳过读序号操作(单个DS18B20适用)
Write_DS18B20(0x44); //步骤3:启动温度转换
TL0 = 256 - 250; //利用定时器实现1s延时
TH0 = TL0;
TR0 = 1;
T1S_FLG = 0;
while(!T1S_FLG) //步骤4:等待温度转换完成(必须大于500ms)
{
display();
}
TR0 = 0;
DS18B20_FLG = 0;
Init_DS18B20(); //步骤5:初始化
if(DS18B20_FLG == 0) //如果没有检测到DS18B20返回
{
return(0);
}
Write_DS18B20(0xCC); //步骤6:跳过读序号操作(单个DS18B20适用)
Write_DS18B20(0xBE); //步骤7:读取温度寄存器设置(共可读9个寄存器,前两个就是温度)
tempLowChar = Read_DS18B20(); //步骤8:读取温度数据低8位
tempHighChar = Read_DS18B20(); //步骤8:读取温度数据高4位
tempInt = tempHighChar;
tempInt <<= 8;
tempInt = tempInt | tempLowChar;
temp = TurnTemp(tempInt);
return(temp);
}
//DS18B20驱动
/////////////////////////////////////////////////////////////////////////////
//实现四位LED温度显示,其中最高位LED显示温度正负,最低位为温度的一位小数
main()
{
unsigned int t =0;
IE = 0x82; //开1#中断
TMOD = 0x02; //定时工作方式2
while(1)
{
t = ReadTemp();//读温度
if(DS18B20_FLG == 0)
{
LEDBuf[3] = 10;
LEDBuf[2] = 10;
LEDBuf[1] = 11;
LEDBuf[0] = 0; //显示“E0”
}
else
{
if(TEMP_FLG)
{
if(t > 5500)
{
LEDBuf[3] = 10;
LEDBuf[2] = 10;
LEDBuf[1] = 11;
LEDBuf[0] = 1; //显示“E1”
}
else
{
LEDBuf[3] = 13; //显示“-”
LEDBuf[2] = t/1000; //显示温度的十位
LEDBuf[1] = (t/100)%10; //显示温度的个位
LEDBuf[0] = (t/10)%10; //显示温度的小数位
}
}
else
{
if(t > 20000)
{
LEDBuf[3] = 10;
LEDBuf[2] = 10;
LEDBuf[1] = 11;
LEDBuf[0] = 1; //显示“E2”
}
else
{
LEDBuf[3] = 12; //显示“+”
LEDBuf[2] = t/1000; //显示温度的十位
LEDBuf[1] = (t/100)%10; //显示温度的个位
LEDBuf[0] = (t/10)%10; //显示温度的小数位
}
}
}
display();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -