⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ds18b20.c

📁 一款电力行业使用的温湿度控制器源代码 湿度传感器采用HF3223 温度采用DS18B20 单片机采用mega8 编程采用winavr2007
💻 C
字号:
#include "inc/config.h"


#define DQ_18B20 (1<<3) // PD3 
#define DQ_TO_0() (DDRD |= DQ_18B20) // PD3='0' 
#define DQ_TO_1() (DDRD &= ~DQ_18B20) // PD3='float' 
#define DQ_status() (PIND & DQ_18B20) // read PD3 pin 

/* 请认真检查你的AVR微控制器的时钟频率! 特别注意:频率 
* 定义的单位是MHz! 并且请使用浮点数! 假如你的晶振是12MHz, 
* 你应该写成12.0000或12.0之类。 
* 我的实验电路的晶振是8.0000MHz 
*/ 
#ifndef CPU_CRYSTAL 
#define CPU_CRYSTAL (8.0000) 
#endif 

#define  wait_us(us)\
			_delay_loop_2((u16)((us)*CPU_CRYSTAL/4)) 

/*---------------- 函数原型声明 ------------------*/ 
// 1个初始化模块 
void   ds18b20_config(void);       // 配置端口 

// 3个基本模块 
inline BOOL ds18b20_reset(void);   // 复位DS18B20 
void   ds18b20_write(u08 dat);   // 写字节到DS18B20 
u08  ds18b20_read(void);         // 读字节从DS18B20 

// 2个应用模块 
BOOL   convert_T(void);            // 启动温度转换 
u08 read_T(void);         // 读取转换值 


/*------------------------------------------------------- 
*  配置(使能)AVR与DS18B20的接口 
*/ 
void ds18b20_config(void) 
{ 
    DDRD  &= ~DQ_18B20;   // 输入模式(上电时为高电平) 
    PORTD &= ~DQ_18B20;   // 输出锁存器写0,以后不再更改 
} 

/*------------------------------------------------------- 
*    复位1-wire总线,并探测是否有温度芯片DS18B20(TO-92 
*  封装)挂在总线上,有返回SUCC,没有返回FAIL 
*/ 
BOOL _ds18b20_reset(void) 
{ 
    BOOL bus_flag; 

    DQ_TO_0();      // 设置1-wire总线为低电平(占领总线)... 

    /* 现在延迟480us~960us, 与硬件密切相关,但应尽可能选小值(480us), 
       把抖动留给系统(比如在延迟期间发生中断导致延迟变长)。 
     */ 
    wait_us(490);   // 490us 

    cli();          // 下面这段时间要求比较严格,为保险起见,关中断 
    DQ_TO_1();      // 设置1-wire总线为高电平(释放总线) 
     
    /* 这个浮点数是由编译器计算好的,而不是由你的MCU在运行时临时计算的, 
       所以不会占用用户MCU的时间,不必担心(看看前面的宏你就可以确定了) 
     */ 
    wait_us(67.5);  // 最佳时间: 60us+7.5us!(忙延时,只是一种策略) 
     
    // 探测总线上是否有器件     
    if(DQ_status()) bus_flag=FAIL;   // 复位单总线但没有发现有器件在线 
    else bus_flag=SUCC;              // 复位单总线并发现有器件在线 
     
    sei();          // 退出临界代码区(开中断) 

    /* 保证Master释放总线的时间(不是说总线处于高电平的时间)不小于 
       480us即可,这一时间从读总线状态之前就开始了,所以这里把这个 
       时间计算在内。在Master释放总线的前半段,也是被动器件声明它 
       们在线之时。 
     */ 
    wait_us(490-67.5);   // 490-67.5us 

    return(bus_flag); 
} 

/*-------------------------------------------------------- 
*  复位函数冗余处理
*/ 
inline BOOL ds18b20_reset(void)
{
	u08 Cnt = 0;
	while(!(_ds18b20_reset() == SUCC))
	{
		Cnt++;
		if(Cnt > 3)
		return FAIL ;
	}
	return SUCC ;
}

/*-------------------------------------------------------- 
*  写命令或数据到温度芯片DS18B20(发送一个字节) 
*/ 
void ds18b20_write(u08 dat) 
{ 
    u08 count; 

    // 每个字节共8位,一次发一位 
    for(count=0; count<8; count++) { 
        cli();                   // 保证绝对不会发生中断! 
        DQ_TO_0();               // 设置1-wire总线为低电平 
        wait_us(2);              // about 2us 
         
        if(dat&0x01) DQ_TO_1();  // 并串转换,先低位后高位 
        else DQ_TO_0(); 
        dat >>= 1;               // 下一位做好准备 
         
        // 60us~120us(实际不能到120us, 因为其它语句也用时间了!) 
        wait_us(62);             // 62us 
         
        DQ_TO_1(); 
        sei();                   // 恢复系统中断 
        wait_us(2);              // 2us 
    } 
} 

/*--------------------------------------------------------- 
*  从温度芯片DS18B20读配置或数据(接收一个字节) 
*/ 
u08 ds18b20_read(void) 
{ 
    u08 count,dat; 

    dat = 0x00;       // 数据接收准备 
     
    // 每个字节共8位,一次收一位 
    for(count=0; count<8; count++) { 
        cli();        // 保证绝对不会发生中断! 
         
        // 从总线拉低到读总线状态,不能大于15us! 
        DQ_TO_0();    // 设置1-wire总线为低电平(拉低总线以同步) 
        wait_us(2);   // 2us 
        DQ_TO_1();    // 设置1-wire总线为高电平(释放总线) 
        wait_us(4);   // 4us         
        dat >>= 1; 
        if(DQ_status()) dat|=0x80;   // 读取总线电平,先收低位再收高位 
         
        sei();        // 恢复系统中断 
        wait_us(62);  // 必须大于60us 
    } 
    return(dat); 
} 

/*------------------------------------------------------- 
*     我的电路中只有一个器件DS18B20,所以不需要多个器件的ID 
*  识别,跳过之后,启动温度转换,但在启动后,用户应等待几百个 
*  毫秒,才能读到这次的转换值,这是DS18B20的数据手册规定的。 
*  因为温度转换是需要时间的嘛!(^_^) 
*/

BOOL convert_is_succ = FALSE ;

BOOL convert_T(void) 
{ 
    if(ds18b20_reset()==SUCC) {  // 如果复位成功 
        ds18b20_write(0xcc);     // 跳过多器件识别 
        ds18b20_write(0x44);     // 启动温度转换 
		convert_is_succ = TRUE;
		return TRUE ;
    }
	else
	{
		convert_is_succ = FALSE;
		return FALSE ;
	}
} 

/*********************************************************************************************************
** 函数名称: CRC8_Dallas
** 功能描述: DS18B20的CRC8校验
** 输 入: 需校验的值
** 输 出: 单字节CRC结果
** 全局变量: 无
** 调用模块: 
********************************************************************************************************/
		u08 CRC8_Dallas(u08 Data,u08 CRC_Dallas)
{
u08 i;
u08 flag ;
CRC_Dallas^=Data;
for (i = 0; i < 8; i++)
   {
	flag = ( CRC_Dallas & (1<<0) );
  	CRC_Dallas  >>= 1;
    if (flag) CRC_Dallas ^= 0x8c;  // b10001100 es la palabra del CRC (x8 + x5 + x4 + 1)
                                 //  7..43..0  junto con el 1 aplicado a f.
   }
   return CRC_Dallas;
} 

/*------------------------------------------------------- 
*  读取转换后的温度值 
*  我假定DS18B20一定是正确的,所以没有返回有关状态。当你故意 
*  把DS18B20从电路中拔下而能让程序告诉你出错时,你可以自己修 
*  改这段代码! 
*/ 
u08 read_T(void) 
{ 
    u16 value = 0xee01; 
	u08  valueL;
	u08  valueH; 
    u08  crc8;
	u08  Cnt = 0;

	if(convert_is_succ == FALSE)
	{
		return FALSE;
	}

    while(ds18b20_reset()==SUCC) 
	{  							 // 如果复位成功 
        ds18b20_write(0xcc);     // 跳过多器件识别 
        ds18b20_write(0xbe);     // 读暂存器 
    	valueL = ds18b20_read(); // 低字节 
  	 	valueH = ds18b20_read(); // 高字节 
 		value  = ((uint16)valueH<<8) + valueL ; 
		crc8=CRC8_Dallas( valueL,0 );
		crc8=CRC8_Dallas( valueH,crc8 );
		crc8=CRC8_Dallas( ds18b20_read(),crc8 );
		crc8=CRC8_Dallas( ds18b20_read(),crc8 );
		crc8=CRC8_Dallas( ds18b20_read(),crc8 );
		crc8=CRC8_Dallas( ds18b20_read(),crc8 );
		crc8=CRC8_Dallas( ds18b20_read(),crc8 );
		crc8=CRC8_Dallas( ds18b20_read(),crc8 );
		crc8=CRC8_Dallas( ds18b20_read(),crc8 );

		if(crc8 == 0)
		{
			break;
		}
		else
		{
			Cnt++ ;
			if(Cnt > 3)
			{
				value = 0xee02 ;
				break;		
			}
		}
    }

 
	Temperature = value *10/16;
	
	if(	(value & 0xff00) == 0xee00	)
	{
		return FALSE ;
	}
	else
	{
		return TRUE ;
	}
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -