单片机MSP430 DS1B20 驱动

文章目录

多个共总线

ds18b20.h


#ifndef __ds18b20
#define __ds18b20

#include "msp430g2553.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define DQ_1 P2OUT |= BIT0
#define DQ_0 P2OUT &= ~BIT0
#define DQ_in   P2DIR &= ~BIT0
#define DQ_out  P2DIR |= BIT0
#define DQ_val  (P2IN & BIT0)

void read_rom(unsigned char rom[]);
void WRITE_ROM(unsigned char T_H, unsigned char T_L, unsigned char CONFIG1);

unsigned int get_one_temperature(unsigned char ch);
unsigned char DS18B20_SearchRomId(unsigned char (*pID)[8], unsigned char Num);//没用到




#endif


ds18b20.c

#include "ds18b20.h"

#define CPU_F ( (double) 8000000)
#define delay_us( x )   __delay_cycles( (long) (CPU_F * (double) x / 1000000.0) )
#define delay_ms( x )   __delay_cycles( (long) (CPU_F * (double) x / 1000.0) )

unsigned char ds18b20_rom1[8] = { 0x80, 0x3C, 0x01, 0xA8, 0x16, 0x8D, 0xB7, 0x28 }; /* 八个DS18B20的64位ROM地址 */
unsigned char ds18b20_rom2[8] = { 0xB4, 0x3C, 0x01, 0xA8, 0x16, 0x1C, 0x9C, 0x28 };
unsigned char ds18b20_rom3[8] = { 0x6E, 0x3C, 0x01, 0xA8, 0x16, 0x8E, 0x3A, 0x28 };
unsigned char ds18b20_rom4[8] = { 0x9F, 0x3C, 0x01, 0xA8, 0x16, 0x75, 0xA3, 0x28 };

/************************************************
 ** 函数名称 : void reset(void)
 ** 函数功能 : ds18b20复位函数
 ** 输    入 : 无
 ** 输    出 : 无
 ** 说    明 :
 ************************************************/
void reset(void)
{

    DQ_out; /* 先设为输入口 */
    DQ_0; /* 主机发送复位脉冲,强制拉DQ至低电平 */
    delay_us(750); /* 延时500vs */
    DQ_1;
    delay_us(15);

//    DQ_in; /* 设为输入口,释放DQ线 */
//    while (DQ_val == 1)
//        ; /* 等待器件DS18B20应答(如果有低电平出现说明总线上有器件作出应答) */
//    delay_us(50); /* 延时 */
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
unsigned char DS18B20_Check(void)
{
    unsigned char retry = 0;
    DQ_in; //SET PA0 INPUT
    while (DQ_val && retry < 200)
    {
        retry++;
        delay_us(1);
    };
    if (retry >= 200)
        return 1;
    else
        retry = 0;
    while (!DQ_val && retry < 240)
    {
        retry++;
        delay_us(1);
    };
    if (retry >= 240)
        return 1;
    return 0;
}

//从DS18B20读取一个位
//返回值:1/0
unsigned char DS18B20_Read_Bit(void)            // read one bit
{
    unsigned char data;
    DQ_out;            //SET PA0 OUTPUT
    DQ_0;
    delay_us(2);
    DQ_1;
    DQ_in;            //SET PA0 INPUT
    delay_us(12);
    if (DQ_val)
        data = 1;
    else
        data = 0;
    delay_us(50);
    return data;
}
//从DS18B20读取一个字节
//返回值:读到的数据
unsigned char DS18B20_Read_Byte(void)    // read one byte
{
    unsigned char i, j, dat;
    dat = 0;
    for (i = 1; i <= 8; i++)
    {
        j = DS18B20_Read_Bit();
        dat = (j << 7) | (dat >> 1);
    }
    return dat;
}
//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(unsigned char dat)
{
    unsigned char j;
    unsigned char testb;
    DQ_out;    //SET PA0 OUTPUT;
    for (j = 1; j <= 8; j++)
    {
        testb = dat & 0x01;
        dat = dat >> 1;
        if (testb)
        {
            DQ_0;    // Write 1
            delay_us(2);
            DQ_1;
            delay_us(60);
        }
        else
        {
            DQ_0;    // Write 0
            delay_us(60);
            DQ_1;
            delay_us(2);
        }
    }
}
//开始温度转换
void DS18B20_Start(void)    // ds1820 start convert
{
    reset();
    DS18B20_Check();
    DS18B20_Write_Byte(0xcc);    // skip rom
    DS18B20_Write_Byte(0x44);    // convert
}

/************************************************
 ** 函数名称 : void read_rom(unsigned char rom[])
 ** 函数功能 : 从ds18b20中读出64位序列号
 ** 输    入 : 无
 ** 输    出 : 无
 ** 说    明 :
 ************************************************/
void read_rom(unsigned char rom[])
{
    unsigned char i;
    reset();
    DS18B20_Check();
    DS18B20_Write_Byte(0x33);
    for (i = 8; i > 0; i--)
    {
        rom[i - 1] = DS18B20_Read_Byte();
    }
}

/************************************************
 ** 函数名称 : bit match_rom(uchar *rom)
 ** 函数功能 : 64位的ROM序列号匹配
 ** 输    入 : 无
 ** 输    出 : 无
 ** 说    明 :
 ************************************************/
char match_rom(unsigned char *rom)
{
    unsigned char i;
    reset();
    DS18B20_Check();
    DS18B20_Write_Byte(0x55);
    for (i = 8; i > 0; i--)
    {
        DS18B20_Write_Byte(*(rom + i - 1));
    }
    return (1);
}
//写入配置 分辨率多少位 默认12位
void WRITE_ROM(unsigned char T_H, unsigned char T_L, unsigned char CONFIG1)
{
    reset(); /*复位 */
    DS18B20_Write_Byte(0xCC); /* SKIP ROM */
    DS18B20_Write_Byte(0x4E); /* 写RAM命令 */
    DS18B20_Write_Byte(T_H); /* 温度报警高限值 */
    DS18B20_Write_Byte(T_L); /* 温度报警低限值 */
    DS18B20_Write_Byte(CONFIG1); /* 配置位 */
    reset(); /* 重新复位 */
    DS18B20_Write_Byte(0xCC); /* SKIP ROM */
    DS18B20_Write_Byte(0x48); /* 将RAM拷贝到EEPROM */
    delay_ms(12); /* 耗时约10MS */
}

/* 读取温度 */
unsigned int get_one_temperature(unsigned char ch)
{
    unsigned int Temp_l = 0, Temp_h = 0, Temp = 0;
    float f_temp;

    switch (ch)
    {
    case 1:
        match_rom(ds18b20_rom1);
        break;
    case 2:
        match_rom(ds18b20_rom2);
        break;
    case 3:
        match_rom(ds18b20_rom3);
        break;
    case 4:
        match_rom(ds18b20_rom4);
        break;
    }
    DS18B20_Write_Byte(0xbe);                    // convert
    Temp_l = DS18B20_Read_Byte(); // LSB
    Temp_h = DS18B20_Read_Byte(); // MSB

    DS18B20_Start();                    // ds1820 start convert

    Temp_h <<= 8;
    Temp = Temp_h + Temp_l;
    f_temp = Temp * 0.0625; /* 18b20的分辨率是0.0625 */
    Temp = f_temp * 10 + 0.5; /* 乘以10表示小数点后面取一位,加0.5是四舍五入 */
    return (Temp); /* Temp是整型 */
}

/*****************************************************************
 * @brief   :DS18B20_WriteBit() 主机向总线写1bit 数据
 * @param   : bit:要写入位的值 0或1
 * @retval  :无
 ****************************************************************/
void DS18B20_WriteBit(unsigned char bit)
{
    DQ_out; /* 主机端口推挽输出模式 */
    DQ_0; /* Write 0 拉低总线10-15us */
    delay_us(12);

    if (bit & 0x01)
    {

        DQ_1;  // Write 1

    }
    else
    {
        DQ_0;    // Write 0

    }

    delay_us(30); /* 写入数据位,保持20-45us */
    DQ_1; /* 释放总线 */
    delay_us(5);
}

/*****************************************************************
 * @brief   :DS18B20_Read2Bit() 主机从总线上读取2位的数据
 * @param   :无
 * @retval  :读到到的数据 :00H,01H,10H,11H
 ****************************************************************/
unsigned char DS18B20_Read2Bit(void)
{
    unsigned char i, data = 0;

    for (i = 0; i < 2; i++)
    {
        data <<= 1;
        if (DS18B20_Read_Bit())
            data |= 1;
    }
    return (data);
}
/*****************************************************************
 * @brief   :DS18B20_CRC8() DS18B20 ROMID CRC校验
 * @param   :*pRomId :要校验诉RomID
 * @retval  :返回校验值
 ****************************************************************/
unsigned char DS18B20_CRC8(unsigned char *pRomId)
{
    unsigned char i, x;
    unsigned char crcbuff;
    unsigned char crc;
    crc = 0;
    for (x = 0; x < 8; x++)
    {
        crcbuff = pRomId[x];
        for (i = 0; i < 8; i++)
        {
            if (((crc ^ crcbuff) & 0x01) == 0)
                crc >>= 1;
            else
            {
                crc ^= 0x18; /* crc=x8+x5+x4+1 */
                crc >>= 1;
                crc |= 0x80;
            }
            crcbuff >>= 1;
        }
    }
    return (crc);
}
#define MAXNUM 16                       //定义最多有16个 DS18B20
/*****************************************************************
 * @brief   :DS18B20_SearchRom() 搜索DS18B20 ROM Id
 * @param   :pID:DS18B20 ID缓冲区指针 ,Num:DS18B20数目,必须事先知道
 * @retval  :搜索到的DS18B20数目
 ****************************************************************/
unsigned char DS18B20_SearchRomId(unsigned char (*pID)[8], unsigned char Num)
{
    unsigned char k, l, chongtuwei, m, n;
    unsigned char zhan[MAXNUM];
    unsigned char ss[64];
    unsigned char num = 0;
    l = 0;

    do
    {
        reset();
        delay_us(500); /* 给系统时间知道,总线上有没有器件  不给延时,就是不行的 */
        DS18B20_Write_Byte(0xF0);
        for (m = 0; m < 8; m++)
        {
            unsigned char s = 0;
            for (n = 0; n < 8; n++)
            {
                k = DS18B20_Read2Bit(); /* 读两位数据 */
                k = k & 0x03;
                s >>= 1;
                if (k == 0x01) /* 01H:表示总线上所有器件该位为0,为了保持器件与总线的联系,所以主机应写0 */
                {
                    DS18B20_WriteBit(0);
                    ss[(m * 8 + n)] = 0;
                }
                else if (k == 0x02) /* 10H:前两位的数据为10H(0x02),表示总线上所有器件该位为1,为了保持器件与总线的联系,所以主机应写1 */
                {
                    s = s | 0x80;
                    DS18B20_WriteBit(1);
                    ss[(m * 8 + n)] = 1;
                }
                else if (k == 0x00) /* 读到的数据为00 有冲突位 判断冲突位 */
                {
                    /* 如果冲突位大于栈顶写0 小于栈顶写以前数据 等于栈顶写1 */
                    chongtuwei = m * 8 + n + 1;
                    if (chongtuwei > zhan[l])
                    {
                        DS18B20_WriteBit(0);
                        ss[(m * 8 + n)] = 0;
                        zhan[++l] = chongtuwei;
                    }
                    else if (chongtuwei < zhan[l])
                    {
                        s = s | ((ss[(m * 8 + n)] & 0x01) << 7);
                        DS18B20_WriteBit(ss[(m * 8 + n)]);
                    }
                    else if (chongtuwei == zhan[l])
                    {
                        s = s | 0x80;
                        DS18B20_WriteBit(1);
                        ss[(m * 8 + n)] = 1;
                        l = l - 1;
                    }
                }
                else
                {
                    return (num); /* 搜索完成,//返回搜索到的个数 */
                }
            }
            pID[num][m] = s;
        }
        num = num + 1;
    }
    while (zhan[l] != 0 && (num < MAXNUM));

    return (num); /* 返回搜索到的个数 */
}


单个


#ifndef __DS18B20_H
#define __DS18B20_H

#include "msp430.h"
#include "sys.h"

#define DQ_1 P1OUT |= BIT7
#define DQ_0 P1OUT &= ~BIT7
#define DQ_in   P1DIR &= ~BIT7
#define DQ_out  P1DIR |= BIT7
#define DQ_val  (P1IN & BIT7)

unsigned int get_one_temperature(void);

#endif

#include "DS18B20.h"


/************************************************
 ** 函数名称 : void reset(void)
 ** 函数功能 : ds18b20复位函数
 ** 输    入 : 无
 ** 输    出 : 无
 ** 说    明 :
 ************************************************/
void reset(void)
{
    DQ_out; /* 先设为输入口 */
    DQ_0; /* 主机发送复位脉冲,强制拉DQ至低电平 */
    delay_us(750); /* 延时500vs */
    DQ_1;
    delay_us(15);
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
unsigned char DS18B20_Check(void)
{
    unsigned char retry = 0;
    DQ_in; //SET PA0 INPUT
    while (DQ_val && retry < 200)
    {
        retry++;
        delay_us(1);
    };
    if (retry >= 200)
        return 1;
    else
        retry = 0;
    while (!DQ_val && retry < 240)
    {
        retry++;
        delay_us(1);
    };
    if (retry >= 240)
        return 1;
    return 0;
}

//从DS18B20读取一个位
//返回值:1/0
unsigned char DS18B20_Read_Bit(void)            // read one bit
{
    unsigned char data;
    DQ_out;            //SET PA0 OUTPUT
    DQ_0;
    delay_us(2);
    DQ_1;
    DQ_in;            //SET PA0 INPUT
    delay_us(12);
    if (DQ_val)
        data = 1;
    else
        data = 0;
    delay_us(50);
    return data;
}
//从DS18B20读取一个字节
//返回值:读到的数据
unsigned char DS18B20_Read_Byte(void)    // read one byte
{
    unsigned char i, j, dat;
    dat = 0;
    for (i = 1; i <= 8; i++)
    {
        j = DS18B20_Read_Bit();
        dat = (j << 7) | (dat >> 1);
    }
    return dat;
}
//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(unsigned char dat)
{
    unsigned char j;
    unsigned char testb;
    DQ_out;    //SET PA0 OUTPUT;
    for (j = 1; j <= 8; j++)
    {
        testb = dat & 0x01;
        dat = dat >> 1;
        if (testb)
        {
            DQ_0;    // Write 1
            delay_us(2);
            DQ_1;
            delay_us(60);
        }
        else
        {
            DQ_0;    // Write 0
            delay_us(60);
            DQ_1;
            delay_us(2);
        }
    }
}
//开始温度转换
void DS18B20_Start(void)    // ds1820 start convert
{
    reset();
    DS18B20_Check();
    DS18B20_Write_Byte(0xcc);    // skip rom
    DS18B20_Write_Byte(0x44);    // convert
}



/* 读取温度 */
unsigned int get_one_temperature(void)
{
    unsigned int Temp_l = 0, Temp_h = 0, Temp = 0;
    float f_temp;

   
    reset();
    DS18B20_Check();
    DS18B20_Write_Byte(0xcc);   
    DS18B20_Write_Byte(0xbe);                    // convert
    Temp_l = DS18B20_Read_Byte(); // LSB
    Temp_h = DS18B20_Read_Byte(); // MSB

    DS18B20_Start();                    // ds1820 start convert
    

    Temp_h <<= 8;
    Temp = Temp_h + Temp_l;
    f_temp = Temp * 0.0625; /* 18b20的分辨率是0.0625 */
    Temp = (unsigned int)(f_temp * 10 + 0.5); /* 乘以10表示小数点后面取一位,加0.5是四舍五入 */
    return (Temp); /* Temp是整型 */
}



猜你喜欢

转载自blog.csdn.net/x1131230123/article/details/104887614
今日推荐