AVR单片机_实验8-基于DS18B20芯片实现电子温度计

曾巧文 发布于:2012-8-10 19:03 分类:AVR单片机 标签: 实验 单片机 AVR

AVR单片机_实验8-基于DS18B20芯片实现电子温度计1 实验目的
1.通过实验,会综合利用各模块做简单的设计。
2.理解掌握DS18B20的驱动方式,以及相关的液晶显示2 实验内容
1、完成DS18B20的初始化、温度的读取
2、设计相应的显示界面,实现电子温度计的现实
3、汉字建议字模取12×12,汉字显示方法建议采用实验六中的现实方式;3 实验预习要求
熟悉温度传感器DS18B20的数据手册,查找与温度传感器应用相关的案例。4 实验步骤
1、启动ICCAVR,新建工程文件“Temp.PRJ”,新建mian.c文件,并main.c文件添加到Temp工程中,并设置project->option->target 下的device configuration 选择ATMega16;
2、利用Application Builder产生相应外设的初始化代码,所用外设主要包括3310液晶所用的SPI接口,PA4、PA5、PA6、PB5、PB7。DS18B20所用的GPIO
3、DS18B20的功能函数见ds18B20.c和delay.c 及相应头文件中。
注:字符、数字和汉字的字模可以用字模软件自动生成。推荐两款字模软件:
LCD3310.exe:专门针对3310液晶模块的字模生成软件,特点是简单方便,直接输入汉字,然后选择字模点阵,最后生成字模即可; 缺点是:只能用于3310液晶的字模生成,不能用于其他LCD模块,无法调节字幕的上下偏移位置;
Pctolcd2002完美版.exe :特点是功能强大,适用范围广,缺点是操作复杂,需要设置生成字模的模式;
4、在main.c文件下添加相应代码,实现在温度的采集以及温度值在3310液晶模块上的显示。选择【Project】->【Rebuild All】编译工程,通过PROGISP程序下载程序到单片机,观察实验现象。


3 完成DS18B20的初始化,温度采集;

#include <iom16v.h>
#include <macros.h>
#include "delay.h"
#include "ds18b20.h"


#define INPUT_DQ()		 DDRA &= ~(1 << 2)		/*设置输入*/
#define OUTPUT_DQ()		 DDRA |= (1 << 2)		/*设置输出*/
#define CLR_DQ()		 PORTA &= ~(1 << 2)		/*置低电平*/
#define SET_DQ()		 PORTA |= (1 << 2)		/*置高电平*/
#define READ_DQ()		 PINA & (1 << 2)		/*读了电平*/

/*DS18B20复位函数*/
unsigned char ds1820Reset(void){
	unsigned char flag;
	OUTPUT_DQ();
	SET_DQ();
	CLR_DQ();
	delay100Us();				/*延时500uS(480-960)*/
	delay100Us();
	delay100Us();
	delay100Us();
	delay100Us();
	SET_DQ();
	INPUT_DQ();
	delay60Us();				/*延时60uS*/
	flag = READ_DQ();
	delay100Us();				/*延时500uS(480-960)*/
	delay100Us();
	delay100Us();
	delay100Us();
	delay100Us();
	return flag;
}

/*DS18B20字节读取函数*/
unsigned char ds1820ReadByte(void) {
	unsigned char i;
	unsigned char value = 0;
	for (i=0; i<8; i++){
		//value >>= 1;
		value = value>>1;
		OUTPUT_DQ();
		CLR_DQ();
		delay10us();					/*延时10uS*/
		SET_DQ();
		INPUT_DQ();
		delay10us();					/*延时10uS*/
		if(READ_DQ()){
			value|=0x80;
		}
		delay60Us();			/*延时60uS*/
	}
	return value;
}

/*DS18B20字节写入函数*/
void ds1820WriteByte(unsigned char value) {
	unsigned char i;
	for(i=0; i<8; i++){
		OUTPUT_DQ();
		CLR_DQ();
		delay5us();					/*延时4uS*/
		if(value & 0x01){SET_DQ();}
		//每次都只写最低位,如果最低位是1的话输出高电平作为写1信号,否则无动作即为0						
		delay60Us();			/*延时80uS*/
		SET_DQ();					/*位结束*/
		//value >>= 1;
		value = value>>1;
	}
}

/*DS8B20读取温度信息*/
unsigned char ds1820ReadTemp(void){
	unsigned char tempH,tempL,tempValue,temp0,temp1;
	/*启动一次转换*/
	ds1820Reset();
	ds1820WriteByte(0xCC);	/*勿略地址*/
	ds1820WriteByte(0x44);	/*启动转换*/
	ds1820Reset();
	ds1820WriteByte(0xCC);	/*勿略地址*/
	ds1820WriteByte(0xBE);	/*读取温度*/
	tempL = ds1820ReadByte(); //读数据 
    tempH = ds1820ReadByte(); 
	temp0 = tempL >> 4;     //只要高8位的低四位和低8位的高四位,温度范围0~99! 
    temp1 = tempH << 4;
	tempValue = temp0 + temp1;     
	return tempValue;
}



4、在3310液晶上实现电子温度计界面,显示效果如下: 第一行:“电子温度计”,空半行,然后接着显示:“温度:23.5 C”。注“23.5”为假设的实测温度值.
#include <iom16v.h>
#include <macros.h>
 
#define  	BYTE	unsigned char															 
#define 	WORD	unsigned int


/********************************************************************************

                            	位变量操作宏定义

********************************************************************************/
#define		BIT_SET(a,b)	a|=BIT(b)
#define		BIT_CLR(a,b)	a&=~BIT(b)
#define		BIT_INV(a,b)   	a^=BIT(b)
#define		BIT_STATUS(a,b) a&BIT(b)


/********************************************************************************

                            	DS18B20操作定义

********************************************************************************/
#define		CLR_DS18B20		BIT_CLR(PORTD,PD6)		//数据线强制拉低
#define		SET_DS18B20		BIT_SET(PORTD,PD6)		//数据线强制拉高,上拉
#define		HLD_DS18B20		BIT_SET(DDRD,PD6)		//Mega16控制总线
#define		RLS_DS18B20		BIT_CLR(DDRD,PD6)   	 	//释放总线
#define		STU_DS18B20		BIT_STATUS(PIND,PD6)		//数据线的状态
void delayUs(unsigned int temp)
{
 	 while(temp--);

}
/**********************************************************************
functionName: BYTE resetDS18B20(void)
description :DS18B20初始化
**********************************************************************/
BYTE OWReset(void)
{
	BYTE errTime=0;
	RLS_DS18B20;		//释放总线
	_NOP();
	HLD_DS18B20;		//Maga16控制总线
	CLR_DS18B20;		//强制拉低
	delayUs(150);		//209.42us
	delayUs(150);		//209.42us 480us
	RLS_DS18B20;	//释放总线,总线自动上拉
	_NOP();			
	while(STU_DS18B20)	
	{
		delayUs(2);	 	//5.15us
		errTime++;
		if(errTime>14)
		return(0x00);		//如果等带大于约 5.15us*20就返回0x00,报告复位失败(实际上只要等待15-60us)
	}
	errTime=0;
	while(!(STU_DS18B20))	
	{
		delayUs(2);	 	//5.15us
		errTime++;
		if(errTime>33)
		return(0x00);		//如果等带大于约 5.15us*50就返回0x00,报告复位失败(实际上只要等待60-240us)
	}
	delayUs(120);
	delayUs(125);
	return(0xff);
}

////////////////////////////////////////////////

unsigned char OWReadBit(void)
{     unsigned char t;
	  	 HLD_DS18B20;	//Maga16控制总线
		CLR_DS18B20;	//强制拉低
		_NOP();
		RLS_DS18B20;		//释放总线,DS18B20会将总线强制拉低
		delayUs(3);
	 if(STU_DS18B20)
		t=1;
		else
		t=0;
		delayUs(8);	 	//14.92us
	    delayUs(8);
		delayUs(8);	 	//14.92us
		RLS_DS18B20;		//释放总线
		 delayUs(12);
		return(t);
		
		
		}
/**********************************************************************
functionName: BYTE readByteDS18B20(void)
description :读DS18B20一个字节
**********************************************************************/
BYTE OWReadbyte(void)
{
	BYTE i;
	BYTE retVal=0;
	RLS_DS18B20;		//释放总线
	for(i=8;i>0;i--)
	{
	 	retVal>>=1;
	  	if(OWReadBit)
		retVal|=0x80; 	
	}
	delayUs(1);	 		//2.71us(大于1us就行了)
	return(retVal);
}
/////////////////////////////////////////
void OWWriteBit(unsigned char temp)
{
        HLD_DS18B20;		//Maga16控制总线
		CLR_DS18B20;		//强制拉低
		 if(temp)
		RLS_DS18B20;		//释放总线
		else
		CLR_DS18B20;		//强制拉低
		delayUs(35);	 	//60us
			 	
		RLS_DS18B20;		//释放总线
		delayUs(50);
		}

/**********************************************************************
functionName: BYTE readByteDS18B20(void)
description :写DS18B20一个字节
**********************************************************************/
void OWWriteByte(BYTE wb)
{
	BYTE i;
	BYTE temp;
	RLS_DS18B20;		//释放总线
	for(i=0;i<8;i++)
	{
		temp=wb>>i;
		temp&=0x01;
		OWWriteBit(temp);	 	
	}
}
///////////////////////////////////////////////
void delayms(void)
{unsigned int i;
int j;
for(j=0;j<10;j++)
{for(i=0;i<40000;i++)
;}
}

/**********************************************************************
functionName: unsigned int readTempDS18B20(void)
description :读DS18B20温度
**********************************************************************/
unsigned int readTempDS18B20(void)
{
	 BYTE tempL,tempH;
	WORD x;
	OWReset();
	OWWriteByte(0xcc); 	//跳过ROM
	OWWriteByte(0x44);		//启动温度转换
	delayms();
	OWReset();
	OWWriteByte(0xcc);		//跳过ROM
	OWWriteByte(0xbe);		//读数据
	tempL=OWReadbyte();
	tempH=OWReadbyte();
	x=(tempH<<8)|tempL;
	return(x);
} 


5 思考题:请查阅相关资料,解释1-wair通信中数据的读取过程。(DS18B20是如何读的?)

主机将数据线从高电平拉低至低电平,1us以上,之后让数据线升为高电平,从而产生读取数据的起始信号,从主机将数据线从高电平拉低至低电平的时间在15ms-100ms,主机读取数据,每个读取数据的周期最短的持续时间为10ms,每个周期与周期之间必须有1ms以上的高电平恢复区

版权所有:《曾巧文博客-关注互联网IT技术,记录生活点滴》 => 《AVR单片机_实验8-基于DS18B20芯片实现电子温度计
本文地址://qiaowen.net/post-1239.html
除非注明,文章均为 《曾巧文博客-关注互联网IT技术,记录生活点滴》 原创,欢迎转载!转载请注明本文地址,谢谢。

有 8504 人浏览,获得评论 0 条

发表评论:

Powered by emlog 粤ICP备12040901号

>>本作品采用-知识共享署名-非商业-禁止演绎-协议-进行许可 |站点地图 | | | | 开放分类目录 |