数据传感器DS18B20
编写原因:.....暂略
特性:
1. 单独的单线接口,只需1个接口引脚即可通信;
2. 不需要外部元件;
3. 可用数据线供电;
4. 不需备份电源;
5. 测量范围从-55°C ~ +125°C, 增量为0.0625°C;
6. 以12位数字值方式读出温度;
7. 在1s内把温度变换为数字;
知识点:
1. 每个18B20包括唯一的64位长的序号放在ROM中;
开始8位产品类型编码| 接着48位每个器件唯一序号| 最后8位:前56位的CRC
2. 18B20最小单位刻度是0.0625°C, (这里后面解释)
DS18B20的控制流程
根据DS18B20的通信协议,DS18B20只能作为从机,而单片机系统作为主机,片机控制DS18B20完成一次温度转换必须经过3个步骤:
1. 初始化;
2. 发送ROM指令;
3. 发送18B20功能指令。
@以上3个流程还有顺序不能颠倒且缺一不可,每次只要发送任何一条ROM指令,这个流程必须从第1再开始才能发送另外的ROM指令;
一,初始化
/* ******************************************************************************* ** ** GPIO_DQ_Out_Mode(void) ** ** ** 功能描述:设置DQ引脚为开漏输出模式 ** ** 参 数 :无 ** ** 返回值 :无 ** ******************************************************************************* */ void GPIO_DQ_Out_Mode(void) { GPIO_InitTypeDef GPIO_InitStructure ; GPIO_InitStructure.GPIO_Pin = DQ_GPIO_Pin ; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ; //开漏输出 GPIO_Init(DQ_GPIO ,&GPIO_InitStructure) ; } /* ******************************************************************************* ** ** GPIO_DQ_Input_Mode(void) ** ** ** 功能描述:设置DQ引脚为浮空输入模式 ** ** 参 数 :无 ** ** 返回值 :无 ** ******************************************************************************* */ void GPIO_DQ_Input_Mode(void) { GPIO_InitTypeDef GPIO_InitStructure ; GPIO_InitStructure.GPIO_Pin = DQ_GPIO_Pin ; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING ; //浮空输入 GPIO_Init(DQ_GPIO ,&GPIO_InitStructure) ; } /* ******************************************************************************* ** Tx_ResetPulse(void) ** ** ** 功能描述:发送复位脉冲 ** ** 参 数 :无 ** ** 返回值 :无 ** ******************************************************************************* */ void Tx_ResetPulse(void) { GPIO_DQ_Out_Mode() ; DQ_Write_0() ; //复位脉冲 Delay_10us(50) ; //至少保持480us DQ_Write_1() ; //加速上升沿速度 Delay_10us(1) ; } /* ******************************************************************************* ** ** Rx_PresencePulse(void) ** ** ** 功能描述:接受应答信号 ** ** 参 数 :无 ** ** 返回值 :无 ** ******************************************************************************* */ void Rx_PresencePulse(void) { GPIO_DQ_Input_Mode() ; while( DQ_ReadBit()) ; //等待DS18b20应答 while( DQ_ReadBit() == 0) ; //DS18b20将总线拉低60~240us ,然后总线由上拉电阻拉高 Delay_10us(30) ; GPIO_DQ_Out_Mode() ; //接受完成,主机重新控制总线 } /* ******************************************************************************* ** DS18B20_Init(void) ** ** ** 功能描述:初始化DS18b20 ** ** 参 数:无 ** ** 返回值 :无 ** ******************************************************************************* */ void DS18B20_Init(void) { Tx_ResetPulse(); Rx_PresencePulse(); }
Tx_ResetPulse:函数:主机总线发送复位脉冲
PresencePulse函数:主机读取18B20返回的存在脉冲(电平持续60-240us)
二.写时序
/* ******************************************************************************* ** ** Write_OneByte_ToDS18b20(unsigned char data) ** ** ** 功能描述:写一个字节到DS18b20 ** ** 参 数 :无 ** ** 返回值 :无 ** ******************************************************************************* */ void Write_OneByte_ToDS18b20(unsigned char data) { unsigned char i ; GPIO_DQ_Out_Mode() ; for(i=0 ;i<8 ;i++) { if(data&0x01) //低位在前 { //写1 DQ_Write_0() ; //写时间空隙总是从总线的低电平开始 Delay_10us(1) ; //15us内拉高 DQ_Write_1() ; Delay_10us(8) ; //整个写1时隙不低于60us } else { //写0 DQ_Write_0() ; Delay_10us(11) ; //保持在60us到120us之间 DQ_Write_1() ; Delay_10us(1) ; } data >>= 1 ; } }写1 还是写0 由15-60us 的电平区分,所以 DQ_write_0函数后延时长是写0, DQ_write_1函数后延时长是写1;
且是从低位开始写, 所以写完后 data>>=1 ;
三.读时序
/* ******************************************************************************* ** ** Read_OneByte_FromDS18b20(void) ** ** ** 功能描述:从DS18b20读一个字节 ** ** 参 数 :无 ** ** 返回值 :读出的数据 ** ******************************************************************************* */ unsigned charRead_OneByte_FromDS18b20(void) { unsigned char i ,data = 0 ; for(i=0 ;i<8 ;i++) { GPIO_DQ_Out_Mode() ; data >>= 1 ; DQ_Write_0() ; Delay_10us(1) ; GPIO_DQ_Input_Mode() ; Delay_10us(1) ; if(DQ_ReadBit()) { data |= 0x80 ; } Delay_10us(7) ; //等待这一位数据完成传输 } GPIO_DQ_Out_Mode() ; return data ; }
18B20用12位存储温度值,最高位是符号位,下图是其温度存储方式,负温度S=1,正温度S=0;
如:0550H 是+85°C 0191H:+25.0625°C FC90H是-55°C
/* *************************************************************************************************** ** ** Read_Temperature(unsigned char *sign , unsigned char *interger , unsigned int *decimal) ** ** ** 功能描述:读取温度信息 ** ** 参 数:*sign - 保存符号(零上或零下) ** *integer - 保存整数部分 ** *decimal - 保存小数部分 ** ** 返回值 :无 ** *************************************************************************************************** */ void Read_Temperature(unsigned char *sign , unsigned char *interger , unsigned int *decimal) { unsigned char a=0; unsigned char b=0; unsigned int tmp ; DS18B20_Init(); Write_OneByte_ToDS18b20(ROM_Read_Cmd); DS18B20_Init(); Write_OneByte_ToDS18b20(ROM_Skip_Cmd);//跳过读序列号操作 Write_OneByte_ToDS18b20(Convert_T); //启动温度转换 Delay_ms(780);//等待DS18b20转换完成 DS18B20_Init(); Write_OneByte_ToDS18b20(ROM_Skip_Cmd); Write_OneByte_ToDS18b20(Read_Scratchpad); //读取寄存器内容 a= Read_OneByte_FromDS18b20(); //温度低8位 b= Read_OneByte_FromDS18b20(); //温度高8位 Tx_ResetPulse(); //中断数据读取 tmp = (b<<8) | a ; if(b & 0xF0) { *sign = 1 ; //符号部分 tmp = ~tmp+1 ; //二进制数求补 再换成十进制数得到被测温度值 } else { *sign = 0 ; } *interger = (tmp>>4) & 0x00FF; //整数部分 *decimal = (tmp & 0x000F) * 625 ; //小数部分 实际上是乘以0.0625最小步进 同时把小数变成非小数显示 }
代码和数据手册已上传到我的资源:http://download.csdn.net/detail/yx_l128125/6755749