使用的是如图所示的测温模块
一开始还以为这个模块会把一个模拟量输出到 dat 引脚,然后我还用了ADC ,结果无用功,还以为是它的模块坏了。。。
- 提醒:接入电源后,模块上的灯没有亮,并不是模块坏了
时序
时序很重要!时序很重要!时序很重要!
- 微秒级的精确延时
- 初始化、写时序、读时序
C代码
注意延时函数就行了
ds18b20.c
#include "stc15.h"
#include "delay.h"
#include "util.h"
#include "ds18b20.h"
//管脚定义
sbit DQ = P0^1;
void initDS18B20(void)
{
unsigned char x = 1;
DQ = 0; // DQ 复位
Delay500us();
DQ = 1; // 单片机将DQ拉低
Delay68us();
x = DQ;
Delay500us();
if(x == 0){ // 稍做延时后 如果 x=0 则初始化成功 x=1 则初始化失败
dudu(); // 蜂鸣器响两声
}
}
/*
从 DS18B20 中读取数据,每次读取一个 bit
详解:
* 从该模块内置芯片中读取数据时,需要先给它一个上升沿
dat 初始为 00000000
dat>>1 右移一位,也是 00000000
当执行完 DQ=0; DQ=1; 后,该模块给一个电平信号传递给 P0^0(DQ)
if(DQ == 1) 则
dat = 00000000 | 10000000 = 1000000
否则
对应的位依然为 0
如此循环 8 次
*/
unsigned char rd18b20(void)
{
unsigned char i=0,val=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
dat >>= 1;
DQ = 0; // 给脉冲信号
Delay4us();
DQ = 1; // 给脉冲信号
Delay10us();
val = DQ;
if(val) dat|=0x80;
Delay45us();
}
return dat;
}
/*************************************
*************************************/
void wr18b20(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
Delay15us();
DQ = dat & 0x01;
Delay60us();
DQ = 1;
dat >>= 1;
}
DQ = 1;
}
/*************************************
byte0 : 2^3 2^2 2^1 2^0 2^-1 2^-2 2^-3 2^-4
byte1 : 0 0 0 0 2^7 2^6 2^5 2^4
(该位为0,高位总值必小于等于 127)
1、读取温度预备操作
- 初始化
- 启动温度转换
- 注意延时
2、读取操作
- 初始化
- 读取温度寄存器
3、温度处理(读取的温度可以是正的,也可以是负的)
- 因为该模块内部芯片以补码方式存储数字,正数,负数需要区别对待
- 仅处理整数
返回值:
读取的温度结构体:{
val:温度值数据,
neg:正负数标识
}
*************************************/
struct ResTemp read_temp(void)
{
struct ResTemp rt;
unsigned char low = 0, hig = 0, flag = 0;
initDS18B20();
wr18b20(0xCC); // 跳过读序号列号的操作
wr18b20(0x44); // 启动温度转换
delay_ms(750); // 此处延时 750ms 肯定没有问题
initDS18B20();
wr18b20(0xCC); // 跳过读序号列号的操作
wr18b20(0xBE); // 读取温度寄存器等(共可读9个寄存器) 前两个就是温度
delay_us(100); // 稍作延时
low = rd18b20();// 读取温度值低位
hig = rd18b20();// 读取温度值高位,当 byte1 的
if(hig > 127)
{
hig=(256 - hig);
low=(256 - low);
flag=1; // 负温度求补码
}
low = (low & 0xf0) >> 4; // 移至低位
hig = (hig & 0x0f) << 4; // 移至高位
rt.val = low + hig;
rt.neg = flag;
return rt;
}
/*************************************
将数字温度转换成字符串
参数说明:
1、要转换的温度值(数字)
2、转换后存储的数据数组
3、正负数标识
*************************************/
void temp2str(unsigned char val,unsigned char buf[], unsigned char flag)
{
unsigned char idx = 0;
idx = number2str(val,buf,flag);
buf[idx++] = '*';
buf[idx++] = 'C';
buf[idx] = '\0';
}