配置DS18B20温度传感器
配置初始化函数
DS18B20的通信协议为单总线通信协议
首先由主机发送一个复位脉冲约480-960us;然后总线被拉高;在15-60us之后传感器向单片机发送一个约60-240us的存在脉冲,然后总线被拉高。
uint8_t DS18B20_Rst(void)
{
DS18B20_GPIO_Config ();
DS18B20_DQ_1;
DS18B20_Mode_Out_PP();
DS18B20_DQ_0;
Delay_us(750);
DS18B20_DQ_1;
DS18B20_Mode_IPU();
Delay_us(70);
if(DS18B20_DQ_IN() == 0)
{
Delay_us(240);
if(DS18B20_DQ_IN() == 1)
return 0;
}
else
return 1;
}
配置写函数
当主机将数据线从高逻辑级别拉到低逻辑级别时,将启动写入时隙。有两种类型的写时槽:写1时槽和写0时槽。所有写入时隙的持续时间必须至少为60µs,且每个写入周期之间的恢复时间至少为1µs以上。在DQ线下降后,DS18B20在15µs到60µs的窗口中对DQ线进行采样。
如果DQ为高,则会出现Write1。如果DQ为低低,则会出现Write0。
- 要使主机生成写1时隙,必须将数据线拉到逻辑低级别,然后释放,允许数据线在写时隙开始后的15µs内拉到高级别。
- 要使主机生成写0时隙,必须将数据线拉到逻辑低级别,并在低级别保持60µs。
void Write_Byte(uint8_t dat)
{
uint8_t tem = 0,i = 0;
DS18B20_Mode_Out_PP();
for(i = 0; i < 8;i++)
{
tem = dat & 0x01;
dat = dat >> 1;
if(tem == 0)
{
DS18B20_DQ_0;
Delay_us(70);
DS18B20_DQ_1;
Delay_us(5);
}
if(tem == 1)
{
DS18B20_DQ_0;
Delay_us(5);
DS18B20_DQ_1;
Delay_us(60);
}
}
}
配置读函数
当要从DS18B20读取数据时,主机生成读取时隙。当主机将数据线从逻辑高级级别到逻辑低级别时,启动读取时隙。数据线必须保持在低逻辑级别至少1µs;来自DS18B20的输出数据在读取时隙边缘下降后15µs有效。因此,主机必须将DQ引脚拉低,以便从读取槽的开始读取其15µs的状态。在读取时隙结束时,DQ引脚将通过外部上拉电阻重新拉高。所有读取时间槽的持续时间必须至少为60µs,每个读取时间槽之间的恢复时间至少为1-µs。
uint8_t Read_Byte(void)
{
uint8_t dat = 0,num = 0,i = 0;
for(i = 0; i < 8;i++)
{
uint8_t num = 0;
DS18B20_Mode_Out_PP();
DS18B20_DQ_0;
Delay_us(15);
DS18B20_Mode_IPU();
if(DS18B20_DQ_IN() == 0)
num = 0;
else
num = 1;
Delay_us(50);
dat = (num << i) | dat;
}
return dat;
}
供电配置
要搭配硬件电路使用
void Power_Select(uint8_t value)
{
DS18B20_WriteByte(0xB4);
if(value == 1)
DS18B20_WriteByte(1);
if(value == 0)
DS18B20_WriteByte(0);
}
读取芯片ID
void DS18B20_ReadId ( uint8_t * ds18b20_id )
{
uint8_t uc;
DS18B20_WriteByte(0x33); //发送读取ID的命令
for ( uc = 0; uc < 8; uc ++ )
ds18b20_id [ uc ] = DS18B20_ReadByte();
}
跳过匹配ROM
static void DS18B20_SkipRom ( void )
{
DS18B20_Rst();
DS18B20_WriteByte(0XCC);
}
匹配ROM
static void DS18B20_MatchRom ( void )
{
DS18B20_Rst();
DS18B20_WriteByte(0X55);
}
读取温度的两种模式
匹配ROM的情况下
float DS18B20_GetTemp_MatchRom ( uint8_t * ds18b20_id )
{
uint8_t tem_h, tem_l, i;
short s_tem;
float f_tem;
//匹配ROM
DS18B20_Rst();
DS18B20_WriteByte(0X55);
for(i=0;i<8;i++)
DS18B20_WriteByte ( ds18b20_id [ i ] );
DS18B20_WriteByte(0X44); //启动温度转换。
//匹配ROM
DS18B20_Rst();
DS18B20_WriteByte(0X55);
for(i = 0; i < 8; i++)
DS18B20_WriteByte ( ds18b20_id [ i ] );
DS18B20_WriteByte(0XBE); //从暂存器中读取字节和CRC字节。
tem_l = DS18B20_ReadByte(); //tem_l接受低八位
tem_h = DS18B20_ReadByte(); //tem_h接受高八位
s_tem = tem_h << 8;
s_tem = s_tem | tem_l; //s_tem存储温度的初始值
//将温度转换为float型、摄氏度
if( s_tem < 0 )
f_tem = (~s_tem+1) * 0.0625;
else
f_tem = s_tem * 0.0625;
//返回温度的值
return f_tem;
}
不匹配ROM的情况下
float DS18B20_GetTemp_SkipRom ( void )
{
uint8_t tem_h, tem_l;
short s_tem;
float f_tem;
DS18B20_SkipRom ();
DS18B20_WriteByte(0X44); //启动温度转换。
DS18B20_SkipRom ();
DS18B20_WriteByte(0XBE);
tem_l = DS18B20_ReadByte();
tem_h = DS18B20_ReadByte();
s_tem = tem_h << 8;
s_tem = s_tem | tem_l;
if( s_tem < 0 )
f_tem = (~s_tem + 1) * 0.0625;
else
f_tem = s_tem * 0.0625;
return f_tem;
}
配置主函数
int main(void)
{
uint8_t uc, ucDs18b20Id [ 8 ];
SysTick_Init();
LED_GPIO_Config();
DS18B20_GPIO_Config();
USART_Config();
while( DS18B20_Rst() == 1)
printf("\r\n DS18B20初始化成功 \r\n");
printf("\r\n DS18B20初始化失败 \r\n");
DS18B20_ReadId ( ucDs18b20Id ); //读取序列号
printf("\r\n序列号为:0x");
for ( uc = 0; uc < 8; uc ++ ) //打印序列号
printf ( "%.2x", ucDs18b20Id [ uc ] );
while(1)
{
printf ( "温度为: %.1f\r\n", DS18B20_GetTemp_MatchRom ( ucDs18b20Id ) );
Delay_ms(1000);
}
}