📄 ds1820.c
字号:
//**********************************************************************
//功能 : 实时时钟DS1820操作模块
//作者 : lihj
//创建日期 : 2004-07-10
//版本 : V1.0
//修改记录 :
//***********************************************************************
#include <reg51.h>
#include <std.h>
#include <ds1820.h>
sbit TMDAT = P3^4; //根据实实际情况设定
//函数功能:延时(12MHz晶振)
//输入参数:<count>延时时间长度,单位1ms
void Delay_ms (U16 count)
{
U16 i;
while (count)
{
i = 123;
while (i>0) i--;
count--;
}
}
//函数功能:复位芯片(至少480us长的低电平信号)
void ResetChip (void)
{
U16 i;
TMDAT = 0; //480us~960us长低电平:复位
i = 150;
while (i--); //延时约900 uS(12Mhz时)
TMDAT = 1;
i = 5;
while (i--); //DS1820检测到上升沿后,过15~60us后输出“存在”信号
}
//函数功能: 判断DS1820是否存在
//返回参数: TRUE:芯片存在
// FALSE:芯片不存在
U8 ChipPresenceCheck(void)
{
U16 i;
ResetChip();
//等待70us,应该检测到低电平
i = 11;
while(i--);
if(TMDAT)
{
return FALSE;
}
//等待400us,应检测到高电平,低电平信号保持60~240us
i = 65;
while (i--);
if(TMDAT)
{
return TRUE;
}
else
{
return FALSE;
}
}
//函数功能:从总线上读取1位信号
bit RdBit (void)
{
U16 i;
bit b0;
TMDAT = 0; i++; //下降沿之后,保持低电平至少1us //
TMDAT = 1; i++; i++; //微量延时(既作输入又作输出的I/O脚,读数据时,先拉高电平)
b0 = TMDAT;
i = 9;
while (i--); //延时60us
return (b0);
}
//函数功能:从总线上读取1个字节信号
U8 RdByte (void)
{
U8 i,j,byRdData=0;
for (i=0;i<8;i++)
{
j = RdBit ();
byRdData >>= 1;
byRdData = (j << 7) | byRdData;
}
return (byRdData);
}
//函数功能:向总线上写一位数据
void WrBit(bit b0)
{
U8 i;
if (b0)
{
TMDAT = 0; //产生一个下降沿,低电平至少保持1us //
i++; i++;
TMDAT = 1; //输出1
i = 9; while (i--); //高电平保持60us //
}
else
{
TMDAT = 0; // 写0
i = 9; while (i--); //低电平保持60us //
TMDAT = 1;
i++; i++;
}
}
//向总线上写一个字节
void WrByte (U8 dat)
{
U8 i;
bit testb;
for (i=0;i<8;i++)
{
testb = dat & 0x01;
dat = dat >> 1;
WrBit(testb);
}
}
//函数功能 :写1-Wire协议头操作(复位芯片、选择芯片、写命令码)
//输入参数 :<pSN>芯片序号
// : <byCommand>命令码
void SendHeaderData(U8 *pSN, U8 byCommand)
{
U8 i;
ResetChip(); //复位
Delay_ms(1); //延时
//***********************
//如果总线上只有一个设备,不需要选择芯片操作
#if (CHIP_NUM_IN_WIRE == 1)
WrByte(0xcc); //总线上只有一个设备,跳过芯片匹配步骤
#else
WrByte(0x55); //发送ROM匹配命令
for(i=0;i<8;i++)
{
WrByte(*pSN++); //发送64位序列号
}
#endif
WrByte(byCommand); //发送读取中间寄存器命令
}
//函数功能 : 读温度芯片中间寄存器(从偏移地址0开始)
//输入参数 : <pSN>温度芯片的序号(ROM码)
// : <pRdData> 存放读取出的数据
// : <byLen>需读取的数据的长度
void RdScratchpad(U8 *pSN, U8 *pRdData, U8 byLen)
{
U8 i;
//输入参数检查
if(byLen > 9)
{
byLen = 9;
}
SendHeaderData(pSN, 0xbe);
//读出数据
for(i=0;i<byLen;i++)
{
*pRdData++ = RdByte();
}
ResetChip(); //复位芯片,结束读操作
Delay_ms(1); //延时
}
//函数功能 : 写温度芯片中间寄存器(从偏移地址2开始)
//输入参数 : <pSN>温度芯片的序号(ROM码)
// : <pWrData> 写到中间寄存器的源数据
// : <byLen>写入数据的长度
void WrScratchpad(U8 *pSN, U8 *pWrData, U8 byLen)
{
U8 i;
//输入参数检查
if(byLen > 2)
{
byLen = 2;
}
SendHeaderData(pSN, 0x4e); //发送协议头
//写入数据
for(i=0;i<byLen;i++)
{
WrByte(*pWrData++);
}
ResetChip(); //复位芯片,结束写操作
Delay_ms(1); //延时
}
//函数功能:启动温度转换过程
//输入参数:<pSN>芯片序号
void StartConvertTmpt (U8 *pSN) //
{
U8 byBusyFlag=0;
SendHeaderData(pSN, 0x44); //发送协议头
while(1) //某些情况下,这里可能出现死循环
{
byBusyFlag = RdByte();
if(byBusyFlag == 0xff)
{
break;
}
}
ResetChip (); //复位,保持低电平480-960us //
Delay_ms(1);
}
//函数功能 :读取温度
//输入参数 : <pSN>芯片序号
//输出参数 : 温度值,放大10倍的整数
S16 RdTemperture (U8 *pSN) //
{
U8 byRdData[8];
U8 byTEMP_READ;
U8 byCOUNT_PER_C;
U8 byCOUNT_REMAIN;
S16 t;
float ft;
RdScratchpad(pSN, byRdData, 8); //读取数据,没有读CRC校验码
//0.5摄氏度精度的计算方法
// t = byRdData[0]+(byRdData[1]<<8); //1表示0.5摄氏度
// return t;
t = byRdData[0]+(byRdData[1]<<8);
byTEMP_READ = t>>1;
byCOUNT_REMAIN = byRdData[6];
byCOUNT_PER_C = byRdData[7];
ft = (float)byTEMP_READ - 0.25 + (float)(byCOUNT_PER_C - byCOUNT_REMAIN)/(float)byCOUNT_PER_C;
t = ft*10;
return t; //1表示0.1摄氏度
}
//函数功能 :读取芯片序号(只能在总线只有一个器件时调用)
//输入参数 : <pSN>返回的芯片序号存放地址
void ReadROM(U8 *pSN) //
{
U8 i;
ResetChip (); //复位
Delay_ms (1); //延时
WrByte(0x33); //发送读序列号子程序
for(i=0;i<8;i++)
{
*pSN ++ = RdByte(); //读取第一个序列号,应为10H; //
}
}
//功能 :写温度报警上下限
//输入参数 : <pSN>温度芯片序号
// : <nHighAlarmLim> 温度报警上限
// : <nLowAlarmLim> 温度报警下限
U8 WrTmptAlarmLim(U8 *pSN, S16 nHighAlarmLim, S16 nLowAlarmLim)
{
U8 byWrData[2];
U8 byRdData[4];
byWrData[0] = nHighAlarmLim;
byWrData[1] = nLowAlarmLim;
WrScratchpad(pSN, byWrData, 2); //写入数据
RdScratchpad(pSN, byRdData, 4); //读出数据进行校验
if((byRdData[2] != nHighAlarmLim) || (byRdData[3] != nLowAlarmLim))
{
return FALSE;
}
//将中间寄存器数据拷贝到E2RAM(存放报警限数据)
SendHeaderData(pSN, 0x48);
Delay_ms (6); //延时6ms
ResetChip(); //复位芯片,结束本次操作
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -