单片机控制单总线协议DS18B20之模块编程
时间:2014-03-15 08:25:20
收藏:0
阅读:664
这里将我编写的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
评论(0)