多个共总线
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是整型 */
}