/*************************************************************************************************************
* 文件: ds18b20.c
* 功能: 基于STM32的DS18B20单总线
*************************************************************************************************************/
#include "sys.h"
#include "delay.h"
#include "ds18b20.h"
#include "usart.h"
/*************************************************************************************************************************
*函数名:int DS18B20_Reset(void)
*功能 :复位DS18B20总线
*参数 :无
*返回 :TRUE:成功;FALSE:失败
*************************************************************************************************************************/
int DS18B20_Reset(void)
{
u8 i = 0;
Set18b20IOout(); //设置总线端口为输出模式
DS18B20_OUT=1; //拉高总线电平,为复位做准备
delay_us(1); //延时1us为
DS18B20_OUT=0; //拉低总线480us~240us
delay_us(500); //延时>480us
DS18B20_OUT=1; //拉高总线
delay_us(2); //复位完成
Set18b20IOin(); //设置总线端口为输入模式
while(DS18B20_IN) //等待从机应答信号
{
i ++;
delay_us(1);
if(i > 100)
{
printf("DS18B20 error!\r\n");
return FALSE; //等待超时,初始化失败,返回FALSE;
}
}
delay_us(250); //跳过回复信号
return TRUE; //复位完成DS18B20,返回TRUE
}
/*************************************************************************************************************************
*函数名:u8 DS18B20_Init(void)
*功能 :初始化DS18B20数据总线
*参数 :无
*返回 :TRUE:成功;FALSE:失败
*************************************************************************************************************************/
u8 DS18B20_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE); //使能GPIOG时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //设置PG11位推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOG, &GPIO_InitStructure);
GPIO_SetBits(GPIOG,GPIO_Pin_11); //输出1
return DS18B20_Reset();
}
/*************************************************************************************************************************
*函数名:u8 DS18B20_Read_Bit(void)
*功能 :从DS18B20读取1位的数据
*参数 :无
*返回 :data
*************************************************************************************************************************/
u8 DS18B20_ReadBit(void)
{
u8 data=0;
Set18b20IOout(); //设置数据总线接口为输出
DS18B20_OUT=0; //拉低总线
delay_us(12); //延时10-15us
DS18B20_OUT=1; //释放总线
Set18b20IOin(); //设置数据总线接口为输入
delay_us(10);
if(DS18B20_IN) //读取数据
{
data=1;
}
delay_us(42); //延时40-45us
return data; //返回数据
}
/*************************************************************************************************************************
*函数名:u8 DS18B20_ReadData(void)
*功能 :从DS18B20读取一个字节的数据
*参数 :无
*返回 :data
*************************************************************************************************************************/
u8 DS18B20_ReadData(void)
{
u8 i,j,data=0;
for (i=1;i<=8;i++)
{
j=DS18B20_ReadBit();
data=(j<<7)|(data>>1);
}
return data;
}
/*************************************************************************************************************************
*函数名:void DS18B20_WriteBit(u8 bit)
*功能 :向DS18B20写入1bit的数据
*参数 :bit
*返回 :无
*************************************************************************************************************************/
void DS18B20_WriteBit(u8 bit)
{
Set18b20IOout(); //设置数据总线接口为输出
DS18B20_OUT=0; //拉低数据总线
delay_us(12); //延时10-15us
DS18B20_OUT= bit&0x01; //写入数据,
delay_us(30); //延时20-45us
DS18B20_OUT=1; //释放总线
delay_us(5);
}
/*************************************************************************************************************************
*函数名:void DS18B20_WriteData(u8 data)
*功能 :向DS18B20写入1字节的数据
*参数 :data
*返回 :无
*************************************************************************************************************************/
void DS18B20_WriteData(u8 data)
{
u8 i;
for(i=0;i< 8;i++)
{
DS18B20_WriteBit(data);
data >>= 1;
}
}
/*************************************************************************************************************************
*函数名:s16 DS18B20_ReadTemper(void)
*功能 :读取温度值
*参数 :无
*返回 :温度值*100
*************************************************************************************************************************/
s16 DS18B20_ReadTemper(void)
{
u8 th, tl;
s16 data;
if(DS18B20_Reset() == FALSE) //错误判断
{
return 0xffff; //返回错误特征值
}
DS18B20_WriteData(SKIP_ROM); //跳过ROM
DS18B20_WriteData(CONVERT_T); //启动温度转换
DS18B20_Reset();
DS18B20_WriteData(SKIP_ROM); //跳过ROM
DS18B20_WriteData(READ_SCRATCHPAD); //温度读取指令
tl = DS18B20_ReadData(); //低8位数据
th = DS18B20_ReadData(); //高8位数据
data = th;
data = data<<8;
data = data|tl;
data = data*6.25; //数值精确到小数点后两位
return data; //返回值=温度*100;
}
/*************************************************************************************************************************
*函数名:u8 DS18B20_Read2Bit(void)
*功能 :读取2bit数据
*参数 :无
*返回 :data
*************************************************************************************************************************/
u8 DS18B20_Read2Bit(void)
{
u8 i,data = 0;
for(i = 0;i < 2;i ++)
{
data <<= 1;
if(DS18B20_ReadBit())
{
data = data|1;
}
}
return data;
}
//------------------------------------------------------------------------------
//-----------------------后面的代码使用于多个DS18B20的环境下--------------------
//------------------------------------------------------------------------------
/*************************************************************************************************************************
*函数名:u8 DS18B20_SearchROM(u8 (*pID)[8],u8 Num)
*功能 :查询DS18B20的ROM
*参数 :(1)、 pIN:总线上DS18B20的ID存储的缓冲区指针
(2)、 Num:DS18B20的个数,在MAXNUM中有定义
*返回 :搜索到总线上DS18B20的个数
*************************************************************************************************************************/
u8 DS18B20_SearchROM(u8 (*pID)[8],u8 Num)
{
unsigned char k,l=0,ConflictBit,m,n;
unsigned char BUFFER[MAXNUM]={0};
unsigned char ss[64];
unsigned char s=0;
u8 num = 0;
do
{
DS18B20_Reset(); //复位DS18B20总线
DS18B20_WriteData(SEARCH_ROM); //搜索ROM
for(m=0;m<8;m++)
{
// unsigned char s=0;
for(n=0;n<8;n++)
{
k=DS18B20_Read2Bit(); // 读两位数据
k=k&0x03;
s= s>>1;
if(k==0x01) //0000 0001 如果读到的数据为0
{
DS18B20_WriteBit(0);//写0,使总线上为0的器件响应
ss[(m*8+n)]=0;
}
else if(k==0x02) //0000 0010 如果读到的数据为1
{
s=s|0x80;
DS18B20_WriteBit (1);//写1,使总线上为1的器件响应
ss[(m*8+n)]=1;
}
else if(k==0x00)//如果读取到的数据为00,则有冲突,需进行冲突位判断
{
ConflictBit=m*8+n+1;
if(ConflictBit>BUFFER[l])//如果冲突位大于栈顶,则写0
{
DS18B20_WriteBit (0);
ss[(m*8+n)]=0;
BUFFER[++l]=ConflictBit;
}
else if(ConflictBit<BUFFER[l])//如果冲突位小于栈顶,则写以前的数据
{
s=s|((ss[(m*8+n)]&0x01)<<7);
DS18B20_WriteBit (ss[(m*8+n)]);
}
else if(ConflictBit==BUFFER[l])//如果冲突位等于栈顶,则写1
{
s=s|0x80;
DS18B20_WriteBit (1);
ss[(m*8+n)]=1;
l=l-1;
}
}
else//如果读到的数据为0x03(0000 0011),则说明单总线上不存在任何设备
{
return num; //搜索完成,返回搜索到的个数
}
delay_us(5);
}
pID[num][m]=s;
s=0;
}
num=num+1;
}
while(BUFFER[l]!=0&&(num<MAXNUM));
return num; //返回搜索到的个数
}
/*************************************************************************************************************************
*函数名:s16 DS18B20_ReadDesignateTemper(u8 pID[8])
*功能 :读取指定ID的DS18B20的温度值
*参数 :(1)、 pIN:总线上DS18B20的ID
*返回 :温度值*100
*************************************************************************************************************************/
s16 DS18B20_ReadDesignateTemper(u8 pID[8])
{
u8 th, tl;
s16 data;
if(DS18B20_Reset() == FALSE) //错误判断
{
return 0xffff; //返回错误信息
}
DS18B20_WriteData(SKIP_ROM); //跳过ROM指令
DS18B20_WriteData(CONVERT_T); //启动温度转换 指令
DS18B20_Reset();
DS18B20_WriteData(MATH_ROM); //匹配ROM指令
for(data = 0;data < 8;data ++) //发送8个字节的序列号
{
DS18B20_WriteData(pID[data]);
}
delay_us(10);
DS18B20_WriteData(READ_SCRATCHPAD); //读取温度指令
tl = DS18B20_ReadData(); //低8位数据
th = DS18B20_ReadData(); //高8位数据
data = th;
data = data<<8;
data = data|tl;
data = data*6.25; //数值精确到小数点后两位
return data; //返回值=温度*100;
}
#include "sys.h"
#ifndef DS18B20_H_
#define DS18B20_H_
//定义总线上的DS18B20的最大个数MAXNUM
#define MAXNUM 4
//DS18B20指令
typedef enum
{
SEARCH_ROM = 0xf0, //搜索ROM指令
READ_ROM = 0x33, //读取ROM指令
MATH_ROM = 0x55, //匹配ROM指令
SKIP_ROM = 0xcc, //跳过ROM指令
ALARM_SEARCH = 0xec, //报警搜索指令
CONVERT_T = 0x44, //温度转换指令
WRITE_SCRATCHPAD = 0x4e, //写暂存器指令
READ_SCRATCHPAD = 0xbe, //读取转存器指令
COPY_SCRATCHPAD = 0x48, //拷贝暂存器指令
RECALL_E2 = 0xb8, //召回EEPROM指令
READ_POWER_SUPPLY = 0xb4, //读取电源模式指令
} DS18B20_CMD;
//DS18B20 ROM编码
typedef struct
{
u8 DS18B20_CODE; //DS18B20单总线编码:0x19
u8 SN_1; //序列号第1字节
u8 SN_2; //序列号第2字节
u8 SN_3; //序列号第3字节
u8 SN_4; //序列号第4字节
u8 SN_5; //序列号第5字节
u8 SN_6; //序列号第6字节
u8 crc8; //CRC8校验
} DS18B20_ROM_CODE;
#define TRUE 0xff
#define FALSE 0X00
//IO方向设置
#define Set18b20IOin() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=8<<12;}
#define Set18b20IOout() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=3<<12;}
IO操作函数
#define DS18B20_OUT PGout(11) //数据端口 PG11
#define DS18B20_IN PGin(11) //数据端口 PG11
//函数使用申明
int DS18B20_Reset(void);
u8 DS18B20_Init(void);
u8 DS18B20_ReadBit(void);
u8 DS18B20_ReadData(void) ;
void DS18B20_WriteBit(u8 bit);
void DS18B20_WriteData(u8 data);
s16 DS18B20_ReadTemper(void);
u8 DS18B20_Read2Bit(void);
u8 DS18B20_SearchROM(u8 (*pID)[8],u8 Num);
s16 DS18B20_ReadDesignateTemper(u8 pID[8]);
#endif /*DS18B20_H_*/