/*
* 功能描述:DS18B20(单个)驱动程序
* 温度精度:正温度,1位小数,无校验
* EEPROM 0:温度LSB 1:温度MSB 2:TH 3:TL 4:精度寄存器(9~12)8:CRC
* 采用默认值:转换精度默认为12 位,而分辨率是0.625
* DS18B20 复位-->执行ROM 指令-->执行DS18B20 功能指令。
* 硬件平台:ATmega128a 外部晶振:7372800
* 编译环境:WinAVR2011 + AVR Studio4.18
* 作 者:蔡亚辉
* 编写时间:2011-08-03
* 修改记录:
* 版 本:V1.0
*/
#ifndef __DS18B20_H__
#define __DS18B20_H__
#define DS18B20_DQ PA0
#define DS18B20_DDR DDRA
#define DS18B20_PORT PORTA
#define DS18B20_PIN PINA
/* 外部调用函数 */
extern unsigned char ds18b20_read_temprature(unsigned int *p_data);
#endif
/*
* 功能描述:DS18B20(单个)驱动程序
* 温度精度:正温度,1位小数,无校验
* EEPROM 0:温度LSB 1:温度MSB 2:TH 3:TL 4:精度寄存器(9~12)8:CRC
* 采用默认值:转换精度默认为12 位,而分辨率是0.625
* DS18B20 复位-->执行ROM 指令-->执行DS18B20 功能指令。
* 硬件平台:ATmega128a 外部晶振:7372800
* 编译环境:WinAVR2011 + AVR Studio4.18
* 作 者:蔡亚辉
* 编写时间:2011-08-03
* 修改记录:
* 版 本:V1.0
*/
#include <avr/io.h>
#include <util/delay.h>
#include "ds18b20.h"
#define ds18b20_dq_ddr_in() DS18B20_DDR &= ~(1<<DS18B20_DQ)
#define ds18b20_dq_ddr_out() DS18B20_DDR |= (1<<DS18B20_DQ)
#define ds18b20_dq_set() DS18B20_PORT |= (1<<DS18B20_DQ)
#define ds18b20_dq_cle() DS18B20_PORT &= ~(1<<DS18B20_DQ)
#define ds18b20_dq_get() DS18B20_PIN & (1<<DS18B20_DQ)
/* DS18B20 ROM指令 */
#define ds18b20_read_rom() ds18b20_write_byte(0x33) /* 读取ROM */
#define ds18b20_match_rom() ds18b20_write_byte(0x55) /* 匹配ROM */
#define ds18b20_skip_rom() ds18b20_write_byte(0xcc) /* 跳过ROM */
#define ds18b20_search_rom() ds18b20_write_byte(0xf0) /* 搜索ROM */
#define ds18b20_alarm_rom() ds18b20_write_byte(0xec) /* 报警搜索 */
/* DS18B20 暂存器指令 */
#define ds18b20_write_scratchpad() ds18b20_write_byte(0x4e) /* 写暂存器 */
#define ds18b20_read_scratchpad() ds18b20_write_byte(0xbe) /* 读暂存器 */
#define ds18b20_copy_scratchpad() ds18b20_write_byte(0x48) /* 拷贝暂存器 */
#define ds18b20_convert_t() ds18b20_write_byte(0x44) /* 启动温度转换 */
#define ds18b20_recall_e2() ds18b20_write_byte(0xb8) /* 重读E2 */
#define ds18b20_read_power_supply() ds18b20_write_byte(0xb4) /* 读取供电方式 */
/* ds18b20初始化 0:复位成功 1:复位失败*/
static unsigned char ds18b20_reset(void)
{
unsigned char read_data = 0;
/* 控制器产生复位信号 */
ds18b20_dq_ddr_out();
ds18b20_dq_cle();
_delay_us(500); /* 480us~960us */
ds18b20_dq_set();
ds18b20_dq_ddr_in();
_delay_us(80); /* 15~60us */
/* ds18b20产生存在信号 0:复位成功 1:复位失败 */
read_data = ds18b20_dq_get();
_delay_us(500);
ds18b20_dq_ddr_out();
ds18b20_dq_set();
return(read_data);
}
/* ds18b20读一字节 */
static unsigned char ds18b20_read_byte(void)
{
unsigned char i = 0;
unsigned char read_data = 0;
for (i = 0;i < 8;i++) /* LSB -> MSB */
{
read_data >>= 1;
ds18b20_dq_ddr_out();
ds18b20_dq_set();
_delay_us(1); /* 两次读时间片间隔大于1us */
ds18b20_dq_cle(); /* 开始一个读时间片 */
_delay_us(4);
ds18b20_dq_set();
ds18b20_dq_ddr_in();
_delay_us(10); /* 读时间片开始后15us内主机对数据线进行采样 */
if(ds18b20_dq_get())
{
read_data |= 0x80;
}
_delay_us(60); /* 60us~120us */
}
return (read_data);
}
/* ds18b20写一字节 */
static void ds18b20_write_byte(unsigned char data)
{
unsigned char i = 0;
for (i = 0;i < 8;i++) /* LSB -> MSB */
{
ds18b20_dq_ddr_out();
ds18b20_dq_set();
_delay_us(1); /* 两次写时间片间隔大于1us */
ds18b20_dq_cle();
_delay_us(4);
if (data&0x01)
{
ds18b20_dq_set();
}
else
{
ds18b20_dq_cle();
}
_delay_us(80); /* 60us~120us */
ds18b20_dq_set();
data >>= 1;
}
}
/* ds18b20启动转换 */
static unsigned char ds18b20_start(void)
{
if (ds18b20_reset()) return 1; /* ds18b20初始化 0:复位成功 1:复位失败*/
ds18b20_skip_rom(); /* ds18b20跳过地ROM */
ds18b20_convert_t(); /* ds18b20启动转换 */
_delay_us(5);
return 0;
}
/* ds18b20读取温度值 0 成功 1失败 */
unsigned char ds18b20_read_data(unsigned int *p_data)
{
unsigned char temp_l = 0;
unsigned char temp_h = 0;
unsigned int temp = 0;
if (ds18b20_start()) return 1; /* ds18b20启动转换 */
if (ds18b20_reset()) return 1; /* ds18b20初始化 0:复位成功 1:复位失败*/
ds18b20_skip_rom(); /* ds18b20跳过地址 */
ds18b20_read_scratchpad(); /* ds18b20读取温度寄存器 */
temp_l = ds18b20_read_byte(); /* 温度低位 */
temp_h = ds18b20_read_byte(); /* 温度高位 */
if (ds18b20_reset()) return 1; /* ds18b20初始化 0:复位成功 1:复位失败*/
temp = temp_h;
temp <<= 8;
temp |= temp_l;
temp = temp*0.625;
if ((temp_h&0x80) == 0x80) return 1;/* 不检测负温度 */
*p_data = temp;
return 0;
}
/* ds18b20读取温度值*/
unsigned char ds18b20_read_temprature(unsigned int *p_data)
{
unsigned int temp = 0;
if (!ds18b20_read_data(&temp))
{
*p_data = temp;
return 0;
}
else
{
return 1;
}
}