📄 18b20.c
字号:
#include<at89x51.h>
//#include<port.h>
#include"intrins.h"
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P3^6;
// uchar code tv[]={0xf7,0xfb,0xfd,0xfe};
// uchar code a[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff};
// uchar data led[4];
//共阳段码表
//字节的高位对应数码管的H段,依次类推
//static unsigned char code number_Tab[21]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90//0-9共阳段码表
unsigned int j=0; //,0xbf,0xff}; //-和清0共阳段码表
unsigned char dispbitcode[8]={0xf7,0xfb,0xfd,0xfe/*,0xef,0xdf,0xbf,0x7f*/}; //位扫描
unsigned char dispcode[12]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xc6,0xff};
//共阳数码管字段码 0xc6表示C温度符号。
unsigned char dispbuf[4];
// 延时子函数
//**************************************************************/
void delay(uint t)
{ for (; t>0 ; t--) ;
}
/************************************************************
/* 产生复位脉冲初始化DS18B20 */
void ow_reset(void)
{ char presence=1;
while(presence)
{
while(presence)
{
DQ=1;_nop_();_nop_();//从高拉倒低
DQ=0;
//delay(50); //550 us
DQ=1;
// delay(6); //66 us
presence=DQ; // 一直等到得到存在脉冲DQ=0 presence=0 复位成功,继续下一步
}
// delay(45); //延时500 us
presence=~DQ;
}
DQ=1; //拉高电平
}
/************************************************************
向 1-WIRE 总线上写一个字节**数据线从高电平拉至低电平,产生写起始信号。
15ms之内将所需写的位送到数据线上
**************************************************************/
void write_byte(uchar val)
{
uchar i;
for (i=8; i>0; i--) //在15~60ms之间对数据线进行采样,如果是高电平就写1,低写0发生。
{
DQ = 1;_nop_(); _nop_(); //在开始另一个写周期前必须有1Us以上的高电平恢复期。
DQ = 0;_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); //5us
DQ = val&0x01; //最低位移出
// delay(6) ; //66us
val = val/2; //右移1位
}
// delay(1);
}
/************************************************************
//读1字节 //主机数据线先从高拉至低电平1us以上,再使数据线升为高电平,从而产生读信号
**************************************************************/
uchar read_byte (void)
{
uchar i;
uchar value = 0;
for(i = 8;i>0;i--)
{
DQ = 1; // 给脉冲信号
_nop_(); _nop_();
value>>= 1;
DQ = 0; // 给脉冲信号
_nop_(); _nop_(); _nop_(); _nop_();_nop_(); //4us
DQ = 1; _nop_();_nop_();_nop_();_nop_();_nop_();//5us
if(DQ)
{ value|= 0x80 ; }
// delay(13); //66us 注意延时的长短,如果是delay(6) 会造成LED闪烁
}
DQ = 1;
return(value) ;
}
/*--------------------------------------------------------------------------------------
设置DS18B20转换精度及报警**见配置寄存器说明**
-----------------------------------------------------------------------------------------*/
void Setting_DS18B20(void)
{
ow_reset();
write_byte(0xCC); // 跳过读序号列号的操作
write_byte(0x4e);//准备往暂存器2,3位TH,TL写数据
write_byte(0x64); //100不使用DS18B20本身的温度告警设置,为进行转换精度设定,凑两个写寄存器操作
write_byte(0x8a); //-10
write_byte(0x7f); //设置DS18B20 为12位转换精度 R1,R0的值决定转换精度 R1=R0=1对应12位
}
/*--------------------------------------------------------------------------------------
读取温度并完成转化,
-----------------------------------------------------------------------------------------*/
void Read_Temperature(void)
{
uchar tplsb,tpmsb; // 温度值低位、高位字节
uchar flag=0;
// unsigned int j=0; //暂存计算得温度的整数部分
float tt;
ow_reset();
write_byte(0xCC); // 跳过读序号列号的操作
write_byte(0x44); // 启动温度转换
ow_reset();
write_byte(0xCC); //跳过读序号列号的操作
write_byte(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
tplsb=read_byte(); // 温度值低位字节(其中低4位为二进制的“小数”部
tpmsb=read_byte(); // 高位值高位字节(其中高5位为符号位
//转换温度
j=tpmsb;
j<<=8;
j+=tplsb; //写为j=j|tplsb;也可以。// 两字节合成一个整型变量。
if(tpmsb>7)
{
j=(j^0xffff);//异或
j=j+1; //如果温度小于0,这5位为1,测到的数值需要取反加1再乘于0.0625即可得到实际 温度。
}
tt=(j*0.0625);
j=tt*10+0.5; //四舍五入成整数,并扩大十倍 此处暂不考虑符号
dispbuf[3]=j/100%10; //十位
dispbuf[2]=j/10%10; //个位
dispbuf[1]= j%10;//取温度小数点1位
//dispbuf[3]=j/1000; //百位
/*此程序用的是三极管驱动4位数码管显示,考虑到为数有限,将百位和负号位屏蔽掉*/
dispbuf[0]=10; //表示温度符号C
}
/*------------------------------------------------------------------------
温度显示
-------------------------------------------------------------------------*/
void disp(void)
{
uint k;
/*此程序用的是三极管驱动4位数码管显示,考虑到为数有限,将百位和负号位屏蔽掉*/
//if(tpmsb>7) //表示负温度
// { //把负号标志放在整数最高位不是0的前一位
// if(temperature_tab[0]==0&&temperature_tab[1]!=0) temperature_tab[0]=10;
// if(temperature_tab[0]==0&&temperature_tab[1]==0){ temperature_tab[0]=11;temperature_tab[1]=10;}
//}
for(k=0;k<4;k++)
{
P0 = dispbitcode[k];
P2 = dispcode[dispbuf[k]];
// delay(30);
if(k==2) //加上数码管的dp小数点
P2&=0x7f;
// delay(40);
P0=0xff;
}
}
/*------------------------------------------------------------------------
主函数
--------------------------------------------------------------------*/
main ()
{
Setting_DS18B20();
while(1)
{
Read_Temperature(); _nop_(); _nop_(); _nop_();
disp();
}
}
//**********************配置寄存器******************************//
//该字节各位的意义如下:
//表3: 配置寄存器结构
//TM R1 R0 1 1 1 1 1
//低五位一直都是"1",TM是测试模式位,用于设置DS18B20在工作模式还是在测试模式。
//在DS18B20出厂时该位被设置为0,用 户不要去改动。R1和R0用来设置分辨率,如下表所示:(DS18B20出厂时被设置为12位)
//表4: 温度分辨率设置表
//R1 R0 分辨率 温度最大转换时间
//0 0 9位 93.75ms
//0 1 10位 187.5ms
//1 0 11位 375ms
//1 1 12位 750ms
///****************温度符号的说明********/////
//12位转化后得到的12位数据,存储在18B20的两个8比特的RAM中,二进制中的前面5位是符号位,
//如果测得的温度大于0, 这5位为0,只要将测到的数值乘于0.0625即可得到实际温度;
//如果温度小于0,这5位为1,测到的数值需要取反加1再乘于0.0625即可得到实际 温度。
//例如+125℃的数字输出为07D0H,+25.0625℃的数字输出为0191H,-25.0625℃的数字输出为FF6FH,
//-55℃的数字输出为FC90H 。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -