写的不知道好很差,有什么不对的地方还请指出,谢了。算法
一、本节基于DS18B20 1总线通信。函数
二、驱动DS18B20,代码3个:初始化DS18B20、写1字节、读1字节。编码
三、运用DS18B20,接口有7个:读取ROM编码、配置高温报警低温报警及精度、温度转换、拷贝寄存器值到EEPROM、召回EEPROM值到寄存器里、读取DS18B20的状态(好像没有什么用)、读取DS18B20的温度(float类型,精度自行选择)。spa
四、温度读取出来后用数码管来显示小数,目前数码管显示小数有点小问题。这个问题之后在解决。code
五、DS18B20对时序有要求,故代码里有加入延迟处理。接口
#ifndef __DS18B20_H__ #define __DS18B20_H__ #include <reg52.h> sbit wire = P2^2;//GPIO P2.2 extern unsigned char ROM[8]; //bit DS18B20_RST(void); //一、复位初始化DS18B20,若是返回0则初始化失败 //void write_1_byte_DS18B20(unsigned char); //二、向DS18B20写1字节 //unsigned char read_1_byte_DS18B20(void); //三、读DS18B20 1字节 以前的读取多移动了一位,哎 sb了 void view_DS18B20(void);//四、读取DS18B20 ROM编码 //0x33表示读取64位ROM编码0x55表示匹配ROM对应的器件0xf0表示搜索ROM void acc_DS18B20(char TH, char TL, unsigned char z);//五、配置一个器件的TH高温报警温度和TL低温报警温度和温度精度z void convert_DS18B20(unsigned char); //六、转换温度,x为选择使用的精度9位 10位 11位 12位,默认12位 void copy_acc_EEPROM_DS18B20(void); //七、拷贝配置好的寄存器的值到EEPROM里 void recall_EEPROM_DS18B20(void);//八、召回EEPROM里的3个字节数据到寄存器对应里面(高温、低温、精度) bit wire_status_DS18B20(void); //九、读取DS18B20反馈状态 1bit 这个好像没什么用处 float read_temp_DS18B20(unsigned char);//十、读取DS18B20的温度,输入选择的精度9位 10位 11位 12位 9 10 11 12,默认12位 #endif
#include "delay.h" #include <intrins.h> #include "led.h" #include "ds18b20.h" //与DS18B20通信传输数据的时候均是先传送低位最后传送高位 unsigned char ROM[8]; //一、复位初始化DS18B20 bit DS18B20_RST(void) { wire = 0; delay_us(75); //拉低480us复位DS18B20 wire = 1; //释放数据线 delay_us(8); //延迟60us开始判断是否有应答信号 if(wire) //没有应答的话 { delay_us(26);//延迟180us二次判断DS18B20回复存在信号,即应答ACK信号 if (wire)//尚未应答的话 { return 0;//当函数返回0表示DS18B20初始化失败 } else//有应答信号了 { delay_us(26);//延迟180us判断是否器件释放总线 if (wire)//释放总线的话 { delay_us(26);//再次延长180us return 1;//当函数返回1表示DS18B20初始化成功 } else { return 0;//当函数返回0表示DS18B20初始化失败 } } } else//有应答信号了 { delay_us(38);//延长240us if (wire == 1)//若是器件释放总线的话 { delay_us(38);//再次延长240us return 1;//当函数返回1表示DS18B20初始化成功 } else { return 0;//当函数返回0表示DS18B20初始化失败 } } } //二、向DS18B20写1字节 void write_1_byte_DS18B20(unsigned char x) { unsigned char i=0; for (i;i < 8;i++) { wire = 0; _nop_(); //延迟大于1us wire = x & 0x01; delay_us(8);//延迟60us让DS18B20好采样 wire = 1;//释放总线 x = x >> 1; } } //三、读DS18B20 1字节。。。。马来币以前dat返回数据没有取反,总线没有释放就直接读取数据了 unsigned char read_1_byte_DS18B20(void) { unsigned char i; unsigned char dat=0; for ( i=0 ; i < 8; i ++) { dat = dat >> 1;//放在for循环后面有问题,会向右多移动一位,怪不得以前的数据读取出来有问题 wire = 0; _nop_(); wire = 1;//释放总线,等待DS18B20发送数据到总线上 _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();//延迟个6us时间在采集数据 if(wire)//这个if里面的数不建议写成if(wire);推荐写成if(wire==1); { dat += 0x80; } wire = 1;//释放总线 delay_us(8);//延迟60us } return dat; } //四、读取DS18B20 ROM编码 ,须要读取DS18B20 ROM编码 void view_DS18B20(void) //0x33表示读取64位ROM编码0x55表示匹配ROM对应的器件0xf0表示搜索ROM { unsigned char i; DS18B20_RST(); write_1_byte_DS18B20(0x33); for (i = 0; i < 8; i++) { ROM[i] = read_1_byte_DS18B20(); } } //五、配置一个器件的TH高温报警温度和TL低温报警温度和温度精度z void acc_DS18B20(char TH,char TL,unsigned char z) { unsigned char i;//用来存储精度对应的指令 switch (z) { case 9:i = 0x1f;break; case 10:i = 0x3f;break; case 11:i = 0x5f;break; case 12:i = 0x7f;break; default:i = 0x7f;//默认12位精度 break; } DS18B20_RST();//复位初始化成功 write_1_byte_DS18B20(0xcc); //跳过64位ROM码检测 write_1_byte_DS18B20(0x4e);//配置寄存器指令。马来币这个语句忘记写了 不写那么配置数据坑定写不进去啊 write_1_byte_DS18B20(TH); //配置高温报警温度 最高位为1则表示负温度,为0则表示正温度,±1℃ write_1_byte_DS18B20(TL); //配置低温报警温度 write_1_byte_DS18B20(i); //i=0001 1111 0x1f 9位精度,转换时间93.75ms //i=0011 1111 0x3f 10位精度,转换时间187.5ms //i=0101 1111 0x5f 11位精度,转换时间375ms //i=0111 1111 0x7f 12位精度,转换时间750ms } //六、转换温度,x为选择使用的精度9位 10位 11位 12位,默认12位 void convert_DS18B20(unsigned char x) { DS18B20_RST(); //初始化函数 write_1_byte_DS18B20(0xcc); //跳过64位ROM码检测 write_1_byte_DS18B20(0x44); //温度转换指令-功能命令 //x=0001 1111 0x1f 9位精度,转换时间93.75ms //x=0011 1111 0x3f 10位精度,转换时间187.5ms //x=0101 1111 0x5f 11位精度,转换时间375ms //x=0111 1111 0x7f 12位精度,转换时间750ms switch (x) { case 9: delay_ms(95); break; case 10:delay_ms(190); break; case 11:delay_ms(380); break; case 12:delay_ms(750); break; default:delay_ms(900); break;//默认按照12位精度转换时间 } } //七、拷贝配置好的寄存器的值到EEPROM里 void copy_acc_EEPROM_DS18B20(void) { DS18B20_RST();//初始化函数 write_1_byte_DS18B20(0xcc); //跳过64位ROM码检测 write_1_byte_DS18B20(0x48);//将配置好的寄存器的值拷贝到EEPROM里 } //八、召回EEPROM里的3个字节数据到寄存器对应里面(高温、低温、精度) void recall_EEPROM_DS18B20(void) //召回EEPROM里的3个字节数据到寄存器对应里面(高温、低温、精度) { DS18B20_RST(); //初始化DS18B20函数 write_1_byte_DS18B20(0xcc); //跳过64位ROM码检测 write_1_byte_DS18B20(0xb8); //操做指令将EEPROM里的数据拷贝到寄存器里 } //九、读取DS18B20反馈状态 1bit 这个好像没什么用处 bit wire_status_DS18B20(void) { if(!wire) { delay_ms(1000);//延长1s时间 if (!wire) { return 1;//转换时长太长了,转换失败 } else { LED_shan_suo(2);//led灯闪烁2次 return 0;//转换完成 } } LED_shan_suo(2);//led灯闪烁2次 return 0;//转换完成 } //十、读取DS18B20的温度,输入选择的精度9位 10位 11位 12位 9 10 11 12,默认12位 float read_temp_DS18B20(unsigned char x) { bit a;//临时变量负责判断温度是正数仍是负数,正数为0,负数为1 unsigned char TL = 0; unsigned int TH = 0; float result; DS18B20_RST();//复位器件 write_1_byte_DS18B20(0xcc);//跳过ROM检测指令 write_1_byte_DS18B20(0xbe);//读取暂存寄存器使用的指令 TL = read_1_byte_DS18B20();//将读取的低温8位存起来 TH = read_1_byte_DS18B20();//将读取的高温8位存起来 DS18B20_RST();//强制复位,后面的数据不在读取了 //开始使用算法计算温度 if (TH < 8) { a = 0;//为正数 } else { a = 1;//为负数 } TH <<= 8; TH += TL;//TH = TH | TL; if (a)//判断TH是否是负温度 { TH = ~TH + 1;//先转换为正数,主要是要处理数据 } switch (x) { case 9: TH>>=3;result = TH * 0.5; break;//右移表示精度不须要过高须要匹配9位精度 case 10: TH>>=2;result = TH * 0.25; break;//右移表示精度不须要过高须要匹配10位精度 case 11: TH>>=1;result = TH * 0.125; break;//右移表示精度不须要过高须要匹配11位精度 case 12: TH>>=0;result = TH * 0.0625; break; default:result = TH * 0.0625; break; } if (!a) { return result;//返回正小数 } else { return -result;//返回负小数 } } //十一、搜索是否温度有报警0xec指令 只有温度超过设定值后才会响应