DS18B20组件

DS18B20.h

#ifndef _DS18B20_H
#define _DS18B20_H

sbit DS18B20_IO = P3^2;  //DS18B20通信引脚

#ifndef _1T
void delayX10us(uint8_t t);
#else
void delayX10us(uint16_t t);
#endif // _1T
bit getDS18B20ack();
void writeDS18B20(uint8_t dat);
uint8_t readDS18B20();
bit startDS18B20();
bit getDS18B20temperature(int16_t * temp);
uint8_t getIntPart(int16_t temp);
uint8_t getDecPart(int16_t temp);
bit getSign(int16_t temp);

#endif // _DS18B20_H

DS18B20.c

/**
 * 文件名:DS18B20.c
 * 描  述:温度传感器DS18B20驱动模块
 */
#include 
#include 
#include "stdint.h"
#include "DS18B20.h"

/* 软件延时函数,延时时间(t*10)us */
#ifndef _1T
void delayX10us(uint8_t t) {    //时钟晶振11.0592MHz
    do {
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
    } while (--t);
}
#else
void delayX10us(uint16_t t) {   //注意!会溢出!
    t *= 6;
    do {
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
    } while (--t);
}
#endif // 1T
/* 复位总线,获取存在脉冲,以启动一次读写操作 */
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;
}























你可能感兴趣的:(AVR单片机,51单片机,Arduino)