/*
*******************************************************************************
* 文件名:DS18B20.c
* 描 述:温度传感器DS18B20驱动模块
*******************************************************************************
*/
#include <reg52.h>
#include <intrins.h>
#include "stdint.h"
sbit ds18b20_io = P3^2; //DS18B20通信引脚
/* 软件延时函数,延时时间(t*10)us */
void delayX10us(uint16_t t) {
t *= 6;
do {
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
} while (--t);
}
/* 复位总线,获取存在脉冲,以启动一次读写操作 */
bit getDs18b20Ack() {
bit ack;
EA = 0; //禁止总中断
ds18b20_io = 0; //产生500us复位脉冲
delayX10us(50);
ds18b20_io = 1;
delayX10us(6); //延时60us
ack = ds18b20_io; //读取存在脉冲
while (!ds18b20_io); //等待存在脉冲结束
EA = 1; //重新使能总中断
return ack;
}
/* 向DS18B20写入一个字节,dat-待写入字节 */
void writeDs18b20(uint8_t dat) {
uint8_t mask;
EA = 0; //禁止总中断
//低位在先,依次移出8个bit
for (mask = 0x01; mask != 0; mask <<= 1) {
ds18b20_io = 0; //产生2us低电平脉冲
_nop_();
_nop_();
if ((mask & dat) == 0) //输出该bit值
ds18b20_io = 0;
else
ds18b20_io = 1;
delayX10us(6); //延时60us
ds18b20_io = 1; //拉高通信引脚
}
EA = 1; //重新使能总中断
}
/* 从DS18B20读取一个字节,返回值-读到的字节 */
uint8_t readDs18b20() {
uint8_t dat, mask;
EA = 0; //禁止总中断
//低位在先,依次采集8个bit
for (mask = 0x01; mask != 0; mask <<= 1) {
ds18b20_io = 0; //产生2us低电平脉冲
_nop_();
_nop_();
ds18b20_io = 1; //结束低电平脉冲,等待18B20输出数据
_nop_(); //延时2us
_nop_();
if (ds18b20_io) //读取通信引脚上的值
dat |= mask;
else
dat &= ~mask;
delayX10us(6); //再延时60us
}
EA = 1; //重新使能总中断
return dat;
}
/* 启动一次18B20温度转换,返回值-表示是否启动成功 */
bit startDs18b20() {
bit ack;
ack = getDs18b20Ack(); //执行总线复位,并获取18B20应答
//如18B20正确应答,则启动一次转换
if (ack == 0) {
writeDs18b20(0xCC); //跳过ROM操作
writeDs18b20(0x44); //启动一次温度转换
}
return ~ack; //ack==0表示操作成功,所以返回值对其取反
}
/* 读取DS18B20转换的温度值,返回值-表示是否读取成功 */
bit getDs18b20Temperature(int16_t * temp) { //温度有正负,有符号
bit ack;
uint8_t lowByte, highByte; //16bit温度值的低字节和高字节
ack = getDs18b20Ack(); //执行总线复位,并获取18B20应答
//如18B20正确应答,则读取温度值
if (ack == 0) {
writeDs18b20(0xCC); //跳过ROM操作
writeDs18b20(0xBE); //发送读命令
lowByte = readDs18b20(); //读温度值的低字节
highByte = readDs18b20(); //读温度值的高字节
*temp = ((int16_t)highByte << 8) | lowByte; //合成为16bit有符号整型数
}
return ~ack; //ack==0表示操作应答,所以返回值为其取反值
}
uint8_t getIntPart(int16_t temp) { //温度是16位有符号数
if (temp & 0x8000) //温度是负数
temp = -temp; //取绝对值
temp >>= 4;
return (uint8_t)temp;
}
uint8_t getDecPart(int16_t temp) { //精确到十进制的一位小数
uint8_t lowByte;
if (temp & 0x8000) //温度是负数
temp = -temp; //取绝对值
lowByte = temp; //取低字节
lowByte &= 0x0F; //高4位清0
return (lowByte * 10) >> 4; //乘以10,除以16
}
bit getSign(int16_t temp) { //温度是16位有符号数
return temp & 0x8000;
}
ds18b20.c
最新推荐文章于 2024-07-02 02:45:43 发布