📄 18b20shu.c
字号:
#include "reg51.H"
#include "intrins.h"
#define DELAY5US _nop_();
sbit SDA=P1^0;
sbit SCL=P1^1;
sbit P1_7=P1^7;
#define WSLA1 0x70
#define RSLA1 0x71
sbit DQ=P3^3;
//*************** 函数声明 *********************
void STA(void);
void STOP(void);
void CACK(void);
void WRBYT(unsigned char *p);
void WRNBYT(unsigned char *R3,unsigned char *R2,unsigned char *R0,unsigned char n);
unsigned b[20]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe4,0xfe,0xf6,0xee,0x3e,0x9c,0x7a,0x9e,0x8e,0xfa,0x1e,0x12,0x00};
unsigned char GET_TEMPER();
unsigned char temp[2],temp_num;
void INIT_1820(); //初始化函数
void TEMP_COV(); //温度转换函数
void WRITE_1820(unsigned char datax); //写DS18B20函数
void READ_1820(); //读DS18B20函数
void DELAY60US();
void DELAY80US();
void DELAY300US();
void DELAY();
unsigned char FLAG1;
//*************** 主函数 *********************
main()
{
//unsigned char datay;
unsigned char a[8]={0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc};
unsigned char shu,n,*c,*y,*x,wai=0x10,WSLA=WSLA1,f4,ffh,ffl,xiaoh,xiaol;//f4是小数的二进制数
unsigned long int h=0,f,ff;
//P1=0xff;
while(1)
{
GET_TEMPER(); //采集温度函数(数据在temp[0]、temp[1]中)
TEMP_COV(); //将12位精度的数值转换成8位温度值在temp_num中
h=(unsigned long int)temp_num;
f4=temp[0]&0x0f;
f=(unsigned long int)f4;
ff=f*10000/16;
xiaoh=ff/100;
xiaol=ff%100;
shu=(unsigned char)h;
a[4]=shu%10;//a[0]为个位
a[4]=b[a[4]]+1;//将a【0】变为字符码
a[5]=shu%100;
a[5]=a[5]/10;
a[5]=b[a[5]];
a[6]=shu/100;
a[6]=b[a[6]];
ffh=(unsigned char)xiaoh;
a[2]=ffh%10;
a[2]=b[a[2]];
a[3]=ffh/10;
a[3]=b[a[3]];
ffl=(unsigned char)xiaol;
a[0]=ffl%10;
a[0]=b[a[0]];
a[1]=ffl/10;
a[1]=b[a[1]];
x=&WSLA;
c=&wai;
y=a;
n=8;
WRNBYT(x,c,y,n);
DELAY();
//datay=temp_num; //缓冲
//P1=~datay; //数据取反后送P1口输出
}
}
unsigned char GET_TEMPER()
{ unsigned char i;
DQ=1;
BCD:INIT_1820(); //对DS18B20初始化
if(FLAG1!=1)
goto BCD; //如果18B20不存在返回继续
DELAY80US(); //存在时延时
i=0xcc; //写ROM命令(跳过序列号)
WRITE_1820(i);
i=0x44; //发送温度转换命令
WRITE_1820(i);
DELAY(); //延时等待转换
CBA:INIT_1820(); //对DS18B20初始化
if(FLAG1!=1)
goto CBA; //如果18B20不存在返回继续
DELAY80US(); //存在时延时
i=0xcc; //写ROM命令(跳过序列号)
WRITE_1820(i);
i=0xbe; //发出读温度命令
WRITE_1820(i);
READ_1820(); //READ_1820
}
void INIT_1820()
{ DQ=1;
_nop_();
DQ=0;
DELAY300US();
DQ=1;
DELAY80US();
if(DQ!=0x01) FLAG1=0x01; //建立标志
else FLAG1=0x00;
DELAY300US();
DQ=1; //释放总线
}
void WRITE_1820(unsigned char datax)
{ unsigned char i;
for(i=0;i<8;i++)
{ //DQ=0后15US之内就应当把数据发送到DQ上
DQ=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
if(datax & 0x01)DQ=1; //根据datax 组装发送位DQ
else DQ=0; //或者使用 DQ=datax&0x01;
datax=datax>>1;
DELAY60US(); //DS18B20在DQ=0的15-60us内采样DQ
DQ=1;
_nop_();
}
}
void READ_1820() //从DS18B20中连续读出两个字节温度值
{ unsigned char i,j; //数据送temp[2]中,其中temp[0]为低8位,temp[1]为高四位
for(i=0;i<2;i++)
{ temp[i]=0xff;
for(j=0;j<8;j++)
{
DQ=1;
_nop_();
DQ=0; //拉低DQ
_nop_(); //维持1US
DQ=1; //释放
_nop_(); //DQ=0后15US内主控器必须完成采样DQ
temp[i]=temp[i]>>1;
if(DQ==1) temp[i]=temp[i]|0x80;
else temp[i]=temp[i]&0x7f;
DELAY60US(); //>60US 后释放DQ
}
}
}
void TEMP_COV() //将temp[0]、temp[1]中的12位数职去掉低4位(小数)
{unsigned char i,j; //合并到 temp_num中
i=temp[0]&0xf0;
i=i>>4;
j=temp[1]<<4;
temp_num=i|j;
}
void DELAY60US()
{ unsigned char i;
for(i=0;i<6;i++);
}
void DELAY80US()
{ unsigned char i,j;
for(i=0;i<8;i++)
for(j=0;j<1;j++);
}
void DELAY300US()
{ unsigned char i,j;
for(i=0;i<33;i++)
for(j=0;j<1;j++);
}
void DELAY()
{ unsigned char i,j;
for(i=0;i<255;i++)
for(j=0;j<250;j++);
}
//【附录二】由C语言编制的I2C通讯子函数
// 以上的内容如果在主函数的前面已经包含、声明时,可以省略。
//#################################################################################
void STA(void) //启动信号子函数
{ SDA=1;
SCL=1;
DELAY5US
SDA=0;
DELAY5US
SCL=0;
}
//#################################################################################
void STOP(void) //停止信号子函数
{ SDA=0;
SCL=1;
DELAY5US
SDA=1;
DELAY5US
}
//#################################################################################
void MACK(void) //应答信号子函数
{ SDA=0;
SCL=1;
DELAY5US
SCL=0;
SDA=1;
}
//#################################################################################
void NMACK(void) //非应答信号子函数
{ SDA=1;
SCL=1;
DELAY5US
SCL=0;
SDA=0;
}
//#################################################################################
void CACK(void) //应答检测子程序
{
SDA=1;
SCL=1;
DELAY5US
F0=0;
if(SDA==1)
F0=1;
SCL=0;
}
//#################################################################################
// 发送一字节子数据程序 WRBYT
//#################################################################################
void WRBYT(unsigned char *p)
{ unsigned char i=8,temp;
temp=*p;
while(i--)
{ if((temp&0x80)==0x80)
{ SDA=1;
SCL=1;
DELAY5US
SCL=0;
}
else
{ SDA=0;
SCL=1;
DELAY5US
SCL=0;
}
temp=temp<<1;
}
}
//#################################################################################
// 接收一字节子数据程序 RDBYT
//#################################################################################
void RDBYT(unsigned char *p)
{ unsigned char i=8,temp=0;
while(i--)
{ SDA=1;
SCL=1;
DELAY5US
temp=temp<<1;
if(SDA==1)
temp=temp|0x01;
else
temp=temp&0xfe;
SCL=0;
}
*p=temp;
}
//#################################################################################
// 发送N个字节子数据程序 WRNBYT
//#################################################################################
void WRNBYT(unsigned char *R3,unsigned char *R2,unsigned char *R0,unsigned char n)
{
loop: STA();
WRBYT(R3);
CACK();
if(F0)
goto loop;
WRBYT(R2);
CACK();
if(F0)
goto loop;
while(n--)
{ WRBYT(R0);
CACK();
if(F0)
goto loop;
R0++;
}
STOP();
}
//#################################################################################
// 接收N个字节子数据程序 RDNBYT
//#################################################################################
//【子函数入口参数说明】:
//R3是外部器件地址写,R4是外部器件地址读,R2是从器件内部子地址,R0是目标数据块首地址,//n是要读的字节数
void RDNBYT(unsigned char *R3,unsigned char *R4,unsigned char *R2,unsigned char *R0,unsigned char n)
{
loop1: STA();
WRBYT(R3);
CACK();
if(F0)
goto loop1;
WRBYT(R2);
CACK();
if(F0)
goto loop1;
STA();
WRBYT(R4);
CACK();
if(F0)
goto loop1;
while(n--)
{ RDBYT(R0);
if(n>0)
{
MACK();
R0++;
}
else NMACK();
}
STOP();
}
//#################################################################################
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -