单片机温度检测报警程序(ds18b20)
程序采用数字温度采集芯片 ds18b20 获取温度 分辨率为12位 可以由此程序获的更低分辨率温度
ds18b20 只有三个i/o接口 其中两个为电源引脚 一个为数据总线
只需要一条口线通信 简化了分布式温度传感应用 无需外部元件 可用数据总线供电
电压范围为3.0 V至5.5 V 无需备用电源 测量温度范围为-55 ° C至+125 ℃
ds18b20 相关介绍:ds18b20 百度百科
Proteus 仿真:
Code:
#include <reg51.h>
#include <math.h>
#define uchar unsigned char // 宏定义uchar 为无符号字符
#define uint unsigned int
sbit DQ=P2^3;
sbit alarm =P3^4; //温度告警标志位
sbit test = P1^0;
unsigned long temp; //温度值
uchar tempH,tempL,tempSign; //ds18b20 读取的温度高位 和低8位 ,最高上限温度和最低下限温度,温度符号
signed long setMax=10;
signed long setMin=-10;
float precision=0.0625; //温度精度(默认12位)
uchar seg[8]={0}; // eg. -100.0625
// 延时函数
void delay(uint t) //最大65ms 2^16
{
/TMOD = 0x01; //启用T0 计时器 工作方式1
TH0 = (65536 - t )/256;
TL0 = (65536 - t )%256;
EA = 0; //禁止中断
TR0 = 1; //开始T0计数
while( TF0 == 0);
TF0 = 0; // 清除T0 溢出标志位
TR0 = 0; //关闭T0计数/
while(t–);
}
// ds18b20 初始化函数
uchar init(void)
{
uchar feedback;
DQ = 0 ;
delay(100);
DQ = 1;
/while(DQ); //用于获取反馈信号,返回0为成功,返回1为初始化失败
feedback = DQ;/
delay(25);
//return feedback; //返回0复位成功,返回1复位失败
}
// 写函数
void write(uchar var) //先输出低位,再输出高位
{
uchar i;
for(i=8;i>0;i–)
{
DQ = 0;
DQ = var&0x01; // 获取最后一位数据写入数据线
delay(5);
//(DQ == 1)? delay(10):delay(70); //延时保证ds18b20 采样。写入为 1 15us 内需释放数据线;写入为 0 至少延时 60us;
DQ = 1;
var >>= 1; //右移一位
}
//delay(5);
}
// 读函数
uchar read( void )
{ //先读取低位,再读取高位
uchar feedback = 0;
uchar i;
for(i=8;i>0;i–)
{
DQ = 0;
feedback >>= 1; // 右移
DQ = 1; // 数据线拉低15us内 释放数据线
//delay(1);
if(DQ){ feedback |= 0x80;} //在feedback 在高位写入1 等待右移处理
delay(5);
}
return feedback;
}
// 配置ds18b20 参数说明:(最高温度,最低温度)
//暂不可用
void setConfig(char th,char tl)
{
uchar precision;
init();
write(0xcc);
write(0x4e);
write(th); //默认最高温度为+125
write(tl);//默认最低温度为-55
}
// 温度超限报警处理
void warning()
{
uchar maxSign=0,minSign=0; //最高温度和最低温度符号
if(setMax > 0)
{
maxSign = 1;
}
if(setMin > 0)
{
minSign = 1;
}
if( temp < labs(setMin)10000 && tempSign <= minSign ) //小于下限温度
{
alarm=0;
delay(100);
alarm=1;
delay(100);
}else{
alarm =0;
}
if( temp > setMax10000 && tempSign >=maxSign ) //大于上限温度
{
alarm=0;
delay(100);
alarm=1;
delay(100);
}else{
alarm =0;
}
}
// 温度显示处理,转换 tampH 和 tempL ,写入数组 seg[8], 得出十进制 温度 temp
void convert()
{
uint tempC; //补码温度
uchar seg7; //温度符号位
tempC = tempH256.0 + tempL;
//tempC=tempH<<8;
//tempC|=tempL;
if(tempC > 0x0800)
{
seg7 = 0x40; //温度为负温度
tempSign = 0;
temp = (~tempC + 1); // 补码求原码,取反加一
temp=tempprecision;
}else{
tempSign = 1;
seg7 = 0x00; // 温度为正
temp = tempC ;
temp=tempprecision10000; //放大10000倍,用于取余获取各位数值
}
//temp = 1234567;
seg[7] = seg7;
seg[6] = temp/1000000;
seg[5] = temp%1000000/100000;
seg[4] = temp%1000000%100000/10000;
seg[3] = temp%1000000%100000%10000/1000;
seg[2] = temp%1000000%100000%10000%1000/100;
seg[1] = temp%1000000%100000%10000%1000%100/10;
seg[0] = temp%1000000%100000%10000%1000%100%10;
}
//数码管动态显示 ,读取数组seg[8]
void ledShow()
{
uchar i=0,m,led;
uchar tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //共阴数码管 0-9
uchar tabPoint[] = {0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; //共阴数码管 0-9 带小数点
do{
m=seg[i];
if( i == 4 ) //数码管第四位包含小数点 单片机开发板 数码管和proteus 仿真不同
{
led = tabPoint[m];
}else if( i==7 ){ //符号位跳过译码
led = seg[7];
}else{
led = tab[m];
}
P2 = i ; //送位码 单片机开发板 数码管和proteus 仿真不同
P0 = led; //送段码
delay(100);
i++;
warning();
}while(i<8);
}
//从ds18b20 获取温度,获取 tempH 和 tempL
void getTemp()
{
init();
write(0xCC); //跳过rom搜索
write(0x44); //启动温度转换
delay(100); //温度转换最多750ms
init();
write(0xCC);
write(0xBE); //读出ds18b20 内部RAM 9直接内容
delay(100);
tempL = read(); //读出温度低字节
tempH = read(); //读出温度高字节
//tempMax = read(); //读取高温触发器
//tempMin = read(); //读取低温触发器
}
void main()
{
while(1){
getTemp();
convert();
ledShow();
}
}