#include <avr/io.h>
#include <util/delay.h>
#include "ds18b20.h"
const prog_uchar matchrom[24]={
0x28,0x19,0x57,0x21,0x02,0x00,0x00,0xa7,
0x28,0xec,0x47,0x21,0x02,0x00,0x00,0x42,
0x28,0x0d,0x61,0x21,0x02,0x00,0x00,0x38};
static void delay_nus(unsigned int n) //N us延时函数
{
unsigned int i=0;
for (i=0;i<n;i++)
_delay_us(1);
}
static void delay_nms(unsigned int n) //N ms延时函数
{
unsigned int i=0;
for (i=0;i<n;i++)
_delay_ms(1);
}
unsigned char test_ds18b20(void)
{
unsigned char i;
SET_DIR_1WIRE; //设置PA2 为输出
SET_OP_1WIRE;
delay_nus(2);
CLR_OP_1WIRE;
delay_nus(480); //480us以上
SET_OP_1WIRE;
CLR_DIR_1WIRE;
delay_nus(80);
if(CHECK_IP_1WIRE) i = 0;
else i = 1;
SET_DIR_1WIRE;
SET_OP_1WIRE;
delay_nus(240); //60~240us
return i;
}
void init_1820(void)//复位函数
{
SET_DIR_1WIRE; //设置PA2 为输出
SET_OP_1WIRE;
delay_nus(2);
CLR_OP_1WIRE;
delay_nus(480); //480us以上
SET_OP_1WIRE;
CLR_DIR_1WIRE;
delay_nus(20); //15~60us
while(CHECK_IP_1WIRE);
SET_DIR_1WIRE;
SET_OP_1WIRE;
delay_nus(240); //60~240us
}
void write_1820(unsigned char x)
{
unsigned char m;
for(m=0;m<8;m++)
{
CLR_OP_1WIRE;
delay_nus(2);
if(x&(1<<m)) //写数据了,先写低位的!
SET_OP_1WIRE;
else
{CLR_OP_1WIRE;}
delay_nus(60); //15~60us
SET_OP_1WIRE;
delay_nus(5);
}
}
unsigned char read_1820(void)
{
unsigned char temp,k,n;
temp=0;
for(n=0;n<8;n++)
{
CLR_OP_1WIRE;
_delay_us(2);
SET_OP_1WIRE;
CLR_DIR_1WIRE;
delay_nus(8);
k=(CHECK_IP_1WIRE); //读数据,从低位开始
if(k)
temp|=(1<<n);
else
temp&=~(1<<n);
delay_nus(60);
SET_DIR_1WIRE;
}
return (temp);
}
void start(void)//全部开始转换
{
init_1820();
write_1820(0xcc);
write_1820(0x44);
delay_nms(800);
}
/************************************************************
此函数用于读取指定ds18b20的温度,返回值的低字节存储整数部分,
高字节低四位存储小数部分,不含符号位
***************************************************************/
unsigned int gettemp(unsigned char number)
{
volatile unsigned char temh,teml,wm0,wm1,wm2,wm3;
unsigned int temp = 0;
start();
match_rom(number);
write_1820(0xbe); //发出读命令
teml=read_1820();
temh=read_1820(); //读数据
wm0=teml>>4;
wm1=temh<<4;
wm2=wm1+wm0;
wm3=wm2/100;
temp = (10 * ((unsigned int)teml & 0x0f) / 16) << 8;//取温度的小数0.1位的数字
temp |= (unsigned int)(wm2 & 0xff);//取温度的整数部分
return temp;
}
/***********************************************
此函数用于读取当前ds18b20中64位rom的值,存入readrom中
************************************************/
/*
void read_rom(void)
{
unsigned char i;
init_1820(); //复位18b20
write_1820(0x33); //写读rom命令
for(i=0;i<8;i++)
readrom[i]=read_1820();
}
*/
/********************************************
此函数用于读取指定ds18b20中9字节ram的值,存入readram中
*******************************************************/
void read_ram(unsigned char number)
{
unsigned char i;
loop:
match_rom(number);
write_1820(0xbe);
for(i=0;i<9;i++)
readram[i]=read_1820();
i=DS18B20_CheckCRC8(readram,9);
if(i!=0x01) goto loop;
}
/**********************************************
此函数用于匹配指定ds18b20的64位rom,
之后可进行相关读写操作等。
**************************************************/
void match_rom(unsigned char number)
{
unsigned char i;
volatile char j;
init_1820();
write_1820(0x55);
for(i=0;i<8;i++)
{
j=pgm_read_byte(matchrom+i+8*number);
write_1820(j);
}
}
/***************************************************
向指定ds18b20中写入TH,和Tl 并copy到eeram中
****************************************************/
void write_ram(unsigned char temph,unsigned char templ,unsigned char num)
{
match_rom(num);
write_1820(0x4e);
write_1820(temph);
write_1820(templ);
write_1820(0x48);
delay_nms(10);
}
unsigned char CRCValue(unsigned char NewData,unsigned char CRCData)
{
unsigned char bitValue; //
unsigned char TempValue; //模拟CRC硬件内部的8位数据寄存器
unsigned char i;
for(i=0; i<8; i++)
{
//新数据位与CRC寄存器的内容的D0位的异或值作为内部通道的输入
bitValue = (NewData ^ CRCData)& 0x01;
//执行X4、X5的异或操作
if(bitValue==0x01)
{
TempValue = CRCData ^ 0x18;
}
else
{
TempValue = CRCData;
}
//CRC寄存器无进位右移
TempValue >>= 1;
//补上进位位,即D0位
if(bitValue==0x01)
{
CRCData = TempValue | 0x80;
}
else
{
CRCData = TempValue;
}
//为处理下一位作准备
NewData >>= 1;
}
return CRCData;
}
/*****************************************************************
此函数用于CRC校验,DataLength为长度,Databuff为缓存区
******************************************************************/
unsigned char DS18B20_CheckCRC8(unsigned char *DataBuff,unsigned char DataLength)
{
volatile unsigned char CRCData;
unsigned char i;
CRCData = 0;
for(i=0; i<DataLength; i++)
{
CRCData = CRCValue(DataBuff[i],CRCData);
}
if(CRCData == 0)
{
return 0x01;
}
else
{
return 0;
}
}