关于DS18B20的驱动,请各位前辈斧正,小菜鸟一枚
本帖最后由 czp123123 于 2012-11-8 15:18 编辑DS18B20的时隙非常重要,我有点把握不好,在什么时候延时多长时间有点糊涂,请大家斧正下面的驱动程序,主要是延时和延时函数,每个延时函数各延时多长时间也是蒙的,
给点好的建议,本人在校学生,希望在做项目的前辈们给点建议,谢谢大家了。。。/********************************************************************/
/********************************************************************/
/********************************************************************/
#include<iom16v.h>
#include<macros.h>
/*****一些宏定义*******/
#define DS18B20_PIN PD4
//PA7输出
#define DS18B20_PIN_SET_OUT() DDRD|=(1<<DS18B20_PIN)
//PA7输入
#define DS18B20_PIN_SET_IN() DDRD&=~(1<<DS18B20_PIN)
//PA7拉高
#define DS18B20_WR1() PORTD|=(1<<DS18B20_PIN)
//PA7拉低
#define DS18B20_WR0() PORTD&=~(1<<DS18B20_PIN)
//读取PA7的电平
#define R_DS18B20() PIND&(1<<DS18B20_PIN)
//跳过ROM
#define SKIP_ROM 0xCC
//转换温度
#define CONVERT_TEM 0X44
//读取暂存器RAM
#define READ_RAM 0XBE
/***延时函数us级***/
void delay_us(unsigned int i)
{
while(i--);
}
/***延时函数ms级*******/
void delay_ms(unsigned int i)
{
unsigned int a;
unsigned char b;
for(a=0;a<i;a++)
for(b=1;b;b++);
}
/****DS18B20的复位初始化****/
void DS18B20_start()
{
unsigned char i;
DS18B20_PIN_SET_OUT; //置位输出口
DS18B20_WR0; //总线产生下降沿,初始化开始
for(i=0;i<20;i++)delay_us(25); //总线保持低电平在480—960微妙之间
DS18B20_WR1(); //总线拉高,主机释放总线,准备接收DS18B20的应答脉冲
DS18B20_PIN_SET_IN(); //配置为输入
delay_us(20); //DS18B20检测到总线上升沿后等待15—60微秒
while(R_DS18B20); //等待DS18B20发出应答脉冲
while(!R_DS18B20); //DS18B20发出存在脉冲,持续60—240微妙
delay_us(20);
DS18B20_PIN_SET_OUT(); //置为输出口
DS18B20_WR1(); //主机释放总线
}
/********向DS18B20中写入一字节的数据或命令**************/
void DS18B20_send(unsigned char temp)
{
unsigned char i;
for(i=0;i<8;i++)
{
DS18B20_WR0(); //总线拉低,启动“写时间片”
delay_us(2); //延时大于1微秒
if(temp&0x01)DS18B20_WR1(); //该位为1的话就拉高总线写1
delay_us(22); //延时至少60微秒,使写入有效
delay_us(22);
delay_us(22);
DS18B20_WR1(); //总线拉高,释放总线,准备启动下一个“写时间片”
temp>>1; //右移一位
delay_us(1);
}
}
/***********从DS18B20中读取一个字节的数据*****************/
void DS18B20_read()
{
unsigned char temp;
for(i=0;i<8;i++)
{
temp>>1; //表明从高位读取
DS18B20_PIN_SET_OUT(); //置为输出口
DS18B20_WR0; //总线拉低,启动读时间片
delay_us(2);
DS18B20_WR1(); //总线拉高,主机释放总线,接下来2-15微秒读有效
DS18B20_PIN_SET_IN(); //端口置为输入
delay_us(2);
if(R_DS18B20())temp|=0x80; //先读高位,为1的话就置1,为零的话不动,循环的时候右移了
delay_us(20); //60微秒后读完成
delay_us(22);
delay_us(22);
DS18B20_WR1(); //总线拉高,主机释放总线,准备启动下一个“读时间片”
}
return temp;
}
/*********初始化DS18B20**************/
void init_DS18B20()
{
DS18B20_start(); //复位
DS18B20_send(SKIP_ROM); //跳过rom匹配
DS18B20_send(0X4e); //设置写模式
DS18B20_send(0x64); //设置温度的上限为100度
DS18B20_send(0x8a); //设置温度的下线为-10度
DS18B20_send(0x7f); //12bit
}
/************读取并计算要输出的温度****************************/
unsigned int ReadTem_DS18B20()
{
unsigned char i;
unsigned char TL;
unsigned intTH;
DS18B20_start(); //复位
delay_ms(1);
DS18B20_send(SKIP_ROM); //跳过序列号检测命令
DS18B20_send(CONVERT_TEM); //命令DS18B20开始转换温度
for(i=0;i<20;i++)delay_ms(10); //延时200ms等待转换完成
DS18B20_start();
delay_ms(1);
DS18B20_send(SKIP_ROM); //跳过序列号检测命令
DS18B20_send(READ_RAM); //发读取温度数据命令
TL=DS18B20_read(); //先读低8位温度数据
TH=ds18B20_read()<<8; //再读高8位温度数据
DS18B20_start(); //不需要其他数据,初始化DS18B20结束读取
return(TH|TL)*10>>4; //温度放大了10倍,*0.0625=1/16=>>4
} //mega128 8M晶振
const uchar CrcTable=
{0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
uchar CRC_OK1(uchar *p1,uchar num)
{
uchar OutData1;
uchar countbyte1;
OutData1=0;
for(countbyte1=1;countbyte1<num;countbyte1++)
{
OutData1=CrcTable;
p1++;
}
p1-=(num-1);
return(OutData1);
}
void delay2(unsigned int x)//1.5us左右
{
while(x)
{
x--;
}
}
void init_1820(void)
{ DDRB|=0x04;
DS18B20_SET;
delay2(25);///
DS18B20_CRL;
delay2(500); //480us以上
DS18B20_SET;
delay2(45);///
DDRB&=~(1<<PB2);
delay2(40); //15~60us
while(PINB&(1<<PB2))
{
;
}
DDRB|=(1<<PB2);
DS18B20_SET;
delay2(160); //60~240us
}
void write_1820(unsigned char x)
{
unsigned char m;
for(m=0;m<8;m++)
{ DDRB|=(1<<PB2);
DS18B20_CRL;
if(x&(1<<m)) //写数据,从低位开始
DS18B20_SET;
else
DS18B20_CRL;
delay2(40); //15~60us
DS18B20_SET;
}
DS18B20_SET;
}
unsigned char read_1820(void)
{
unsigned char temp,k,n;
temp=0;
for(n=0;n<8;n++)
{ DDRB|=(1<<PB2);
DS18B20_CRL;
//delay(20);//
DS18B20_SET;
//delay(30);//
DDRB&=~(1<<PB2);
k=(PINB&(1<<PB2)); //读数据,从低位开始
if(k)
temp|=(1<<n);
else
temp&=~(1<<n);
delay2(80); //60~120us
DDRB|=(1<<PB2);
}
return (temp);
}
//读取温度
ReadTemperature()
{
unsigned char a=0;
unsigned char b=0;
unsigned int t=0;
static unsigned char ErrorT=0;
static unsigned int LastT;
init_1820(); //复位18b20
write_1820(0xcc); // 发出转换命令
write_1820(0x44);
delay2(400);
init_1820();
write_1820(0xcc);//发出读命令
write_1820(0xbe);
Buf18B20=read_1820();
Buf18B20=read_1820();
t=(unsigned int)((Buf18B20*256+Buf18B20));//计算具体温度
Buf18B20=read_1820();
Buf18B20=read_1820();
Buf18B20=read_1820();
Buf18B20=read_1820();
Buf18B20=read_1820();
Buf18B20=read_1820();
Buf18B20=read_1820();
if((CRC_OK1(Buf18B20,10)!=0)||(Buf18B20!=0xFF)){ if(ErrorT<10) ErrorT++; } else {if(ErrorT>0)ErrorT--; LastT=t; }
if(ErrorT==10) t=0x0640; elset=LastT; //传感器检测错误时,返回温度值100度
return(t);
} coleyao 发表于 2012-11-8 15:57 static/image/common/back.gif
//mega128 8M晶振
const uchar CrcTable=
{0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32,...
CRC是做什么用的? slayer_ni 发表于 2012-11-8 21:54 static/image/common/back.gif
CRC是做什么用的?
CRC校验,增加读取温度数据的可靠性:
在某些应用场合,读取的温度数据可靠性不高,为了增加温度数据的可信度,对读取数据进行CRC校验,符合的通过,不符合则丢弃(如实时性要求高则沿用上一次读取数据,然后再重复下一次读取),经过这样的处理,读取温度数据的可信度可得到大幅提高。
页:
[1]