`

51单片机学习笔记:DS18B20测温程序

阅读更多

 

#include "my51.h"
#include "smg.h"
#include "ds18b20.h"

void main()			  //测试 ,6位数码管显示温度值
{
    u8 i=0;
    u16 temp=0;
    while(1)
    {	
		temp=ds18b20_readTemperaData();
		for(i=0;i<100;i++)
		{
			displaySMG(ds18b20_processTempData(temp)); 	
		}		    
    }
}

 

#ifndef		_DS18B20_H   
#define		_DS18B20_H
#include   "my51.h"
#include   "smg.h"

extern u8 smgWela[7];			  //数码管位选数据
sbit DQ=P2^2;					  //总线定义
bool ds18b20_init();              //初始化函数
u8*  ds18b20_processTempData(u16 temp);//将temp数据处理成数码管可显示数据
u16  ds18b20_readTemperaData();   //读温度
u8 	 ds18b20_readByte() ;         //读一个字节
void ds18b20_writeByte(u8 dat);   //mcu向18b20写一个字节

#endif

 

#include "ds18b20.h"

/******************************************************************
当主机总线t0时刻从高拉至低电平时就产生写时间隙
从to 时刻开始的1us之后,15us之前将所需写的位送到总线上
DSl820 在t0后的15-60us 对总线采样若低电平写入的位是0 ,若高电平写入的位是1 
连续写2 个位之间的间隙应大于1us 
写1,总时间大于60us,在t0开始延时1us就可以写1,15us之后ic来采样,采样时间最大45us
写0,总时间是60~120us,15~60us是ic在采样,120以外就没必要了,mcu总得释放总线吧
不管写1还是写0,大于60us的话,ic肯定已经采样完成了,那mcu就可以释放了
*******************************************************************/
void ds18b20_writeByte(u8 dat)  //mcu向ic写一个字节
{
    u8 i;
	u8 tmep=dat;
    for(i=0;i<8;i++)
    {
        DQ=0;           //产生读写时序的起始信号
        _nop_();        //要求至少1us的延时
        DQ=dat & 0x01; //对总线赋值,从最低位开始写起
        delayXus(10);//延时74us,写0在60~120us之间释放,写1的话大于60us均可释放
        DQ=1;          //释放总线,为下一次mcu送数据做准备,       
		dat>>=1;	   //有效数据移动到最低位,2次写数据间隙至少需1us
    }
}

/**************************************************************************
下降沿产生读时序
整个读时序必须至少有60us的持续时间,相邻两个读时序必须要有至少1us的恢复时间
DS18B20在读时序产生1us后输出数据到总线上,也有可能需要2~3个微秒,但不会更多
而要求主机释放总线和采样总线等动作要在15μs内完成,那么让mcu采样的最佳时机
是读时序产生后的5~13us之间,在15~60us这段时间是18b20的私有时间,它会在这段
时间内的任意时刻释放总线,是不稳定期,我们不要让mcu在这段时间里对总线操作
*******************************************************/
u8 ds18b20_readByte()    //mcu读一个字节
{
    u8 i,value=0;
    for(i=0;i<8;i++)
    {
        DQ=0;                       //起始信号
        value>>=1;                  //顺便延时3~4个机器周期
        DQ=1;                       //mcu释放总线
        _nop_();_nop_();_nop_();	//再延时3.3us 
        if(DQ)          
        {
            value|=0x80;//保存高电平数据,低电平的话不用保存,移位后默认是0
        } 
        delayXus(8); //延时60.76us  
    }
    return value;
}

u16 ds18b20_readTemperaData()  //读取温度值
{
    u16 temp=0;
    if(ds18b20_init())
    {
        ds18b20_writeByte(0xcc);      //写指令:跳过rom检测
        ds18b20_writeByte(0x44);     //写指令:温度转换
        //delayms(750);// 转换延时需要750ms以上,我们不等它
		//首次转换未完成时,得到的初始化数据是85度,处理一下就可以了
		//温度转换电路是硬件独立的,不会阻塞初始化功能 
        if(ds18b20_init())
        {
            ds18b20_writeByte(0xcc);  //写指令:跳过检测rom
            ds18b20_writeByte(0xbe);  //写指令:读取温度值
            temp=ds18b20_readByte();  //先读低8位数据
			temp|=(u16)ds18b20_readByte()<<8; //再读高8位数据,然后合并
			temp&= 0x0FFF;	//高4位数据反正没用上,我们用来存放错误码
        }
		else
		{
			led5=0;		 //调试代码
			temp=0x2000; //错误码,初始化失败
		}
    }
	else
	{
		led6=0;			//调试代码
		temp=0x1000;   	//错误码,初始化失败,可能器件损坏
	}
    return temp;
}

bool ds18b20_init()   //初始化
{
    u8 checkState=0;
    DQ=1;             //总线初始状态
    _nop_();_nop_();
    DQ=0;             //mcu先将总线拉低
    delayXus(80);     //延时530us,要求480us~960us的低电平信号
                      //当ic接受到此复位信号后会回发一个存在信号
                      //mcu若要接收此存在信号则先要释放总线,让ic控制该总线
                      //当mcu释放总线后的15~60us之后,ic才向总线发一个低电平信号
                      //该信号存在时间为60~240us
    DQ=1;             //mcu释放总线
    delayXus(10);     //mcu释放15~60us以上,(8+6*10)*1.085=73us,
                      //这时DS18B20已经拉低信号,大约60~240us应答保持时间,
    checkState=DQ;    //在这段60~240us时间内,mcu采样是否有器件响应,0表示有响应
    delayXus(70);     //延时464us,加上之前的73us,共537us
                      //虽然ic在拉低电平60~240us之后,会释放总线,但整个时间至少480us
                      //故我们共用时537us,这样是为了不影响后续的操作                    
    if(checkState)    //checkstate为0说明有器件响应,为1无器件响应
    {
        return FALSE;
    }
    return TRUE;	  //初始化成功
}

u8* ds18b20_processTempData(u16 temp) //返回数码管可直接显示的数据指针
{
	u8 i=0;	
	if(0x0550==temp)	  //如果初始化温度数据是85度的话
	{
		led7=0;		   	  //亮灯报警,调试 
		smgWela[5]=18;	  //当温度是85度,第6个数码管显示负号
		return 	smgWela;  //一般刚上电时能看到这个负号
	}

	if(1==(temp&0x0800))  //检测第11位是否为1,为1是负温度
	{
		temp&=0x07ff;	  //只取第0~10共11个位
		temp=(~temp+1) & 0x07ff;//将补码还原
		smgWela[0]=18;	 //第一个数码管显示18号元素,即负号
	}
	else
	{
		smgWela[0]=dark;  	 //正温度的话这个数码管就不要显示了
	}
    temp=(u16)(temp*6.25);	 //精度的1000倍,我们将小数点另外叠加显示
	if(temp>=10000)
	{
		 smgWela[1]=1;   	 //第二个数码管显示1,是百位上,100度以上啊
	}
	else
	{
		smgWela[1]=dark;     //百位上是0的话不要显示这个0
	}
    smgWela[2]=temp%10000/1000;	   //第三个数码管 十位
    smgWela[3]=temp%1000/100;	   //第四个数码管 个位叠加小数点
    smgWela[4]=temp%100/10;		   //第五个数码管 
    smgWela[5]=temp%10;			   //第六个数码管
	smgWela[6]=0xf7;			   //第4个数码管叠加小数点
	return smgWela;				   //返回数组
}

 

#ifndef _51SMG_H_
#define _51SMG_H_

#include <reg52.h>
#include "mytype.h"
sbit dula =P2^6;  		//段选锁存器控制  控制笔段
sbit wela =P2^7;  		//位选锁存器控制  控制位置

#define dark	0x11//在段中,0x11是第17号元素,0x00是低电平,数码管不亮,即table[17]
#define dotDark 0xff//小数点全暗

void displaySMG(u8* pWela); //数码管显示函数,参数是数组指针

#endif

 

#include "smg.h"
#include "my51.h"

static u8 code table[]= { 		//0~F外加小数点和空输出的数码管编码
	0x3f , 0x06 , 0x5b , 0x4f , // 0 1 2 3
	0x66 , 0x6d , 0x7d , 0x07 , // 4 5 6 7
	0x7f , 0x6f , 0x77 , 0x7c , // 8 9 A B
	0x39 , 0x5e , 0x79 , 0x71 , // C D E F
	0x80 , 0x00 ,0x40           // . 空 负号    空为第17号元素
 };

/*  由于此表只能一次显示一个小数点,故已注释掉,仅供查询
	例如想要第一个和第六个数码管小数点同时点亮,
	则执行 pWela->dot = 0xfe & 0xdf  即可
	u8 code dotTable[]={   //小数点位置,某一位置0时,小数点亮
	0xff ,                 //全暗
	0xfe , 0xfd , 0xfb ,   //1 2 3
	0xf7 , 0xef , 0xdf     //4 5 6                    
};*/

u8 data smgWela[7]={0,0,0,0,0,0,0}; //第一位到第六位,最后一个是小数点位置控制

//P0口的数码管位选控制锁存器只用了低6位,我们保留高2位的数据,留作它用
void displaySMG(u8* pWela)
{
	u8 i=0;	
    //控制6位数码管显示函数,不显示的位用参数dark
    u8 preState=P0|0x3f;  //保存高2位状态,其中最高位是ADC0804的片选信号
	wela=0;dula=0;_nop_();//先锁定数据,防止吴亮及位选锁存器高2位数据被改变
		
	P0=0;  		 	      //由于数码管是共阴极的,阳极送低电平,灯不亮
    dula=1;_nop_();
    dula=0;	  	 	      //段选数据清空并锁定

    P0=preState;  		  //共阴极数码管是阴极置高不亮,低6位置1,高2位保留	
    wela=1;_nop_();		  //注:wela和dula上电默认为1		 
    wela=0;		  		  //位选锁定,初始保留高2位的数据,低6位置高不亮

	for(i=0;i<6;i++)	  //显示6位数码管
	{
		P0=table[pWela[i]]|(((1<<i) & pWela[6])?0x00:0x80);
	    dula=1;_nop_();	     //送段数据,叠加小数点的显示,0x00点亮小数点
	    dula=0;
	    
	   	P0=preState&~(1<<i); //不影响高2位数据,低6位是数码管位选,低电平有效
	    wela=1;	_nop_();	 //送位选号
	    wela=0;	
	    delayms(1);			 //稍作延时,让灯管亮起来			
		{  //消除叠影及误亮,阴极置1不亮,低6位置1,高2位保留并锁定
	        P0=preState;
	        wela=1;	_nop_();			
	        wela=0;	
	    }
	}
}

 

#ifndef _MY51_H
#define _MY51_H
#include <reg52.h>
//#include <math.h>
#include <intrins.h>
#include "mytype.h"


#define high	1   //高电平
#define low		0   //低电平

#define led P1    //灯总线控制

sbit led0=P1^0;     //8个led灯,阴极送低电平点亮
sbit led1=P1^1;
sbit led2=P1^2;
sbit led3=P1^3;
sbit led4=P1^4;
sbit led5=P1^5;
sbit led6=P1^6;
sbit led7=P1^7;	
sbit ledLock=P2^5;	//led锁存的状态,0锁定 ,1不锁定
   
sbit beep=P2^3;     //蜂鸣器

void delayms(u16 ms);
void delayXus(u8 us); //函数执行(8+6x)个机器周期, 即t=(8+6x)*1.085
/////////////////////////////////////////////////////////////////////////////


#endif

 

#include "MY51.h"

void delayms(u16 ms)     //毫秒级软延时函数
{	
	u16 i,j;
	for(i=ms;i>0;i--)
	{
        for(j=113;j>0;j--)
        {}
	}
}

/****************************************************************
若使用12分频模式的mcu,晶振频率为11059200Hz
则每个机器周期用时12/11059200=1.085微秒
keil4编译,在默认的8级优化方式下
参数us=0时,函数执行9个机器周期,即t=9*1.085=9.77 us
参数us!=0时,函数执行(8+6x)个机器周期, 即t=(8+6x)*1.085 us
*****************************************************************/
void delayXus(u8 us)	//微秒级软延时函数
{
	while(us)           //这种写法有利于减小us=0时的机器周期
	{
		us--;
	}
}

 

1
2
分享到:
评论
2 楼 xouou_53320 2014-10-23  
朱凌峰 写道
楼主,你的 "mytype.h"   文件呢?

#ifndef   _MYTYPE_H
#define   _MYTYPE_H

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

typedef float                             f32   ;
typedef double                   d64  ;
typedef float  const                   fc32 ;
typedef double  const               dc64  ;
typedef volatile float                vf32   ;
typedef volatile double             vd64  ;
//typedef volatile float     const   vfc32   ;
//typedef volatile double  const   vdc64  ;
//////////////////////////////////////////////


typedef signed long  s32;
typedef signed short s16;
typedef signed char   s8;


typedef signed long  const sc32;  /* Read Only */
typedef signed short const sc16;  /* Read Only */
typedef signed char  const sc8;   /* Read Only */

typedef volatile signed long  vs32;
typedef volatile signed short vs16;
typedef volatile signed char  vs8;

//typedef volatile signed long  const vsc32;  /* Read Only */
//typedef volatile signed short const vsc16;  /* Read Only */
//typedef volatile signed char  const vsc8;   /* Read Only */


typedef unsigned long  u32;
typedef unsigned short u16;
typedef unsigned char  u8;

typedef unsigned long  const uc32;  /* Read Only */
typedef unsigned short const uc16;  /* Read Only */
typedef unsigned char  const uc8;   /* Read Only */

typedef volatile unsigned long  vu32;
typedef volatile unsigned short vu16;
typedef volatile unsigned char  vu8;

//typedef volatile unsigned long  const vuc32;  /* Read Only */
//typedef volatile unsigned short const vuc16;  /* Read Only */
//typedef volatile unsigned char  const vuc8;   /* Read Only */

typedef enum {FALSE = 0, TRUE = !FALSE} BOOL;

typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;

typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
////////////////////////////////////////////////////////////////////////////////////////////
#define bool BOOL
#define false FALSE
#define true  TRUE


typedef enum {CLOSE = 0, OPEN = !CLOSE} OPEN_CLOSE;
typedef enum {GND = 0, VCC = !GND} GND_VCC;
typedef enum {NO = 0, YES = !NO} YES_NO;
typedef enum {STOP = 0, START = !STOP} START_STOP;
typedef enum {LOCK = 0, UNLOCK = !LOCK} LCOK_UNLOCK;
////////////////////////////////////////////////////////////////////////////////////////////
#define U8_MAX     ((u8)255)
#define S8_MAX     ((s8)127)
#define S8_MIN     ((s8)-128)
#define U16_MAX    ((u16)65535u)
#define S16_MAX    ((s16)32767)
#define S16_MIN    ((s16)-32768)
#define U32_MAX    ((u32)4294967295uL)
#define S32_MAX    ((s32)2147483647)
#define S32_MIN    ((s32)-2147483648)

#endif
1 楼 朱凌峰 2014-10-22  
楼主,你的 "mytype.h"   文件呢?

相关推荐

    51单片机Proteus仿真实例 DS18B20温度传感器实验

    51单片机Proteus仿真实例 DS18B20温度传感器实验51单片机Proteus仿真实例 DS18B20温度传感器实验51单片机Proteus仿真实例 DS18B20温度传感器实验51单片机Proteus仿真实例 DS18B20温度传感器实验51单片机Proteus仿真...

    基于51单片机的DS18B20测温系统

    本篇文章将介绍基于51单片机的DS18B20测温系统设计。 设计所需物品: - 51单片机开发板 - DS18B20数字温度传感器 - 4位LED数码管模块 - 蜂鸣器模块 - 其他相关组件 设计思路: 1. 将DS18B20数字温度传感器连接到51...

    基于51单片机的DS18B20测温程序

    测试温度,数码管显示,精确到小数点两位,非常适合新手学习的,源程序,本人亲测

    51单片机下oled显示ds18b20采集温度

    在51单片机编程中,我们经常遇到各种传感器数据的采集与显示任务,本项目主要涉及了DS18B20数字温度传感器与OLED显示屏的结合使用,以实现温度实时显示的功能。以下是相关知识点的详细介绍: 1. **51单片机**:51...

    龙芯1B:DS18B20测温程序

    《龙芯1B与DS18B20测温程序详解》 在嵌入式系统设计领域,龙芯1B是一款广泛应用的国产CPU,它基于MIPS架构,具备低功耗、高性能的特点,广泛用于物联网、工业控制以及教育科研等场景。而DS18B20则是一款精准的数字...

    多个DS18B20测温的proteus仿真电路及C语言程序设计

    通过这个项目,学习者可以深入理解DS18B20传感器的工作原理,掌握51单片机的C语言编程,以及利用Proteus进行电路和程序的联合仿真。此外,它还涵盖了多传感器系统的设计与管理,这对于理解和开发更复杂的嵌入式系统...

    DS18B20测温程序仿真

    综上所述,"DS18B20测温程序仿真"项目涵盖了单片机编程、数字温度传感器的使用、单线通信协议的理解以及软件仿真的实践操作,对于学习单片机控制和温度测量技术具有很高的价值。通过这个项目,开发者不仅能掌握DS18B...

    ds18b20通用程序.rar_18b20_ds18b20_ds18b20 51单片机_ds18b20 c程序_ds18b2

    标签进一步细化了这个压缩包的内容:“18b20 ds18b20 ds18b20__51单片机 ds18b20__c程序”。这些标签表明程序是针对DS18B20设计的,并且是用C语言编写的,适用于51系列单片机。C语言是一种底层、高效的语言,适合于...

    ds18b20与51单片机接口程序

    标题中的“ds18b20与51单片机接口程序”指的是使用DS18B20数字温度传感器与51系列单片机进行数据交互的编程实践。这一主题涵盖了电子工程、嵌入式系统以及物联网应用等多个领域,下面将详细介绍其中的知识点。 DS...

    单片机C语言程序设计 DS18B20温度传感器实验(有源码)

    单片机C语言程序设计 DS18B20温度传感器实验(有源码)单片机C语言程序设计 DS18B20温度传感器实验(有源码)单片机C语言程序设计 DS18B20温度传感器实验(有源码)单片机C语言程序设计 DS18B20温度传感器实验(有源码)...

    DS18B20测温程序

    【DS18B20测温程序】是一个用于精确测量温度的软件解决方案,它利用了DS18B20这款数字温度传感器。DS18B20是一款单线数字温度传感器,由 Dallas Semiconductor(现Maxim Integrated)制造,能够提供高精度的温度测量...

    DS18B20测温模块_DS18B20测温模块_ds18b20_

    1. **高精度**:DS18B20的测量精度可达±0.5℃,分辨率达到0.0625℃。 2. **宽量程**:工作温度范围通常在-55℃到+125℃之间,部分型号可扩展至-100℃到+150℃。 3. **自供电**:可通过数据线汲取电源,或使用外部...

    基于51单片机的ds18b20汇编程序

    在这个基于51单片机的DS18B20汇编程序中,我们可以看到,程序主要分为五个部分:DS18B20温度转换程序、DS18B20复位函数、写指令函数、读指令函数和读取温度函数。下面,我们将详细解释每个部分的知识点。 1. DS18B...

    读取DS18B20的序列号程序

    读取DS18B20-64位序列号演示程序; 具有DS18B20检测和CRC码效验功能。 适用于ME300B、ME300A+单片机开发系统。 开机时,LCD1602显示: READ DS18B20 SERIAL NUMBERS 检测DS18B20,存在时,LCD1602显示: DS18B...

    【51单片机】温度传感器DS18B20程序LCD1602显示.doc

    51单片机温度传感器DS18B20程序LCD1602显示 本文档主要介绍了使用51单片机与DS18B20温度传感器和LCD1602液晶显示模块的程序设计。下面是相关知识点的总结: 1、DS18B20温度传感器的基本知识: DS18B20是Dallas...

    DS18B20测温51驱动程序

    通过对DS18B20测温51驱动程序的深入分析,我们不仅了解了DS18B20的工作原理及其与51单片机的接口设计,还学习了如何通过编程实现温度的精确测量。这对于从事嵌入式系统开发的技术人员来说是非常有价值的参考资料。在...

    DS18B20代码51单片机代码

    通过这些资源,你可以学习到如何在51单片机上编程,实现与DS18B20的通信,获取和处理温度数据,进而实现温度监测和控制功能。这涵盖了硬件接口设计、软件编程技巧、协议理解和错误处理等多个方面,对于提升嵌入式...

    DS18B20单片机程序

    标题 "DS18B20单片机程序" 指的是使用DS18B20数字温度传感器与单片机交互的编程实践。DS18B20是一款集成了温度传感器、数字信号处理器和存储器的一线总线(1-Wire)器件,广泛应用于各种环境温度监测系统。 在描述...

    51单片机ds18b20程序和电路图

    1. **数据线连接**:DS18B20的DATA引脚连接到51单片机的某个IO口,通常需要一个4.7K欧姆的上拉电阻。 2. **电源连接**:VDD引脚连接到5V电源,GND引脚接地。如果采用 parasite power mode,则省略VDD连接,通过数据...

Global site tag (gtag.js) - Google Analytics