ds18b20 温度传感器
本实验目标
掌握 DS18B20 的驱动程序原理
掌握使用 ds18b20 温度传感器
1. 硬件原理
下图是我们温度传感器的接入引脚, 3.3V 供电, io 口接 P13 的 GP0( GPIO0 的简称 )。
DS18B20 数字温度传感器接线方便,封装成后可应用于多种场合,如管道式,螺纹式, 磁铁吸附式,不锈钢封装式,型号多种多样,有 LTM8877 ,LTM8874 等等。主要根据应 用场合的不同而改变其外观。封装后的 DS18B20 可用于电缆沟测温,高炉水循环测温, 锅炉测温,机房测温,农业大棚测温,洁净室测温,弹药库测温等各种非极限温度场合。耐 磨耐碰,体积小,使用方便,封装形式多样,适用于各种狭小空间设备数字测温和控制领域。
2. 单总线的概念
目前常用的微机与外设之间进行数据传输的串行总线主要有 I2C 总线、SPI 总线和 SCI 总线。其中 I2C 总线以同步串行 2 线方式进行通信(一条时钟线,一条数据线) ,SPI 总 线则以同步串行 3 线方式进行通信(一条时钟线,一条数据输入线,一条数据输出线) , 而 SCI 总线是以异步方式进行通信(一条数据输入线,一条数据输出线) 。这些总线至少 需要两条或两条以上的信号线。
1-wire , 即单 线 总线 ,又 叫单 总线 。近 年来 , 美 国的 达 拉斯 半 导 体公 司 ( DALLASSEMICONDUCTOR ) 推出了一项特有的单总线( 1-Wire Bus)技术。该技术
与上述总线不同,它采用单根信号线,既可传输时钟,又能传输数据,而且数据传输是双向 的,因而这种单总线技术具有线路简单,硬件开销少,成本低廉,便于总线扩展和维护等优 点。
3. ds18b20 相关时序
初始化(复位)时序图:
( 1 ) 先将数据线置高电平“1” 。
( 2 ) 延时(该时间要求的不是很严格,但是尽可能的短一点)
( 3 ) 数据线拉到低电平“0” 。
( 4 ) 延时 750 微秒(该时间的时间范围可以从 480 到 960 微秒) 。
( 5 ) 数据线拉到高电平“1” 。
( 6 ) 延时等待(如果初始化成功则在 15 到 60 微秒时间之内产生一个由 DS18B20 所 返回的低电平“0” 。据该状态可以来确定它的存在,但是应注意不能无限的进行等待, 不然会使程序进入死循环,所以要进行超时控制) 。
( 7 ) 若 CPU 读到了数据线上的低电平“0”后,还要做延时,其延时的时间从发出的高 电平算起(第( 5 )步的时间算起)最少要 480 微秒。
( 8 ) 将数据线再次拉高到高电平“1”后结束。
写 ds18b20 时序图:
( 1 ) 数据线先置低电平“0” 。
( 2 ) 延时确定的时间为 15 微秒。
( 3 ) 按从低位到高位的顺序发送字节(一次只发送一位) 。
( 4 ) 延时时间为 45 微秒。
( 5 ) 将数据线拉到高电平。
( 6 ) 重复上( 1 )到( 6 )的操作直到所有的字节全部发送完为止。
( 7 ) 最后将数据线拉高。
读 ds18b20 时序图:
( 1 )将数据线拉高“1” 。
( 2 )延时 2 微秒。
( 3 )将数据线拉低“0” 。
( 4)延时 3 微秒。
( 5 )将数据线拉高“1” 。
( 6)延时 5 微秒。
( 7)读数据线的状态得到 1 个状态位,并进行数据处理。
( 8)延时 60 微秒。
4. 驱动程序 (需要详细注释的话参考 cc2540/cc2530 的 ds18b20 程序)
关于字符设备驱动程序的使用,我们可以参照点亮 led 灯的那个实验,这里只给出跟 ds18b20 密切相关的驱动程序,详细的程序请查看我们的驱动文件!
//配置连接温度传感器的引脚
#define DS18B20_L #define DS18B20_H #define DS18B20_OUT #define DS18B20_IN #define DS18B20_STA | *GPIO21_0_DATA &= ~(1<<0) //低电平 *GPIO21_0_DATA |= (1<<0) //高电平 *GPIO21_0_DIR |= (1<<0) //输出 *GPIO21_0_DIR &= ~(1<<0) //输入 *GPIO21_0_DATA & 0x01 |
//寄存器定义
volatile unsigned long *GPIO21_0_DIR;
volatile unsigned long *GPIO21_0_DATA;
//复位 ds18b20 传感器
static unsigned char ds18b20_reset(void)
{
unsigned char ret = 0; unsigned char count = 0;
DS18B20_OUT;
DS18B20_H;
udelay(100);
DS18B20_L;
udelay(600);
DS18B20_H;
udelay(45);
DS18B20_IN;
do {
ret = DS18B20_STA;
udelay(1);
count ;
}
while(ret != 0 && count<50);
DS18B20_OUT;
udelay(400);
DS18B20_H;
return ret;
}
//从 ds18b20 读取一个字节
static unsigned char read_byte(void)
{
unsigned char i,byte=0;
DS18B20_OUT;
DS18B20_H;
udelay(100);
for(i = 0; i<8; i )
{
byte >>= 1;
DS18B20_L;
udelay(4);
DS18B20_H;
udelay(2);
if(DS18B20_STA == 1)
byte |= 0x80;
udelay(10);
}
return byte;
}
//向 ds18b20 写入一个字节
static unsigned char write_byte(unsigned char byte)
{
unsigned char i;
DS18B20_OUT;
DS18B20_H;
udelay(100);
for(i = 0; i<8; i )
{
DS18B20_L; if( byte & 0x01 )
DS18B20_H;
else
DS18B20_L;
udelay(40);
DS18B20_H;
byte >>= 1;
}
udelay(10);
}
//从 ds18b20 中读出温度数据
static unsigned int read_temp(void)
{
unsigned int t = 0 , l = 0;
if(ds18b20_reset())
{
printk("step1,reset_ds18b20 error!\n");
return 0;
}
write_byte(0xcc); write_byte(0x44); udelay(4);
if(ds18b20_reset())
{
printk("step2,reset_ds18b20 error!\n");
return 0;
}
write_byte(0xcc);
write_byte(0xbe);
l = read_byte();
t = read_byte();
t <<= 8;
t = l;
return t;
}
5. 应用程序
int main(int argc, char **argv)
{
int fd; float t;
unsigned int tmp = 0; //打开温度传感器驱动模块
fd = open("/dev/ds18b20", O_RDWR | O_NONBLOCK);
if (fd < 0)
{
printf("can't open!\n");
return -1;
}
read(fd, &tmp, sizeof(tmp));
t = tmp * 0.0625; //这里是对 ds18b20 读取结果的精度补偿
printf("the current temperature is %f\n",t);
close(fd);
return 0;
}
6. 实验结果