📄 ds18b20.c
字号:
#include<reg52.h>
#include<absacc.h>
#include<intrins.h>
#define unit unsigned int
#define uchar unsigned char
#define FALSE 0
#define TRUE 1
#define DS18B20MAX 10
sbit LED=P1^6;
sbit DQ=P1^7;
uchar ROMID[DS18B20MAX][8]; // 该DS18B20的ROMID是 28 CB 81 C2 00 00 00 41
uchar scratchPad[9];
uchar TH=0x64; // 温度监测系统设定的温度报警上限值
// 0 1100100 设为100摄氏度
uchar TL=0xd8; // 温度监测系统设定的温度报警下限值
// 1 1011000 设为零下40摄氏度
uchar confgReg=0x3f; // 温度监测系统设定的配置寄存器数据值
// 0 01 111111 分辨率为10位,最大转换时间187.5秒
void initial(void)
{
IE=0x00;
TMOD=0x20;
PCON=0x00;
SCON=0x40;
TH1=0xfd;
TL1=0xfd;
LED=1;
}
void delay_1s(void)
{
unsigned char i;
unsigned int j;
for(i=0;i<250;i++)
for(j=0;j<672;j++);
}
void delay(int time) // 延时子程序
{ // 系统采用的是11.059MHz的晶振,所以该延时程序产生16*time+24μs 的延时
int i;
for(i=0;i<time;i++);
}
bit bus_reset(void) // 产生单总线系统的总线复位信号,并返回总线上是否存在单总线器件信息
{ // 若返回0表明总线上存在单总线器件,若返回1表明总线上不存在单总线器件
bit presence;
DQ=0; // 拉低DQ总线开始复位
delay(28); // 保持DQ低480μs
DQ=1; // 释放DQ
delay(5); // 等待大于60us,等待从设备将总线拉低,如果有从设备就拉低,否则就是高电平
presence=DQ; // 获取应答信号
delay(25); // 等待总线初始化过程结束
return(presence); // 返回应答信号,有芯片应答presence=0
// 无芯片应答presence=1
}
bit read_bit(void) // 从总线上读取一个数据位
{
DQ=0; // 将总线DQ拉低启动读时隙
DQ=1; // 释放DQ信号线,等待从机返回数据位
_nop_(); // 延时4μs再读数据
_nop_();
_nop_();
_nop_();
return DQ;
}
uchar read_byte(void) // 从单总线上读取一个字节
{
uchar i;
uchar value=0; // 将返回值初始化为0
for(i=0;i<8;i++)
{
if(read_bit())
value|=0x01<<i; // 读一字节数据,一个读时序中读一位,并做移位处理
delay(3); // 延时60μs以完成此次读时序,之后再读下一位数据
}
return(value);
}
void write_bit(uchar bitval) // 向单总线上写一个数据位
{
DQ=0; // 拉低DQ以开始一个写时序
if(bitval==1)
DQ=1; // 如要写"1"则将总线置高
delay(3); // 延时60μs供DS18B20采样
DQ=1; // 释放DQ总线
}
void write_byte(uchar val) // 向单总线上写一个数据字节
{
uchar i;
uchar temp=0; // 将返回值初始化为0
for(i=0;i<8;i++) // 写一字节数据,一次写一位
{
temp=val>>i; // 移位操作,将本次要写的位移到最低位
temp&=0x01;
write_bit(temp); // 向总线写该位
}
delay(5); // 等待时隙结束
}
/*uchar send_matchRom(uchar DS18B20No) // 系统主机向总线发出匹配ROM命令
{ // ROM ID是编号为DS18B20No的温度传感器的ROM序列号
uchar i;
if(bus_reset()) return FALSE; // 如果总线上没有器件,返回FALSE
write_byte(0x55); // 向总线写匹配命令0x55
for(i=0;i<8;i++) // 连续写入8个字节的ROMID
{
write_byte(ROMID[DS18B20No][i]); // 向总线写ROMID的第i个字节
}
return TRUE;
}
void read_scratchPad(uchar DTNo) // 系统主机从指定的DS18B20中读取便笺存储器的所有字节
{ // 读取的结果放到全局变量scratchPad[9]中
uchar i;
send_matchRom(DTNo); // 向总线发出匹配ROM命令,使编号为DTNo的器件处于选中状态
write_byte(0xBE); // 向总线发出读便笺存储器命令
for(i=0;i<9;i++) // 连续读入9个字节的便笺存储器单元
{
scratchPad[i]=read_byte(); // 从总线读取1个字节存入scratchPad[i]
}
}
void write_scratchPad(uchar DTNo) // 系统主机向指定的DS18B20中写入TH、TL及配置寄存器数据
{
send_matchRom(DTNo); // 向总线发出匹配ROM命令,使编号为DTNo的器件处于选中状态
write_byte(0x4E); // 向总线发出写便笺存储器命令
write_byte(TH);
write_byte(TL);
write_byte(confgReg);
}
void read_ROMID(void) // 总线上只有一个DS18B20时,主机读出它的64位ROM代码
{
uchar i;
write_byte(0x33); // 启动读ROM
for(i=0;i<8;i++)
{
ROMID[0][i]=read_byte();
}
}*/
main()
{
uchar i,k,th,tl;
unit t=0;
float result;
P1=0x7f;
DQ=0;
initial();
TR1=1;
while(1)
{
i=bus_reset(); // 如果总线上没有DS18B20,就等待
/* read_ROMID(); // 读出它的序列号
for(i=0;i<8;i++)
{
SBUF=ROMID[0][i];
while(TI==0);
TI=0;
}*/
// delay_1s();
// send_matchRom(0); // 匹配第0个传感器
// write_scratchPad(0); // 写入TH、TL、配置寄存器
write_byte(0xCC);
write_byte(0x44); // 启动转换
while(!read_bit()); // DQ 为低电平,等待,DQ为高表示转换结束
bus_reset();
// read_scratchPad(0); // 读取温度值,scratchPad的前两个字节就是温度
write_byte(0xCC);
write_byte(0xBE);
tl=read_byte();
th=read_byte();
tl&=0xfc; // 精度是10位,因此最低两位无效,屏蔽掉
t=th;
t<<=8;
t|=tl;
result=t*0.0625;
k=(uchar)result;
LED=!LED; // 发光二极管亮,提示发出一个数据
SBUF=k;
while(TI==0);
TI=0;
delay_1s();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -