//============================================================================= //============================================================================= //============================================================================= // 原创 18B20 读写程序,欢迎拍砖 // www.21ic.com 之 E007 //============================================================================= //============================================================================= //=============================================================================
//============================================================================= //============================================================================= //============================================================================= // 以下为 F_18B20.h 文件 //============================================================================= //============================================================================= //=============================================================================
#ifndef __F_18B20_H__ #define __F_18B20_H__ //-----------------------------------------------------------------------------
void DS18B20_Init(void); int DS18B20_ReadTemp();
//----------------------------------------------------------------------------- #endif // #ifndef __F_18B20_H__ // End of this file
//============================================================================= //============================================================================= //============================================================================= // 以下为 F_18B20.c 文件 //============================================================================= //============================================================================= //=============================================================================
#include "F_18B20.h"
// 常用数据类型定义,这部分我是放在 main.h 中的,这里一起贴出来 #ifndef __UU_DEF__ #define __UU_DEF__
typedef unsigned char U8; typedef unsigned int U16; typedef unsigned long U32;
typedef signed char S8; typedef signed int S16; typedef signed long S32;
typedef union UU16 { U16 u16; S16 s16; U8 u8[2]; S8 s8[2]; } UU16; // used with UU16 # define LSB 1 # define MSB 0
typedef union UU32 { U32 u32; S32 s32; UU16 uu16[2]; U16 u16[2]; S16 s16[2]; U8 u8[4]; S8 s8[4]; } UU32; // used with UU32 (b0 is least-significant byte) # define b0 3 # define b1 2 # define b2 1 # define b3 0
typedef unsigned char BYTE; typedef unsigned char UCHAR; typedef union {unsigned short i; unsigned char c[2];} WORD; // 这些定义包容了大部分人习惯的写法 #endif // #ifndef __UU_DEF__
//----------------------------------------------------------------------------- // 以下定义 1-Wire 时隙 // 这些值用于调用 Delay 函数时的参数,应根据具体情况而定,关系到 1-Wire 成功读写 // 的关键,故一定要精确设置 // 此例中使用 C8051F340 MCU,时钟48MHz,根据测试后计算而得公式 n(us)*4 - 2
#define wV_30us 118
// 高速和低速时各个时隙值,本例中使用的是低速值 // 使用高速模式时定义一个 OWHIGHSPEED 即可 // #define OWHIGHSPEED #ifdef OWHIGHSPEED // high speed
#define wOW_A ( 1.5 * 4 - 2 ) #define wOW_B ( 7.5 * 4 - 2 ) #define wOW_C ( 7.5 * 4 - 2 ) #define wOW_D ( 2.5 * 4 - 2 ) #define wOW_E ( 0.75 * 4 - 2 ) #define wOW_F ( 7 * 4 - 2 ) #define wOW_G ( 2.5 * 4 - 2 ) #define wOW_H ( 70 * 4 - 2 ) #define wOW_I ( 8.5 * 4 - 2 ) #define wOW_J ( 40 * 4 - 2 )
#else // standard speed
#define wOW_A ( 6 * 4 - 2 ) #define wOW_B ( 64 * 4 - 2 ) #define wOW_C ( 60 * 4 - 2 ) #define wOW_D ( 10 * 4 - 2 ) #define wOW_E ( 9 * 4 - 2 ) #define wOW_F ( 55 * 4 - 2 ) #define wOW_G ( 0 ) #define wOW_H ( 480 * 4 - 2 ) #define wOW_I ( 70 * 4 - 2 ) #define wOW_J ( 410 * 4 - 2 )
#endif
sbit OWDO =P0^4; // 1-Wire DO Line 根据实际使用的口线定义
// #define EINT() { EA = 1; } // #define DINT() { EA = 0; } // 开/关中断的宏,根据MCU来定
//----------------------------------------------------------------------------- // 循环延时程序,每一次循环消耗12个时钟周期,另外固定有25个时钟周期消耗在调用及返 // 回的过程中,故得出延时 n us 计算公式 c = (n*48-25)/12 或 c=n*4-2 // 实际延时值设置应根据实际情况来定 void Delay( unsigned int c ) { while( c-- ); // 用"c--",而不是"--c",在Keil下编译,测试是正确的 // 先判断而后减,必须先判断再减,因为有个 0 值 // 这样的写法我很少敢用,这里测试过没问题才用的 } //----------------------------------------------------------------------------- // 以下为总线复位,写字节,读字节函数,因为时隙要求严格,故在函数中关闭中断 //----------------------------------------------------------------------------- // 复位 1 wire // 设备无响应返回非0,有响应返回0 // 函数名字前的 "OW" means One Wire( 1-Wire ),此类函数可用于其它 1-Wire 设备 U8 OWReset() { U8 rv = 0; DINT(); Delay( wOW_G ); OWDO=0; // 复位 Delay( wOW_H ); // 480us OWDO=1; // 释放总线 Delay( wOW_I ); // 70us rv = OWDO; // 读器件响应 Delay( wOW_J ); // 410us EINT(); return rv; } //----------------------------------------------------------------------------- // 向 1 Wire 写一个字节.x是要写的内容 // w : 预写字节 void OWWriteByte(unsigned char w) { unsigned char i; DINT(); for(i=0;i<8;i++) { if(0x01&w) { // 写1 OWDO=0; Delay( wOW_A ); // 6us OWDO=1; Delay( wOW_B ); // 64us } else { // 写0 OWDO=0; Delay( wOW_C ); // 60us OWDO=1; Delay( wOW_D ); // 10us } w>>=1; } EINT(); } //----------------------------------------------------------------------------- // 从 1 Wire 读一个字节.返回读到的内容 // 返回读取的内容 unsigned char OWReadByte(void) { unsigned char bLoop,rv; rv=0; DINT(); for(bLoop=0;bLoop<8;bLoop++) { rv>>=1; OWDO=0; Delay( wOW_A ); // 6us OWDO=1; Delay( wOW_E ); // 9us if( OWDO ) rv|=0x80; Delay( wOW_F ); // 55us } EINT(); return rv; } //----------------------------------------------------------------------------- // 以下为 18B20 专用函数 //----------------------------------------------------------------------------- // 每次上电都检查设置值,如果与要求的参数一致则跳过,否则重新设置 #define CONFIG18B20 0x7F // 将18b20设为12位,精度就是0.0625度 void DS18B20_Init(void) { if( !OWReset() ) { OWWriteByte( 0xCC ); // 发送Skip ROM命令 // 本例中线上只有一片18B20 // 所以跳过选择器件的过程 OWWriteByte( 0xBE ); // 发送"读"暂存RAM命令 OWReadByte(); // 复位温度值低字节,弃之 OWReadByte(); // 复位温度值高字节,弃之 // 然后读取报警上限/下限温度值及配置值,该值保存是内部EEPROM中, // 在初次上电和更改设置时才需要重写 // 先判断后写的方式,可以保证器件有更长的寿命,并不需要每次都写 // 这里报警温度值均为 0 度 if( 0x00!=OWReadByte() || 0x00!=OWReadByte() || CONFIG18B20!=OWReadByte() ) { OWReset(); OWWriteByte( 0xCC ); // 发送Skip ROM命令 OWWriteByte( 0x4E ); // 发送"写"暂存RAM命令 OWWriteByte( 0x00 ); // 温度报警上限设为0 OWWriteByte( 0x00 ); // 温度报警下限设为0 OWWriteByte( CONFIG18B20 ); // 写配置值 } OWReset(); } } //----------------------------------------------------------------------------- int DS18B20_ReadTemp(void) // 读18b20温度值,此函数为 18B20 专用 { UU16 tmp; tmp.u16=0x8000; // 初始化一不可能值,无器件时时返回此值
if( !OWReset() ) // 如果复位没发现设备则返回无效值 0x8000 { OWWriteByte( 0xCC ); // 发送Skip ROM命令 OWWriteByte( 0x44 ); // 发送温度转换命令
#ifdef POWERONDO POWERDOON(); // 在 DO 线上使能强上拉, // 如果由DO线供电,则采用延时的方式等待转换结束 // 此方式的延时程序依个人风格来写 // DELAYNMS( n ); // 9 位精度,等待>93.74ms // 10 位精度,等待>187.5ms // 11 位精度,等待>375ms // 12 位精度,等待>750ms POWERDOOFF(); // 撤消 DO 强上拉 // 自己定义这两个 DO 线上的强上拉方式 // 的开与关的宏 #else // 单独的电源供给线,采用等待转换结束信号的方式 // 发送开始转换命令后10us,18B20开始转换 // 开始转换后,从DO读位数据,读出0时表示转换未结束 // 读出1时表示转换结束 Delay( wV_30us ); do { DINT(); // 关中断
OWDO=0; Delay( wOW_A ); // 6us OWDO=1; Delay( wOW_E ); // 9us if( OWDO ) tmp.u8[0] = 0x80; // 此时 tmp 空闲,暂时借用一下,可少定义变量 else tmp.u8[0] = 0; Delay( wOW_F ); // 55us EINT(); // 开中断 } while( tmp.u8[0]==0 ); Delay( wV_30us ); #endif
OWReset(); // 总线复位 OWWriteByte( 0xCC ); // 发送Skip ROM命令 OWWriteByte( 0xBE ); // 发送"读"暂存RAM命令
tmp.u8[1]=OWReadByte(); // 读温度低字节 tmp.u8[0]=OWReadByte(); // 读温度高字节 // 51的整型数字高字节在前,NND,我好烦这个 // 18B20 的温度值是一个标准的有符号数,此值乘上 0.0625 即是实际温度值 // 注意,当选择非12bit精度时,要把未使用的低位抹平,复位成0
OWReset(); } return tmp.u16; } //----------------------------------------------------------------------------- // End of this file
//============================================================================= //============================================================================= //============================================================================= // 以下为 main.c 文件 //============================================================================= //============================================================================= //=============================================================================
//#include <C8051F340.h> #include "main.h" #include "F_18B20.h"
//----------------------------------------------------------------------------- void main() { int temp; Init_Device(); // 全部 MCU 初始化工作 EA = 1;
DS18B20_Init(); // 初始化 18B20
while( 1) { temp = DS18B20_ReadTemp(); // 对温度值做进一步处理 // 还有其它需要的工作 } }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // End of this file //-----------------------------------------------------------------------------
|
|