??ds18b20是最常用的数字温度传感器,温度值只能通过一根线读取,体积小,硬件成本低,抗干扰能力强,精度高。温度测量范围 -55°C 到 125°C。
引脚排列如下
-
GND为电源地;
-
DQ输入/输出数字信号;
-
VDD外部供电电源输入端(寄生电源接接地)
内部结构如下:
通过DQ端口可以按照一定的格式读取温度值。
转换成功后的温度值存储在寄存器中
S为符号位,bit0—bit三是存放小数部分,bit4—bit10存储整数部分。
初始化时序
??主机首先发出480-960微秒的低电平脉冲,然后将总线释放为高电平,并在接下来的480微秒内检测总线。如果有低电平,则表明总线上的设备已响应。如果没有低电平,则总线上没有设备响应。
??从器件的DS18B20一上电,就一直在检测总线上是否有480-960微秒的低电平。如果是这样,在总线转换为高电平后,等待15-60微秒,然后将总线电平降低60-240微秒,以响应脉冲,并告诉主机本设备已准备好。如果没有检测到,就一直在等待检测。
读写时序
??所有的写作间隙必须至少60个us相邻两个写作间隙的持续时间必须至少为1us恢复时间。写时序分为0和1两种。
写0时,主机必须继续拉低总线,以满足间隙持续时间的要求(至少60μs),然后释放总线,直到写周期结束。
写1时,主机必须在拉低总线后15μs内释放总线。总线释放后,由于上拉电阻,总线恢复到高电平。
所有的写作操作必须至少有60个us的持续时间,最长不超过120us。相邻两个写作间隙必须至少1us恢复时间。所有的写作操作(写0和写1)都是由拉低总线产生的。
??当总线控制器将数据线从高电平拉到低电平时,读时序必须至少保持1us,然后释放总线。然后在15微秒内对总线进行采样检测,包括前面的降低总线电平1微秒。如果采样期内总线为低电平,则确认为0。如果采样期内总线为高电平,则确认为1。 至少需要60个读时过程才能完成读时过程us只有这样,两个阅读周期至少为1us恢复时间。
读写时序是分时完成的,所以在读写总线时,要按时序阉割。 对ds18b温度转换必须通过以下方式进行 3个步骤 :
(1)每次读写前对ds18b20复位初始化。复位要求主体。 CPU 下拉数据线 500us ,然后释放, DS18B20 收到信号后等待16us ~ 60us 然后发出60左右us~240us 低脉冲,主 CPU 收到此信号后,复位成功。
(2)发送一个 ROM 指令
(3)发送存储指令
\
例如,官方手册给出了一个操作例子
这个例子是总线上有多个设备,每次操作前都要比较身份。如果只有一个设备,可以跳过ROM识别地址。
??接下来可以用代码操作传感器:
#include "ds18b20.h" #include "stm8s103f.h" #include "delay.h" #define DS18B20_DQ_OUT PA_DDR |= 0x08 //输出 #define DS18B20_DQ_IN PA_DDR &= 0xf7 //输入 #define DS18B20_DQ_HIGH PA_ODR |= 0x08 //拉高 #define DS18B20_DQ_LOW PA_ODR &= 0xf7 //拉低 #define DS18B20_DQ_PULL_UP PA_CR1 |= 0x08 //上拉输入 #define DS18B20_DQ_FLOATING PA_CR1 &= 0xf7 ///浮空输入 #define DS18B20_DQ_PUSH_PULL
PA_CR1
|=
0x08
//推挽输出
#define DS18B20_DQ_OPEN_DRAIN PA_CR1 &= 0xf7 //开漏输出
#define DS18B20_DQ_VALUE PA_IDR &0x08 //DQ值
void DS18B20_Init( void )
{
DS18B20_DQ_OUT;
DS18B20_DQ_PUSH_PULL;
DS18B20_DQ_HIGH;
delay_us( 10 );
DS18B20_DQ_LOW;
delay_us( 600 ); /*复位脉冲 */
DS18B20_DQ_IN;
DS18B20_DQ_PULL_UP;
delay_us( 60 );
while ( DS18B20_DQ_VALUE == 1 )
;
delay_us( 400 );
}
void DS18B20_WriteByte(unsigned char _data)
{
unsigned char i = 0;
DS18B20_DQ_OUT;
for ( i = 0; i < 8; i++ )
{
DS18B20_DQ_LOW;
delay_us( 2 );
if ( _data & 0x01 )
{
DS18B20_DQ_HIGH;
}
_data >>= 1;
delay_us( 60 );
DS18B20_DQ_HIGH;
}
}
unsigned char DS18B20_ReadByte(void)
{
unsigned char i = 0, _data = 0;
for ( i = 0; i < 8; i++ )
{
DS18B20_DQ_OUT;
DS18B20_DQ_LOW;
delay_us( 5 );
_data >>= 1;
DS18B20_DQ_HIGH;
DS18B20_DQ_IN;
if ( DS18B20_DQ_VALUE )
{
_data |= 0x80;
}
DS18B20_DQ_OUT;
DS18B20_DQ_HIGH;
delay_us( 60 );
}
return(_data);
}
float DS18B20_ReadTemperature(void)
{
unsigned char temp = 0;
float t= 0;
DS18B20_Init();
DS18B20_WriteByte( 0xcc );
DS18B20_WriteByte( 0x44 );
DS18B20_Init();
DS18B20_WriteByte( 0xcc );
DS18B20_WriteByte( 0xbe );
temp = DS18B20_ReadByte();
t = ( ( (temp & 0xf0) >> 4) + (temp & 0x07) * 0.125);
temp = DS18B20_ReadByte();
t += ( (temp & 0x0f) << 4);
return(t);
}
读取温度时,直接在主函数中调用
#include "stm8s103f.h"
#include "ds18b20.h"
#include "delay.h"
/*系统时钟初始化*/
void SysClkInit(void)
{
//默认值为16M 8分频
CLK_SWR=0xe1; //HSI为主时钟源 16MHz CPU时钟频率
CLK_CKDIVR=0x00; //CPU时钟0分频,系统时钟0分频 16M
}
main()
{
float tem;
SysClkInit();
delay_init(16);
tem=DS18B20_ReadTemperature();
while (1);
}
在使用ds18b20的时候,关键是要保证时序的正确性,如果编写的代码不能正确读出温度值,就需要通过示波器来分析总线上的波形,看看总线上的时序是否和芯片手册中要求的一样。