[51单片机]---DS18B20 温度检测
1,DS18B20
2,DS18B20时序
void ds18b20_reset()
{//ds18b20复位信号 拉低总线750us后释放总线DS18B20_PORT = 0; delay_10us(75); DS18B20_PORT = 1; delay_10us(2);}//为啥需要检测模块?当我们发生了复位,根据时序图,ds18b20将拉低总线60~240us,即为响应
u8 ds18b20_check()
{//ds18b20响应检测u8 time_out = 0;while(DS18B20_PORT && (time_out < 20)){delay_10us(1);time_out++;}//200us超时退出if(time_out >= 20) return 1;elsetime_out = 0;while(!DS18B20_PORT && (time_out < 20)){time_out++;delay_10us(1);}//总线未被上拉拉高,超时退出if(time_out >= 20) return 2;return 0; // 返回0: success
}
初始化时序:拉低总线750us后,释放总线,等待20us可再检测,模块是否回应
写时序:
//写0/1时序:从低位写到高位
void ds18b20_write_byte(u8 dat)
{u8 i =0;u8 temp = 0;for(i =0 ; i<8; i++) {temp = dat&0x01; //写低位->高位 dat>>=1; //移位if(temp){//写1: 拉低总线,等待2个us,后拉高,等待60us,让其模块采样DS18B20_PORT = 0;_nop_();//一个机器周期1us_nop_();//一个机器周期1usDS18B20_PORT = 1;delay_10us(6); }else{//写0:拉低总线60us,模块采样,后释放,等待2us,使总线释放稳定DS18B20_PORT = 0;delay_10us(6);DS18B20_PORT = 1;_nop_();//一个机器周期1us_nop_();//一个机器周期1us}}
}
写1:拉低总线,2个机械周期后释放总线,等待60us后采样
写0:拉低总线,60us后释放,等待2个nop后读取总线
读时序:
u8 ds18b20_read_bit()
{u8 dat = 0;DS18B20_PORT = 0; //拉低_nop_();//一个机器周期1us_nop_();//一个机器周期1usDS18B20_PORT = 1; //释放总线_nop_();_nop_(); //该段时间不能过长,必须在15us内读取数据if(DS18B20_PORT) dat =1;elsedat =0;delay_10us(5);return dat;
}u8 ds18b20_read_byte()
{u8 i =0;u8 temp =0;u8 dat = 0;for(i =0 ;i < 8; i++){temp = ds18b20_read_bit();
// dat >>= 1;
// dat |= (temp << 7); dat = (temp <<7)|(dat >> 1); }return dat;
}
拉低总线2个nop后释放,等待2个nop后,读取总线值
初始化和开始代码:
void ds18b20_start()
{ds18b20_reset();ds18b20_check();ds18b20_write_byte(0xCC);ds18b20_write_byte(0x44);}u8 ds18b20_init()
{ds18b20_reset();return ds18b20_check();
}
基本流程是:复位 —— 发送SKIP ROM(0xCC)—— 发送开始转换指令(0x44)—— 延时 —— 复位 ——发送SKIP ROM (0xCC) —— 发送读取存储器命令(0xBE) —— 连续读取2个字节数据 结束
读取稳定转换代码:
float ds18b20_read_tempture()
{u8 dath =0;u8 datl =0;u16 value = 0;float temp =0;ds18b20_start(); //复位 + SKIP(0xcc 0x44)ds18b20_reset(); //复位ds18b20_check();// 发送SKIP + 读存储器命令ds18b20_write_byte(0xCC);ds18b20_write_byte(0xbe);//连续读出2字节datl = ds18b20_read_byte();dath = ds18b20_read_byte();value = (dath << 8) + datl;if(value&0xf800 == 0xf800) //判断符号位{value =(~value)+1;temp = value*(-0.0625); }else{temp = value*(0.0625); }return temp;
}
配合数码管显示:
u8 Digital_static[17]= \
{0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f,0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};void show_smg_by_index(u8 dat[], u8 pos)
{u8 i =0;u8 pos_temp = pos - 1;for(i = pos_temp; i < 8; i++){switch(i){case 0: LSC=1;LSB=1;LSA=1;break;case 1: LSC=1;LSB=1;LSA=0;break;case 2: LSC=1;LSB=0;LSA=1;break;case 3: LSC=1;LSB=0;LSA=0;break;case 4: LSC=0;LSB=1;LSA=1;break;case 5: LSC=0;LSB=1;LSA=0;break;case 6: LSC=0;LSB=0;LSA=1;break;case 7: LSC=0;LSB=0;LSA=0;break;}//SMG_A_DP_PORT = Digital_static[dat[i - pos_temp]]; SMG_A_DP_PORT = dat[i - pos_temp]; //SMG_A_DP_PORT = dat[0]; delay_10us(100); SMG_A_DP_PORT = 0x00;}
}
主函数代码:
#include "public.h"
#include "ds18b20.h"
#include "diligt_guan.h"int main()
{u8 ret =0;int i = 0;int temp_value = 0;u8 tmp_buf[5];ret = ds18b20_init();while(1){i++;if(i == 50){temp_value = ds18b20_read_tempture()*10;i = 0;delay_10us(50);}if( temp_value < 0){temp_value = -temp_value;tmp_buf[0] = 0x40; }else{tmp_buf[0] = 0x00; }// if (ret==1)
// temp_value = 1111;
// else if(ret == 2)
// temp_value = 2222;tmp_buf[1] = Digital_static[temp_value /1000]; // 0tmp_buf[2] = Digital_static[temp_value %1000/100]; //0x3Ftmp_buf[3] = Digital_static[temp_value %1000%100/10] | 0x80; //point //0x3Ftmp_buf[4] = Digital_static[temp_value %1000%100%10]; // 0show_smg_by_index( tmp_buf, 4);}return 0;
}
总结:
DS18B20 时序较为简单,但是调试起来还是发了很久时间,需要分步骤
① 确认数码管相关代码能否正确显示
② 确认ds1820是否存在