这里将我编写的STC12C5A60S2单片机控制单总线协议温度传感器ds18b20的程序共享一下,是希望前辈们给予斧正 。
(补充:以下代码只需要修改.h文件中含有 “选择” 字样的部分,就可以达到复用的效果)
对于LCD1602模块,请参考我的另一篇文章《单片机控制LCD1602液晶屏之模块化编程》
经过测试,本程序适合11.0592MHZ和12.00MHZ晶振情况,同时本程序合适proteus仿真(需要修改ds18b20.c中的宏TEST的值即可用于proteus仿真)
实验步骤1:修改ds18b20.c中的宏,即可适用于硬件
#define TEST 1 /*1:硬件实验 0 :proteus仿真实验*/
实验步骤2:修改ds18b20.c中的宏,即可适用于proteus仿真
#define TEST 0 /*1:硬件实验 0 :proteus仿真实验*/
测试程序:
#include <reg52.h>
#include <intrins.h>
#include "common.h"
#include "lcd1602.h"
#include "ds18b20.h"
void main(void)
{
int temp,j ;
float f ;
UB8 dat[]={0,0,0,0,0,0,0,0,0,0};
P1=0x00;//leds
#if 0 //临时测试DS18B20的存在与否,用于检测ds18b20Init()函数
if(ds18b20Init() == 0) //存在
{
P1 = 0x01 ;
}
else
P1=0xf8;
while(1)
;
#endif
lcd1602Init() ;
lcd1602WriteCommand(0x0c);/*为了显示时消除光标显示,暂时修改,也可以在lcd1602模块函数中修改*/
lcd1602AddressWriteString(LCD1602_ROW0,0,"Chip : DS18b20") ;
while(1)
{
temp = ds18b20ReadTemperature() ;
if((temp & (0xf8<<8)) ==(0xf8<<8)) //温度为负
{
lcd1602AddressWriteByte(LCD1602_ROW1,0,‘-‘);
temp-=1 ;
temp =~temp ;
f= temp ;
temp = f*0.0625*10+0.5;/*乘以10,并加0.5(用于四舍五入),用以后续的保留1位小数做准备*/
}
else
{
lcd1602AddressWriteByte(LCD1602_ROW1,0,‘+‘);
temp &=~(0xf8<<8);
f = temp ;
temp = f*0.0625*10+0.5;
}
dat[0] = temp / 1000 +‘0‘ ;/*温度百位*/
dat[1]= temp %1000/100 +‘0‘;/*温度十位*/
dat[2] = temp %100 /10 +‘0‘ ;/*温度个位*/
dat[3] = ‘.‘ ;
dat[4] = temp %10 +‘0‘;/*温度小数点后第一位,是进行了四舍五入操作后的数据*/
for(j=0 ; j<5 ; j++)
{
lcd1602AddressWriteByte(1,j+1, dat[j]);
}
}
while(1);
}
/*################ds18b20.h start################*/
#ifndef __DS18B20_H__ #define __DS18B20_H__ #include <reg52.h> sbit ds18b20_io_bit = P3^7 ;/*根据硬件选择*/ //Rom command #define DS18B20_SEARCH_ROM 0xf0 #define DS18B20_READ_ROM 0x33 #define DS18B20_MATCH_ROM 0x55 #define DS18B20_SKIP_ROM 0xcc #define DS18B20_ALARM_SEARCH 0xec //Function command #define DS18B20_CONVERT_TEMPERATURE 0x44 #define DS18B20_WRITE_SCRATCHPAD 0x4e #define DS18B20_READ_SCRATCHPAD 0xbe #define DS18B20_COPY_SCRATCHPAD 0x48 #define DS18B20_RECALL_E2 0xb8 #define DS18B20_READ_POWER_SUPPLY 0xb4 #define DS18B20_EXISTENCE 0 /*存在DS18B20*/ #define DS18B20_NOT_EXISTENCE -1/*不存在DS18B20*/ extern SB8 ds18b20Init(void); extern int ds18b20ReadTemperature(void) ; #endif /*__DS18B20_H__*/
/*################ds18b20.h end################*/
/*################ds18b20.c start################*/
/***************************************************************************
Module :ds18b20.c
Purpose :Implementation of ds18b20 module.
Version :0.01 2014/03/14 12:00(OK)
Complier:Keil 8051 C complier V9.01
MCU :STC12C5A60S2(开发板)
AT89C51 (proteus仿真)
Author :yangrui
Email :yangrui90s@163.com
Modification:
=================
2014/02/24 23:44
Reason:
1.该程序适合11.0592MHZ和12.0MHZ晶振环境,还适用于protes仿真
,但注意在仿真时修改delay15usForDs18b20()和delay720usForDs18b20()
和函数ds18b20ReadTemperature的预编译命令即可。
为了简化修改过程,只需要修改程序中的TEST值即可!!
2.该程序默认使用12位转换精度.(精确到0.0625摄氏度)
=================
***************************************************************************/
#include <reg52.h>
#include <intrins.h>
#include "common.h"
#include "ds18b20.h"
#define TEST 1 /*1:硬件实验 0 :proteus仿真实验*/
/******************************************************
Function :delay15usForDs18b20
Input :N/A
Output :N/A
Return :N/A
Description :N/A
Note :1.这里的延时是由STC-ISP V6.66(软件延时计算器)
生成。
2.这里的延时由两个版本,一个用于ds18b20开发板,
一个用于ds18b20的proteus仿真,因为DS118B20对
时间要求较高,所以需要需要根据具体实验选择。
******************************************************/
void delay15usForDs18b20(void) //11.0592MZH
{
#if (TEST==1) //用于开发板
unsigned char i;
_nop_();
_nop_();
i = 38;
while (--i);
#elif (TEST==0) //用于porteus仿真
unsigned char i;
i = 4;
while (--i);
#endif
}
/******************************************************
Function :delay720usForDs18b20
Input :N/A
Output :N/A
Return :N/A
Description :N/A
Note :1.这里的延时是由STC-ISP V6.66(软件延时计算器)
生成。
2.这里的延时由两个版本,一个用于ds18b20开发板,
一个用于ds18b20的proteus仿真,因为DS118B20对
时间要求较高,所以需要需要根据具体实验选择。
******************************************************/
void delay720usForDs18b20(void) //11.0592MZH
{
#if (TEST==1) //用于开发板
unsigned char i, j;
_nop_();
i = 18;
j = 187;
do
{
while (--j);
} while (--i);
#elif (TEST==0) //用于proteus仿真
unsigned char i, j;
_nop_();
i = 2;
j = 70;
do
{
while (--j);
} while (--i);
#endif
}
/******************************************************
Function :ds18b20Init
Input :N/A
Output :N/A
Return :N/A
Description :N/A
Note :经过测试在11.0592MHZ和12.00MHZ条件下都可以
检测到ds18b20的存在。
******************************************************/
SB8 ds18b20Init(void)
{
SB8 existenceFlag ;
UB8 i=0 ;
ds18b20_io_bit = HIGH_LEVEL ;
_nop_() ;
_nop_() ;
/*master transmit the reset pulse */
ds18b20_io_bit = LOW_LEVEL ;
delay720usForDs18b20();
/*rising edge*/
ds18b20_io_bit = HIGH_LEVEL ;
/*ds18b20 wait 15us to 60us then transmit a presence pulse by
pulling the 1-wire low for 60us to 240 us */
delay15usForDs18b20();
delay15usForDs18b20();
delay15usForDs18b20();
delay15usForDs18b20();
if( ! ds18b20_io_bit)
{/*ds18b20 eixstence*/
existenceFlag = DS18B20_EXISTENCE;
}
else
{/*no ds18b20*/
existenceFlag = DS18B20_NOT_EXISTENCE;
}
while((!ds18b20_io_bit) && (i<250))
{
i++;/*wait*//*暂时,具体见调试*/
/*经过测试,这里的250对于11.0592MHZ和12MHZ都远远足够了*/
}
return existenceFlag ;
}
/******************************************************
Function :ds18b20WriteByte
Input :the data which ready to write to ds18b20
Output :N/A
Return :N/A
Description :write byte-data to ds18b20
Note :N/A
******************************************************/
void ds18b20WriteByte(UB8 dataCode)
{
UB8 i ;
for(i=0 ; i<8 ; i++)
{
ds18b20_io_bit = HIGH_LEVEL ;
_nop_();
_nop_();
ds18b20_io_bit = LOW_LEVEL ;
_nop_();
_nop_();
ds18b20_io_bit = dataCode & 0x01;
dataCode>>=1;
delay15usForDs18b20() ;
delay15usForDs18b20() ;
delay15usForDs18b20() ;
delay15usForDs18b20() ;
/*试验中发现这一句不可以少,尽管下一个循环的第一句也是同样的内容???*/
ds18b20_io_bit = HIGH_LEVEL ;
_nop_();
_nop_();
}
}
/******************************************************
Function :ds18b20ReadByte
Input :N/A
Output :N/
Return :the data form ds18b20
Description :N/A
Note :N/A
******************************************************/
UB8 ds18b20ReadByte(void)
{
UB8 dataCode = 0x00 ;
UB8 i ;
for(i=0 ; i<8 ; i++)
{
ds18b20_io_bit = HIGH_LEVEL ;
_nop_();
_nop_();
ds18b20_io_bit = LOW_LEVEL ;
_nop_();
_nop_();
ds18b20_io_bit = HIGH_LEVEL ;
_nop_();
_nop_();
if(ds18b20_io_bit)
{
dataCode |= (0x01 << i) ;
}
delay15usForDs18b20() ;
delay15usForDs18b20() ;
delay15usForDs18b20() ;
delay15usForDs18b20() ;
}
return dataCode ;
}
/******************************************************
Function :delay750ms
Input :N/A
Output :N/A
Return :N/A
Description :用于ds18b20的内部操作时间等待
Note :N/A
******************************************************/
void delay750ms(void)
{
/*
发现数据最开始上电时为85,但是过一会变成23.063,,而且
感觉温度没有那么高,用于后期调试
*/
unsigned char i, j, k;
i = 32;
j = 133;
k = 87;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
/******************************************************
Function :ds18b20ReadTemperature
Input :N/A
Output :N/A
Return :the temperature of environment
Description :N/A
Note :N/A
******************************************************/
int ds18b20ReadTemperature(void)
{
int temperatureCode ;
UB8 temperature_th , temperature_tl ;
ds18b20Init() ;
ds18b20WriteByte(DS18B20_SKIP_ROM) ;/*跳过ROM操作*/
ds18b20WriteByte(DS18B20_CONVERT_TEMPERATURE) ;/*转换温度命令*/
#if (TEST==1)
delay750ms();
#endif
/*这里如果没有延时,温度也能够测出来,不过刚上电时,
会显示85摄氏度(默认),如果有足够的延时,这里的就会错过这段时间*/
//while(!ds18b20_io_bit);
ds18b20Init() ;
ds18b20WriteByte(DS18B20_SKIP_ROM) ;
ds18b20WriteByte(DS18B20_READ_SCRATCHPAD) ;
temperature_tl = ds18b20ReadByte() ;
temperature_th = ds18b20ReadByte() ;
temperatureCode = (temperature_th << 8) | temperature_tl ;
return temperatureCode ;
}
/*################ds18b20.c end################*/
补充:common.h
#ifndef __COMMON_H__ #define __COMMON_H__ typedef unsigned char UB8 ; typedef unsigned short int UW16 ; typedef unsigned long UL32 ; typedef char SB8; typedef short int SW16 ; typedef long SL32 ; #define HIGH_LEVEL 1 #define LOW_LEVEL 0 #endif /*__COMMON_H__*/
单片机控制单总线协议DS18B20之模块编程,布布扣,bubuko.com
原文:http://blog.csdn.net/yagnruinihao/article/details/21258583