📄 digthermo.c
字号:
/*此程序实现了ds18b20温度传感器的单线数据采集,并且通过LED显示小数和整数部分*/
#include "DigThermo.h"
/* 延时t*11us */
void delay(uint t)
{
for(;t>0;t--);
}
/* 产生复位脉冲初始化DS18B20 */
void TxReset(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; //presence=0 复位成功,继续下一步
}
delay(45); //延时500 us
presence=~DQ;
}
DQ=1; //拉高电平
}
/* 读取数据的一个字节 */
uchar RdByte(void)
{
uchar i;
uchar value=0;
for(i=8;i>0;i--)
{
DQ=1;_nop_();_nop_();
value>>=1;
DQ=0;_nop_();_nop_();_nop_();_nop_(); //4 us
DQ=1;_nop_();_nop_();_nop_();_nop_(); //4 us
if(DQ)value|=0x80;
delay(6); //66 us
}
DQ=1;
return(value);
}
/* 写数据的一个字节 */
void WrByte(uchar val)
{
uchar i;
for(i=8;i>0;i--)
{
DQ=1;_nop_();_nop_(); //从高拉倒低
DQ=0;_nop_();_nop_();_nop_();_nop_(); //5 us
DQ=val&0x01; //最低位移出
delay(6); //66 us
val=val/2; //右移1位
}
DQ=1;
delay(1);
}
/*功能匹配*/
bit match_rom(uchar *rom)
{
uchar i;
TxReset();
WrByte(0x55);
for(i=8;i>0;i--)
{
WrByte(*(rom+i-1));
}
return 1;
}
/* 读取温度值 */
void RdTemp(uchar *serial)
{
TxReset(); // 产生复位脉冲,初始化DS18B20
delay(200); // 延时
WrByte(0xcc); // skip rom 命令
WrByte(0x44); // read scratchpad 命令
delay(1); // 延时
match_rom(serial); //匹配
WrByte(0xbe); // convert T 命令
tplsb = RdByte(); // 温度值低位字节(其中低4位为二进制的“小数”部分)
tpmsb = RdByte(); // 高位值高位字节(其中高5位为符号位)
}
/*对采集到的数据进行处理*/
void DataChange()
{
uint tem;
uchar temp,flag;
uchar low,j;
if(tpmsb>7)
{
flag=1;
tem=tpmsb;
tem<<=8;
tem=tem|tplsb; // 两字节合成一个整型变量。
tem=(tem^0xffff);//异或
tem=tem+1; //取反加1
tplsb=tem&0xff;
tpmsb=tem>>8;
}
temp=tpmsb<<4&0x70;
temp=temp|(tplsb>>4);
display[6]=temp/100; // 取百位数据暂存
display[5]=temp%100/10; // 取十位数据暂存
display[4]=temp%100%10;; // 取个位数据暂存
low=tplsb&0x0f;
switch(low) //处理小数部分,对于12位的分辨率,以0.625和对应的数据相乘可以得出16种情况0000~1111
{
case 0:
display[3]=0;
break;
case 1:
display[3]=0;
display[2]=6;
display[1]=2;
display[0]=5;
break;
case 2:
display[3]=1;
display[2]=2;
display[1]=5;
break;
case 3:
display[3]=1;
display[2]=8;
display[1]=7;
display[0]=5;
break;
case 4:
display[3]=2;
display[2]=5;
break;
case 5:
display[3]=3;
display[2]=1;
display[1]=2;
display[0]=5;
break;
case 6:
display[3]=3;
display[2]=7;
display[1]=5;
break;
case 7:
display[3]=4;
display[2]=3;
display[1]=7;
display[0]=5;
break;
case 8:
display[3]=5;
break;
case 9:
display[3]=5;
display[2]=6;
display[1]=2;
display[0]=5;
break;
case 10:
display[3]=6;
display[2]=2;
display[1]=5;
break;
case 11:
display[3]=6;
display[2]=8;
display[1]=7;
display[0]=5;
break;
case 12:
display[3]=7;
display[2]=5;
break;
case 13:
display[3]=8;
display[2]=1;
display[1]=2;
display[0]=5;
break;
case 14:
display[3]=8;
display[2]=7;
display[1]=5;
break;
case 15:
display[3]=9;
display[2]=3;
display[1]=7;
display[0]=5;
break;
default:break;
}
if(flag) //把负号标志放在整数最高位不是0的前一位
{
if(display[6]==0&display[5]!=0) display[6]=16;
if(display[6]==0&display[5]==0&display[4]!=0) display[5]=16;
if(display[6]==0&display[5]==0&display[4]==0) display[5]=16;
flag=0;
}
for(j=6;j>3;j--)
{
if(display[j]!=0)
break;
if(j==4) break; //当第一个整数位为0时,此位的0显示;
display[j]=17; // 使为0的数据不显示
}
}
/*uchar * read_rom(void)
{
uchar rom[8],i;
TxReset();
WrByte(0x33);
for(i=7;i>=0;i--)
{
rom[i]=RdByte();
}
return &rom[0];
} */
/*定时中断,显示采集的温度*/
void t0(void) interrupt 1 using 0
{
uchar i,tr;
P2=0xff;
if(i==4)//使第四位带有小数点
tr=0x80;
else //其他位小数点不显示
tr=0x00;
P0=(tr|dispcode[display[i]]);
P2=dispbitcode[7-i];
i++;
if(i==8) i=0;
TH0=(65536-2200)/256;
TL0=(65536-2200)%256;
}
/*主函数*/
void main(void)
{
uchar i;
TMOD=0x01;
TH0=(65536-2200)/256;
TL0=(65536-2200)%256;
TR0=1;
ET0=1;
EA=1;
while(1)
{
delay(130);
RdTemp(get_serial+i*8); // 读取温度
display[7]=i+10; //显示当前传感器的编号
DataChange(); //数据处理
i++ ;
if(i==3) i=0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -