📄 ds18b20.c
字号:
/*******************************************************************************
*
*file: DS18B20.c
*
*功能描述:DS18B20温度传感器的驱动
*编写人员:传承科技 吴明显
*编写日期:2009/01/10
*
*第一次修改人员:
*第一次修改日期:
********************************************************************************/
#include<reg51.h>
#include"inc/define.h" //数据类型定义
#include"inc/exactdly.h" //精确延时函数
#include"inc/ds18b20.h"
/*给ROM命令字取个易记的名称 */
#define DS18B20_READ_ROM 0x33 //读取ROM中的64位序列号及CRC
#define DS18B20_MATCH_ROM 0x55 //让总线控制器选取多个DS18B20中的特定一个
#define DS18B20_SKIP_ROM 0xCC //跳过ROM命令字直接对RAM进行操作
#define DS18B20_SEARCH_ROM 0xF0 //用以获取总线上所有DS18B20的64位序列号及CRC
#define DS18B20_ALARM_SEARCH 0xEC //搜索有报警的所有DS18B20
/*给RAM命令字取个易记的名称 */
#define DS18B20_CONVERT_TEMPERT 0x44 //开始温度转换
#define DS18B20_RD_SCRATCHPAD 0xBE //读取暂存器和CRC中的值,共9个字节
#define DS18B20_WR_SCRATCHPAD 0x4E //把字节写入暂存器的地址2和3--报警触发
#define DS18B20_CP_SCRATCHPAD 0x48 //把暂存器内容(报警触发)拷贝到非易失的EEPROM
#define DS18B20_RECALL_EEPROM 0xB8 //把EEPROM中值召回暂存器
#define DS18B20_RD_POWER_MODE 0xB4 //用以判断DS18B20的供电方式
/*The DS18B20s' ROM Serial NUmbers */
u8 code DS18B20_NO[DS18B20_MAX_COUNT][8] =
{{0x28,0x30,0xC5,0xB8,0x00,0x00,0x00,0x8E},
{0x28,0xE5,0xE0,0xC9,0x01,0x00,0x00,0x07}};
u8 gActive_DS18B20 = 0;
/*******************************************************************
*功能描述:DS18B20复位及存在检测(通过存在脉冲判断有无正常工作的DS1820)
*函数名称:Reset
*函数参数:
*返回值: 0 存在正常工作的DS18B20;其他 不存在正常工作的 DS18B20
*注意事项:
********************************************************************/
u8 Reset()
{
u8 flag=0;
DS18B20_DQ = 0; //单片机拉低总线以产生复位脉冲
Delay200us(); //延时480us--960us完成复位
Delay200us();
Delay200us();
DS18B20_DQ = 1; //单片机释放总线
Delay50us(); //等待60--240us
Delay10us();
flag=DS18B20_DQ; //低电平表示有DS18B20回应
Delay200us(); //延时至少240us等待总线恢复
Delay200us();
return flag;
}
/**********************************************************
*功能描述:写一个字节数据到DS18B20
*函数名称:InputByte
*函数参数:
*返回值:
*注意事项:
**********************************************************/
void InputByte(u8 ibyte)
{
u8 i;
u8 delay;
for (i=8;i>0;i--)
{
DS18B20_DQ = 0; //拉低总线,产生写信号
for(delay=2;delay>0;delay--) ; //延时4us
DS18B20_DQ = ibyte&01; //发送1位
Delay50us(); //写时序至少要60us--120us
Delay50us();
DS18B20_DQ = 1; //释放总线,等待总线恢复
ibyte>>=1; //准备下一位数据的传送
}
}
/**********************************************************
*功能描述:从DS18B20中读出一个字节数据
*函数名称:OutputByte
*函数参数:
*返回值:
*注意事项:
**********************************************************/
u8 OutputByte()
{
u8 i,delay;
u8 obyte=0;
for (i=8;i>0;i--)
{
obyte>>=1;
DS18B20_DQ = 0; //拉低总线,产生读信号
for(delay=2;delay>0;delay--); //延时4us
DS18B20_DQ = 1; //释放总线,准备读数据
for (delay=4;delay>0;delay--); //延时8微秒读数据
if (DS18B20_DQ == 1)
obyte |= 0x80;
Delay50us(); //延时100us
Delay50us();
DS18B20_DQ = 1; //拉高总线,准备下一位数据的读取
}
return obyte;//返回读到的数据
}
/**********************************************************
*功能描述:从单总线上所有DS18B20中选中一个进行后续操作
*函数名称:SelectOne
*函数参数:
*返回值:
*注意事项:在总线上只有一个DS18B20时,可以用不提供序列号使用
* 此器件,只要置同文件中的宏ONLY_ONE为1即可
**********************************************************/
void SelectOne( )
{
u8 i;
if(1==ONLY_ONE)
{
Reset(); //复位
InputByte(DS18B20_SKIP_ROM); //跳过ROM命令,当总线上只有一个DS18B20时此命令可简化操作
}
else
{
Reset(); //复位
InputByte(DS18B20_MATCH_ROM); //DS18B20匹配,后跟64位序列号用以选中总线上特定DS18B20
for(i=0;i<8;i++)
InputByte(DS18B20_NO[gActive_DS18B20 ][i]);
}
}
/**********************************************************
*功能描述:从给定的一组数据产生一个8位的CRC码
*函数名称:CRCGenerate
*函数参数:
*返回值:
*注意事项:要把给定数据的低字节存在数组的低地址
**********************************************************/
u8 CRCGenerate(u8 * to_data,u8 num)
{
u8 i;
u8 crc_data;
crc_data=0;
for(i=0;i<num * 8;i++)
{
u8 xor_l,xor_m,xor_r;
xor_r=((to_data[i/8] >> i%8) & 0x01) ^ (crc_data & 0x01);
xor_l=((crc_data >> 4) & 0x01) ^ xor_r;
xor_m=((crc_data >> 3) & 0x01) ^ xor_r;
crc_data >>=1;
if(1==xor_r)
crc_data |= 0x80;
else
crc_data &= 0x7F;
if(1==xor_l)
crc_data |= 0x08;
else
crc_data &= 0xF7;
if(1==xor_m)
crc_data |= 0x04;
else
crc_data &= 0xFB;
}
return crc_data;
}
/**********************************************************
*功能描述:获取暂存器中的所有数据--包括CRC
*函数名称:GetRAMData
*函数参数:ramData 指向接收暂存器数据数组的指针
*返回值:
*注意事项:从DS18B20中读出的值全以unsigned char 形式保存在数
* 组中,有符号数一补码形式存储
**********************************************************/
void GetRAMData(u8 * ramData)
{
u8 i,j;
SelectOne();
InputByte(DS18B20_CONVERT_TEMPERT); //温度转换命令
for(i=100;i>0;i--) //完成温度转换至少需要750ms
for(j=50;j>0;j--)
Delay200us();
SelectOne();
InputByte(DS18B20_RD_SCRATCHPAD); //读DS1820温度暂存器命令
for(i=0;i<9;i++)
ramData[i]=OutputByte(); //获取温度数据和报警设置
}
/**********************************************************
*功能描述:获取当前温度并根据参数决定是否进行CRC校验
*函数名称:GetTempert
*函数参数:do_crc 赋值1时进行CRC校验,否则不进行
*返回值:获取温度方法1:
* tempert_value = tempert/16.0
* 获取温度方法2:
* tempertH = tempert/16; //温度值整数部分
* tempertL = tempert & 0x0F //温度值小数部分
*注意事项: DS18B20的有效温度值为-55——128;本函数以返回
* -64即-0x8400表示CRC验证未通过,即获取的温度错误
**********************************************************/
s16 GetTempert(u8 do_crc)
{
s16 tempert;
u8 crc_data=0;
u8 ramData[9]={0};
GetRAMData(ramData);
tempert =(ramData[1] << 8) + ramData[0]; //提取温度数据
if(1 == do_crc)
{
crc_data=CRCGenerate(ramData,8);
if(crc_data == ramData[8])
return tempert;
else
return -0x8400;
}
return tempert;
}
/**********************************************************
*功能描述:设置报警温度上限值和下限值
*函数名称:SetAlarm
*函数参数:Alarm_H 当温度高于这个值时触发报警
* Alarm_L 当温度低于这个值时触发报警
*返回值:
*注意事项:
**********************************************************/
void SetAlarm(s8 Alarm_H,s8 Alarm_L)
{
u8 i;
SelectOne();
InputByte(DS18B20_WR_SCRATCHPAD); //将温度报警触发写入暂存器的地址2、3
InputByte(Alarm_H);
InputByte(Alarm_L);
SelectOne();
InputByte(DS18B20_CP_SCRATCHPAD); //将暂存器中的报警触发值写入ROM相应位置
for(i=50;i>0;i--)
Delay200us(); //写ROM需要一定时间
SelectOne();
InputByte(DS18B20_RECALL_EEPROM); //将ROM中报警触发值召回到暂存器
}
/**********************************************************
*功能描述:获取当前总线上唯一DS18B20的序列号
*函数名称:ReadSerialNO
*函数参数:serialNO 用以传递64位序列号
* do_crc 赋值1时进行CRC校验,否则不进行
*返回值:返回0表示校验正确,1为不正确;不进行校验时总返回0
*注意事项:本函数是一个工具函数,可以在总线上只有一个DS18B20时
* 获取他的64位序列号
************************************************************/
u8 GetSerialNO(u8 * serialNO,u8 do_crc)
{
u8 i;
u8 crc_data;
Reset(); //复位
InputByte(DS18B20_READ_ROM);
for(i=0;i<8;i++)
serialNO[i]=OutputByte();
if(1 == do_crc)
{
crc_data=CRCGenerate(serialNO,7);
if(crc_data == serialNO[7])
return 0;
else
return 1;
}
return 0;
}
/*
void DS18B20_alarmSearch()
{
bit search_direction =0;
bit last_device_flag =0;
bit last_discrepancy =0;
bit id_bit,id_bit_cmp;
u8 id_bit_num;
u8 last_zero=0;
byte Rom_Value[8] = {0};
Reset();
InputByte(0xF0); //Search ROM命令
for(id_bit_num=1;id_bit_num !=64;id_bit_num++)
{
id_bit=DS18B20_outputBit();
id_bit_cmp=DS18B20_outputBit();
if(1==id_bit && 1==id_bit_cmp) //总线上没有传感器了
{
break;
}
else if(1==id_bit && 0==id_bit_cmp) //参与搜索传感器的ROM 相应位为1
{
search_direction=1;
}
else if(0==id_bit && 1==id_bit_cmp) //参与搜索传感器的ROM 相应位为0
{
search_direction=0;
}
else if(0==id_bit && 0==id_bit_cmp) //参与搜索传感器的ROM 相应位既有0 又有1
{
search_direction=0;
}
if(0==search_direction)
Rom_Value[id_bit_num/8] |= 0<<(id_bit_num%8);
else
Rom_Value[id_bit_num/8] |= 1<<(id_bit_num%8);
DS18B20_inputBit(search_direction);
}
} */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -