📄 18b20 读写程序.txt
字号:
//=============================================================================
//=============================================================================
//=============================================================================
// 原创 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
//-----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -