
/ds18b20读一个字节/
unsigned char ReadOneChar(void)
{
uchar i=0; //定义i用于循环
uchar dat = 0; //读取的8位数据
for (i=8;i>0;i--) //8次循环
{
DQ = 0; //拉低DQ总线开始读时序
dat>>=1; //dat左移一位
DQ = 1; //释放DQ总线
if(DQ) //如果DQ=1,执dat|=0x80;(0x80即第7位为1,如果DQ为1,即读取的数据为1,将dat的第7为置1,然后dat>>=1,循环8次结束,dat即为读取的数据)
//DQ=0,就跳过
dat|=0x80;
delay_18B20(4); // 延时以完成此次读时 序,之后再读下一数据
}
return(dat); //返回读取的dat
}
DQ = dat&0x01;这句语句是错误的。DQ为位变量,而dat为 unsigned char
如果真要这么写的话,应该是这样 :DQ = (bit)dat&0x01;
把我写的给你做个参考吧:
extern uchar8 sig; //sig判定温度符号
/延时函数/
void delay (int us) //DELAY-110592MHZ 调用程序大约为24us,每次循环为16us
{
int s;
for(s=0;s<us;s++);
}
void delayms(int z) //z为毫秒数
{
int x,y;
for(x=z;x>0;x--)
for(y=125;y>0;y--);
}
/复位程序/
unsigned char reset(void)
{
uchar8 presence;
DQ=0; //拉低总线。当总线停留在低电平480us-960us ,总线上所以器件都将被复位
delay(30); //保持低电平504us
DQ=1; //释放总线,让其恢复高电平
delay(3); //等待芯片应答信号
presence=DQ; //获取应答信号
delay(25); //延时以完成整个时序
return(presence); //返回应答信号。有芯片应答返回0,否则返回1。
}
/写一位数据/
void write_bit(char bitval)
{
DQ=0; //拉低DQ总线,开始时序
if(bitval==1) //如果写入的为1,则返回高电平
DQ=1;
delay(5); //延时104us,以完成整个时序
DQ=1;
}
/写一字节数据/
void write_byte(char val)
{
uchar8 i,temp;
for (i=0;i<8;i++) //写入一个字节的数据,一个时序中写一次
{
temp=val>>i; //右移i位
temp&=0x01; //复制那位数据到temp
write_bit(temp); //调用write_bit()
}
delay(5); //延时104us以完成此次时序,之后再写下一数据
}
/读一位数据/
uchar8 read_bit(void)
{
uchar8 i;
DQ=0; //拉低DQ,开始读时序
DQ=1; //释放DQ总线
for(i=0;i<3;i++); //从时序开始延时15us
return(DQ); //返回DQ值
}
/读一字节数据/
uchar8 read_byte(void)
{
uchar8 i,value=0;
for(i=0;i<8;i++)
{
if(read_bit()) //读一字节数据,一个时序中读一次,并作移位处理
value|=0x01<<i;
delay(6); //延时以完成此次读时序,之后再读下一数据
}
return(value);
}
/温度转化/
void tmconvert(void)
{
reset(); //复位
delay(1);
write_byte(0xcc); //仅一个DS18b20 ,跳过ROM
write_byte(0x44); //温度变换
}
/读取温度/
long gettm(void)
{
uchar8 LSB=0,MSB=0; //用于存储读取的温度
long temp;
reset(); //复位
write_byte(0xcc); //写指令,跳过ROM,仅一个DS18b20
write_byte(0xbe); //写指令,读暂存存储器
LSB = read_byte(); //读LSB
MSB = read_byte(); //读MSB
sig=(MSB>>4==0X0F);
if(sig) //判断符号位是否为负值,是负值了,转去处理
{
LSB=~LSB; //温度处理
MSB=~MSB;
LSB=LSB+1;
}
temp=MSB256+LSB; //十六进制转换为10进制
temp=temp100/16; //12位精度,最小分辨率为00625°C
return temp; //获得001°C 的精度并返回
}
我这是用STC做的,应该很容易移植到MPS430上的给你参考一下。
#include<reg52h>
#include<intrinsh>
#define uchar unsigned char
#define uint unsigned int
sbit scl=P1^3;
sbit sda=P1^4;
sbit key1=P1^6;
sbit key2=P1^7;
sbit key3=P2^0;
sbit key4=P2^1;
sbit lcrs=P3^7;//数据/命令
sbit lcwr=P3^5;//读/写
sbit lcden=P3^4;//使能
sbit DS=P2^2;
/sbit lcrs=P3^4;//数据/命令
sbit lcwr=P3^7;//读/写
sbit lcden=P3^5;//使能
/
sbit jrk=P2^2;
sbit cyk=P2^3;
sbit xhk=P2^4;
bit flag=0,rsg=0,not=0,he=0,in=0;
int acon=0,bcon=0,dcon=0,econ=0,
temp=0,y=0,j=0,l=0,cfj=0,ec=0,dc=0,at;
uchar code table[]={48,49,50,51,52,53,54,55,56,57};
uchar code ta1[]={"Temperature UP"};
uchar code ta2[]={"Temperature DN"};
uchar code ta3[]={"Inflator Cycle"};
uchar code ta4[]={"Inflator Time "};
uchar code ta5[]={" Heating UP "};
uchar code ta6[]={" Inflator "};
uchar code table7[]={"Temperature"};
uchar table1[]={0,0,0,'',0};
uchar table3[]={"AptitudeAquarium"};
uchar table4[]={0,0,0,0,0};
uchar n,c=0;
void delay(uchar);
void wen_kong();
void xh();
void rso();
void weno();
void Init_Com(void)
{
TMOD = 0x11;
PCON = 0x00;
TH1=0x61;
TL1=0x99;
EA=1;
ET1=1;
TR1=1;
}
void delay(uchar count) //delay
{
uint i;
while(count)
{
i=200;
while(i>0)
i--;
count--;
}
}
////初始化18B20/////////
bit init18b20(void)
{
uint i;
bit no;
DS=0;
i=103;
while(i>0)i--;
DS=1;
i=4;
while(i>0)i--;
no=DS;
if(no==0)
{
DS=1;
i=100;
while(i>0)i--;
no=DS;
if(no==1)
not=0;
else
not=1;
}
else
not=1;
return (not);
}
bit tmpreadbit(void) //读一位
{
uint i;
bit dat;
DS=0;
i++;
DS=1;
i++;i++;
dat=DS;
i=8;while(i>0)i--;
return (dat);
}
uchar tmpread(void) //读一个字节
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tmpreadbit();
dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里
}
return(dat);
}
void tmpwritebyte(uchar dat) //写一个字节到 ds18b20
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) //write 1
{
DS=0;
i++;i++;
DS=1;
i=8;while(i>0)i--;
}
else
{
DS=0; //write 0
i=8;
while(i>0)i--;
DS=1;
i++;i++;
}
}
}
int tmp() //DS18B20温度读取
{
float tt;
int a,b;
if(init18b20()==0)
{
WDT_CONTR=0x36; /////喂狗
EA=0;
delay(1);
tmpwritebyte(0xcc); // 跳过读ROM *** 作
tmpwritebyte(0x44); // 启动温度转换
delay(10);
init18b20();
delay(1);
tmpwritebyte(0xcc);
tmpwritebyte(0xbe);
a=tmpread();
b=tmpread();
temp=b;
temp<<=8; //将高字节温度数据与低字节温度数据整合
temp=temp|a;
c=b>>4;
tt=temp00625;
temp=tt10+05; //放大10倍输出并四舍五入
EA=1;
return temp;
}
else
not=1;
}
//////1062/////////
void ydelay(uint x)
{
uint a,b;
for(a=x;a>0;a--)
for(b=10;b>0;b--);
}
void write_com(uchar com)
{
P0=com;
lcwr=0;
lcrs=0;
lcden=0;
ydelay(10);
lcden=1;
ydelay(10);
lcden=0;
lcwr=1;
}
void write_date(uchar date)//写数据
{
P0=date;
lcwr=0;
lcrs=1;
lcden=0;
ydelay(10);
lcden=1;
ydelay(10);
lcden=0;
lcwr=1;
}
void init1602()//初始化
{
write_com(0x38);//设置显示模式
ydelay(20);
write_com(0x0c);//开显示
ydelay(20);
write_com(0x06);//指针和光标自动加一
ydelay(20);
write_com(0x01);//清屏指令
ydelay(20);
}
///////显示程序//////
void display(int num)
{
uint i,A1,A2;
WDT_CONTR=0x35; /////喂狗
if(c!=0)
num=~num+1;
A1=num/1000;
A2=num%1000/100;
if(not==0)
{
if(c!=0)
{
c=0;
table1[0]='-';
}
else if(A1==0)
table1[0]=' ';
else
table1[0]=table[A1];
if(A1==0)
if(A2==0)
table1[1]=' ';
else
table1[1]=table[A2];
table1[2]=table[num%1000%100/10];
table1[4]=table[num%1000%100%10];
}
else
{
table1[0]='';
table1[1]='';
table1[2]='';
table1[4]='';
}
write_com(0x80);
for(i=0;i<11;i++)
{write_date(table7[i]);
delay(2);}
write_com(0x8b);
for(i=0;i<5;i++)
{write_date(table1[i]);
delay(2);}
write_com(0xc0);
for(i=0;i<16;i++)
{
if(he==1)
write_date(ta5[i]);
else if(in==1)
write_date(ta6[i]);
else
write_date(table3[i]);
}
c=0;
WDT_CONTR=0x35; /////喂狗
}
////显示2////////////////////
display2(uchar bh,int dat)
{
uchar a,A,B;
WDT_CONTR=0x35; /////喂狗
//write_com(0x01);//清屏指令
y=dat;
y=y&0x8000;
if(y!=0)
dat=~dat+1;
A=dat/1000;
B=dat%1000/100;
if((bh!=4)&&(bh!=5))
{
if(A!=0)
table4[0]=table[dat/1000];
else if((c!=0)||(y!=0))
{
c=0;y=0;
table4[0]='-';
}
else
table4[0]=' ';
if(B!=0)
table4[1]=table[B];
else
table4[1]=' ';
table4[2]=table[dat%1000%100/10];
table4[3]='';
table4[4]=table[dat%1000%100%10];
}
else
{
table4[0]=' ';
if((c!=0)||(y!=0))
{
c=0;y=0;
table4[1]='-';
}
else
table4[1]=' ';
table4[2]=' ';
table4[3]=table[dat%1000%100/10];
table4[4]=table[dat%1000%100%10];
}
write_com(0xc4);
delay(2);
for(a=0;a<5;a++)
write_date(table4[a]);
delay(2);
write_com(0x80);
switch(bh)
{
case 1:for(a=0;a<14;a++)write_date(ta1[a]);break;
case 2:for(a=0;a<14;a++)write_date(ta2[a]);break;
case 3:for(a=0;a<14;a++)write_date(ta3[a]);break;
case 4:for(a=0;a<14;a++)write_date(ta4[a]);break;
default:break;
}
}
///////////x24c02//////////////////
void delay24()
{ ;; }
void init24c02() //初始化
{
sda=1;
delay24();
scl=1;
delay24();
}
void start() //开始信号
{
sda=1;
delay24();
scl=1;
delay24();
sda=0;
delay24();
}
void stop() //停止
{
sda=0;
delay24();
scl=1;
delay24();
sda=1;
delay24();
}
void respons() //应答
{
uchar i;
scl=1;
delay24();
while((sda==1)&&(i<250))i++;
scl=0;
delay24();
}
void write_byte(uchar date) // 写数据子函数
{
uchar i,temp;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
scl=0;
delay24();
sda=CY;
delay24();
scl=1;
delay24();
}
scl=0;
delay24();
sda=1;
delay24();
}
uchar read_byte() // 读数据子函数
{
uchar i,k;
scl=0;
delay24();
sda=1;
delay24();
for(i=0;i<8;i++)
{
scl=1;
delay24();
k=(k<<1)|sda;
scl=0;
delay24();
}
return k;
}
///////写数据函数///////////////////
void write_add(uchar address,uint date)
{
start();
write_byte(0xa0);
respons();
write_byte(address);
respons();
write_byte(date/256);
respons();
write_byte(date%256);
respons();
stop();
}
uchar read_add(uchar address) //读数据函数
{
uchar date;
start();
write_byte(0xa0);
respons();
write_byte(address);
respons();
start();
write_byte(0xa1);
respons();
date=read_byte();
stop();
return date;
}
void delay1ms(uchar ms)
{
uchar i;
while(ms--)
{
for(i = 0; i< 250; i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
int keyf(int num,int up,int dn)
{
uint i;
uchar z;
for(i=0;i<600;i++)
{
display2(n,num);
if(key1==0)
{
delay1ms(30);
if(key1==0)
{
i=0;
n++;
if(n>=9)
n=0;
while(!key1)
display2(n,num);
break;
}
}
if(key2==0)
{
delay1ms(10);
if(key2==0)
{
i=0;
if(num>=up)
num=up;
else if(n!=4)
num=num+1;
else if(num<100)
num=num+5;
else
num=num+10;
for(z=0;z<65;z++)
{
display2(n,num);
if(key2!=0)
break;
}
while(!key2)
{
for(z=0;z<2;z++)
display2(n,num);
if(num>=up)
num=up;
else if(n!=4)
num=num+1;
else if(num<100)
num=num+5;
else
num=num+10;
}
}
}
if(key3==0)
{
delay1ms(10);
if(key3==0)
{
i=0;
if(num<=dn)
num=dn;
else if(n!=4)
num=num-1;
else if(num<100)
num=num-5;
else
num=num-10;
for(z=0;z<65;z++)
{
display2(n,num);
if(key3!=0)
break;
}
while(!key3)
{
for(z=0;z<2;z++)
display2(n,num);
if(num<=dn)
num=dn;
else if(n!=4)
num=num-1;
else if(num<100)
num=num-5;
else
num=num-10;
}
}
}
}
return(num);
}
void keyjc()
{
uchar i=0;
if(key1==0)
{
delay1ms(10);
if(key1==0)
{
EA=0;
for(i=0;i<20;i++)
{
display(tmp());
}
if(key1==0)
{
write_com(0x01);//清屏指令
n++;
if(n>=5)
n=0;
while(!key1)
{
switch(n)
{
case 1:display2(n,acon);break;
case 0:break;
}
}
if(n==1)
{
keyf(&acon,1250,-530);
if((acon-bcon)<3)
bcon=acon-3;
}
if(n==2)
{
keyf(&bcon,1240,-550);
if((acon-bcon)<3)
acon=bcon+3;
}
write_add(1,acon);//A
delay1ms(15);
write_add(3,bcon);//B
n=0;
write_com(0x01);//清屏指令
}
EA=1;
}
}
}
key()
{
uint i;
if(key4==0)
delay1ms(50);
if(key4==0)
{
write_com(0x01);//清屏指令
for(i=0;i<500;i++)
{
if(key4==0)
{
delay1ms(15);
if(key4==0)
{
i=0;
n++;
if(n>=5)
n=0;
while(!key4)
{
switch(n)
{
case 1: display2(1,acon);break;
case 2: display2(2,bcon);break;
default: break;
}
}
}
}
switch(n)
{
case 1: display2(1,acon);break;
case 2: display2(2,bcon);break;
default: break;
}
}
n=0;
}
}
///////滤波////////
int filter()
{
int tm,buf[6];
uchar i,j;
EA=0;
for(i=0;i<6;i++)
{
buf[i]=tmp();
delay1ms(20);
WDT_CONTR=0x35; /////喂狗
}
for(j=0;j<5;j++)
for(i=0;i<5-j;i++)
if(buf[i]>buf[i+1])
{
tm=buf[i];
buf[i]=buf[i+1];
buf[i+1]=tm;
}
tm=((buf[2]+buf[3])/2);
EA=1;
return (tm);
}
void main()
{
uchar b,c;
Init_Com();
init1602();
init24c02();
b=read_add(1);
delay1ms(15);
c=read_add(2);
delay1ms(15);
acon=b256+c;
b=read_add(3);
delay1ms(15);
c=read_add(4);
delay1ms(15);
bcon=b256+c;
AUXR=0x01;// 禁止ALE输出
WDT_CONTR=0x35; //启动看门狗
write_com(0x01);//清屏指令
while(1)
{
at=filter();
display(at);
keyjc();
key();
wen_kong();
weno();
}
}
//////温度控制//////////////
void wen_kong()
{
if((flag==0)&&(not==0))
{
at=filter();
if(at<=bcon)
{
flag=1;
jrk=0;
xhk=0;
he=1;
}
}
}
void weno()
{
if(flag)
{
at=filter();
if(at>=acon)
{
flag=0;
jrk=1;
if(rsg)
xhk=0;
else
xhk=1;
he=0;
}
}
if(not==1)
{
flag=0;
jrk=1;
if(rsg)
xhk=0;
else
xhk=1;
he=0;
}
}
//这是我曾经做的一个温度控制系统,可以调节上下限温度,低于下限温度启动加热,高于上限停止加热。
//温控系统控制程序
//版本号:V10;2015619
//温度传感器:DS18B20
//显示方式:LED
#include <reg51h>
#define uchar unsigned char
sbit keyup=P1^0;
sbit keydn=P1^1;
sbit keymd=P1^2;
sbit out=P3^7; //接控制继电器
sbit DQ = P3^4; //接温度传感器18B20
uchar t[2],number=0,pt; //温度值
uchar TempBuffer1[4]={0,0,0,0};
uchar Tmax=18,Tmin=8;
uchar distab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0xfe,0xf7};
uchar dismod=0,xiaodou1=0,xiaodou2=0,currtemp;
bit flag;
void t0isr() interrupt 1
{
TH0=(65536-5000)/256;
TL0=(65536-5000)%256;
switch(number)
{
case 0:
P2=0x08;
P0=distab[TempBuffer1[0]];
break;
case 1:
P2=0x04;
P0=distab[TempBuffer1[1]];
break;
case 2:
P2=0x02;
P0=distab[TempBuffer1[2]]&0x7f;
break;
case 3:
P2=0x01;
P0=distab[TempBuffer1[3]];
break;
default:
break;
}
number++;
if(number>3)number=0;
}
void delay_18B20(unsigned int i)
{
while(i--);
}
/ds18b20初始化函数/
void Init_DS18B20(void)
{
bit x=0;
do{
DQ=1;
delay_18B20(8);
DQ = 0; //单片机将DQ拉低
delay_18B20(90); //精确延时 大于 480us
DQ = 1; //拉高总线
delay_18B20(14);
x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败,继续初始化
}while(x);
delay_18B20(20);
}
/ds18b20读一个字节/
unsigned char ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 给脉冲信号
dat>>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(4);
}
return(dat);
}
/ds18b20写一个字节/
void WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
delay_18B20(5);
DQ = 1;
dat>>=1;
}
}
/读取ds18b20当前温度/
unsigned char ReadTemperature(unsigned char rs)
{
unsigned char tt[2];
delay_18B20(80);
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的 *** 作
WriteOneChar(0x44); //启动温度转换
delay_18B20(80);
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的 *** 作
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器)前两个就是温度
tt[0]=ReadOneChar(); //读取温度值低位
tt[1]=ReadOneChar(); //读取温度值高位
return(tt);
}
void covert1(void) //将温度转换为LED显示的数据
{
uchar x=0x00,y=0x00;
t[0]=pt;
pt++;
t[1]=pt;
if(t[1]&0x080) //判断正负温度
{
TempBuffer1[0]=0x0c; //c代表负
t[1]=~t[1]; /下面几句把负数的补码/
t[0]=~t[0]; /换算成绝对值/
x=t[0]+1;
t[0]=x;
if(x==0x00)t[1]++;
}
else TempBuffer1[0]=0; //A代表正
t[1]<<=4; //将高字节左移4位
t[1]=t[1]&0xf0;
x=t[0]; //将t[0]暂存到X,因为取小数部分还要用到它
x>>=4; //右移4位
x=x&0x0f; //和前面两句就是取出t[0]的高四位
y=t[1]|x; //将高低字节的有效值的整数部分拼成一个字节
TempBuffer1[1]=(y%100)/10;
TempBuffer1[2]=(y%100)%10;
t[0]=t[0]&0x0f; //小数部分
TempBuffer1[3]=t[0]10/16;
//以下程序段消去随机误检查造成的误判,只有连续12次检测到温度超出限制才切换加热装置
if(currtemp>Tmin)xiaodou1=0;
if(y<Tmin)
{
xiaodou1++;
currtemp=y;
xiaodou2=0;
}
if(xiaodou1>12)
{
out=0;
flag=1;
xiaodou1=0;
}
if(currtemp<Tmax)xiaodou2=0;
if(y>Tmax)
{
xiaodou2++;
currtemp=y;
xiaodou1=0;
}
if(xiaodou2>12)
{
out=1;
flag=0;
xiaodou2=0;
}
out=flag;
}
void convert(char tmp)
{
uchar a;
if(tmp<0)
{
TempBuffer1[0]=0x0c;
a=~tmp+1;
}
else
{
TempBuffer1[0]=0;
a=tmp;
}
TempBuffer1[1]=(a%100)/10;
TempBuffer1[2]=(a%100)%10;
}
void keyscan( )
{
uchar keyin;
keyin=P1&0x07;
if(keyin==0x07)return;
else if(keymd==0)
{
dismod++;
dismod%=3;
while(keymd==0);
switch(dismod)
{
case 1:
convert(Tmax);
TempBuffer1[3]=0x11;
break;
case 2:
convert(Tmin);
TempBuffer1[3]=0x12;
break;
default:
break;
}
}
else if((keyup==0)&&(dismod==1))
{
Tmax++;
convert(Tmax);
while(keyup==0);
}
else if((keydn==0)&&(dismod==1))
{
Tmax--;
convert(Tmax);
while(keydn==0);
}
else if((keyup==0)&&(dismod==2))
{
Tmin++;
convert(Tmin);
while(keyup==0);
}
else if((keydn==0)&&(dismod==2))
{
Tmin--;
convert(Tmin);
while(keydn==0);
}
xiaodou1=0;
xiaodou2=0;
}
main()
{
TMOD=0x01;
TH0=(65536-5000)/256;
TL0=(65536-5000)%256;
TR0=1;
ET0=1;
EA=1;
out=1;
flag=0;
ReadTemperature(0x3f);
delay_18B20(50000); //延时等待18B20数据稳定
while(1)
{
pt=ReadTemperature(0x7f); //读取温度,温度值存放在一个两个字节的数组中
if(dismod==0)covert1();
keyscan();
delay_18B20(30000);
}
}
/ds18b20子程序/
/ds18b20延迟子函数(晶振12MHz )/
#include<reg51h>
sbit DQ=P1^2;
#define uchar unsigned char
void delay_18B20(unsigned int i)
{
while(i--);
}
/ds18b20初始化函数/
void Init_DS18B20(void)
{
unsigned char x=0;
DQ = 1; //DQ复位
delay_18B20(8); //稍做延时
DQ = 0; //单片机将DQ拉低
delay_18B20(80); //精确延时 大于 480us
DQ = 1; //拉高总线
delay_18B20(4);
x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
delay_18B20(20);
}
/ds18b20读一个字节/
unsigned char ReadOneChar(void)
{
uchar i=0;
uchar dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 给脉冲信号
dat>>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(4);
}
return(dat);
}
/ds18b20写一个字节/
void WriteOneChar(uchar dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
delay_18B20(5);
DQ = 1;
dat>>=1;
}
}
/读取ds18b20当前温度/
ReadTemp(void)
{ float val;
uchar temp_value,value;
unsigned char a=0;
unsigned char b=0;
unsigned char t=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的 *** 作
WriteOneChar(0x44); // 启动温度转换
delay_18B20(100); // this message is wery important
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的 *** 作
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
delay_18B20(100);
a=ReadOneChar(); //读取温度值低位
b=ReadOneChar(); //读取温度值高位
temp_value=b<<4;
temp_value+=(a&0xf0)>>4;
value=a&0x0f;
val=temp_value+value;
return(val);
}
以上是DS18B20的驱动程序。然后在主程序中直接调用函数就可以了。
以上是在主程序中的调用,你看关于温度的那个就可以。
#include "reg51h"
#include "18b20h"
#define uchar unsigned char
#define uint unsigned int
uchar code table[]="Welcome To" ;//初始化日期和星期
uchar code table1[]="Our System!";//初始化时间
uchar code table2[]="Temperature is:";//初始化时间
//以下三个是定义LCD的引脚
sbit lcden=P2^2;
sbit lcdwrite=P2^1;
sbit lcdrs=P2^0;
char wendu;
//延时程序
void delay(uint z)
{ uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
//lcd的写指令
void write_com(uchar com)
{
lcdrs=0;
lcden=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
//lcd的写数据
void write_data(uchar da)
{ lcdrs=1;
lcden=0;
P0=da;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
//初始化
void init()
{
uchar num;
lcdwrite=0;
lcden=0;
write_com(0x38); //162显示,57点阵,8位数据
write_com(0x0c);//显示开,关光标
write_com(0x06); //移动光标
write_com(0x01);//清除LCD的显示内容
write_com(0x80);
for (num=0;num<10;num++)
{
write_data(table[num]);
delay(5);
}
write_com(0x80+0x40);
for (num=0;num<11;num++)
{
write_data(table1[num]);
delay(5);
}
}
void write_wendu(uchar add, char da)
{
uchar shi,ge;
shi=da/10;
ge=da%10;
write_com(0x80+0x40+add);
write_data(0x30+shi);
write_data(0x30+ge);
}
//主函数
void main ()
{
uchar num;
init();
delay(2000);
delay(2000);
delay(2000);
write_com(0x01);//清除LCD的显示内容
while(1)
{
write_com(0x80);
for (num=0;num<15;num++)
{
write_data(table2[num]);
delay(5);
}
wendu = ReadTemp( );
write_wendu(2,wendu);
}
}
你的一位十进制数据+0x30,不就变成字符的数字了吗例如:TN是十进制温度 fasong[0]=TN/10 + 0x30; fasong[1]=TN%10 + 0x30;DS18B20采集到的数据你可以在单片机中处理成16进制或字符后发送到上位机,也可以直接发到上位机 由电脑处理数据后显示,当然VB上位机对字符的处理能力强些可以追问。
DS18B20是美国DALLAS半导体公司推出的一种数字化单总线器件,属于新一代适配微处理器的改进型智能温度传感器。我们先来看看DS18B20在芯片手册上的标题——“DS18B20 Programmable Resolution 1-Wire Digital Thermometer”。从这个标题上看我可以获取一些有价值的信息。首先分辨率是可以编程的,也就是我们可以通过程序来修改这个器件的分辨率。其次它又是“一线-总线”,那么简单的讲,就是我们与DS18B20的沟通就是通过这一根线实现的,换一个说法就是“写数据”,“发命令”,“读数据”等等都是通过这根线来完成的。第三点,从标题可以看到,它是数字温度计,也就是它能把温度信号转成数字信号。
其实这里的“第三点”非常重要——把温度信号转成数字信号。注意我们使用这个器件的目的就是要获取温度的信息,那么我们要做的事情就是获取这个DS18B20器件转换的“数字信号”。这是我们的根本目的。其实这个过程中有很多问题值得思考。比如说,这个器件既然能把温度信号转成数字信号,那么可以推测这个器件有个部分或者说它的核心材料具备感知温度的能力。
那么这个材料是什么?为什么这个材料具备这样的能力?最重要的一点是,DS18B20内部是如何把感知的温度信号转成数字信号的?可以看到,这几个问题才是DS18B20的核心内容(叁议电子)。但是想一想我们需要去解答这些问题吗?根本不需要。注意我们这里是从应用层面来思考问题的。我们要干什么?目的就是获取温度值嘛。
刚才不是说了吗,DS18B20能把温度信号转成数字信号。那么我们只需要关心这个“数字信号”放到哪里了,然后通过这一根“一线-总线”进行沟通,取出这个“数字信号”就可以了。至于我们刚才思考那些问题有用吗?根本没必要。当然如果你想深入了解这个器件也可以去查阅相关的资料。这里再次强调,我们是从应用层面来思考问题的。好了,通过对DS18B20芯片手册的标题分析,我们可以推测出一个大概的思路:DS18B20会把周围的温度信号变成数字信号,放在了某个(>
;这是关于DS18B20的读写程序,数据脚P22,晶振110592mhz
;温度传感器18B20汇编程序,采用器件默认的12位转化,最大转化时间750微秒
;可以将检测到的温度直接显示到AT89C51的两个数码管上
;显示温度00到99度,很准确无需校正!
ORG 0000H
;单片机内存分配申明!
TEMPER_L EQU 29H;用于保存读出温度的低8位
TEMPER_H EQU 28H;用于保存读出温度的高8位
FLAG1 EQU 38H;是否检测到DS18B20标志位
a_bit equ 20h ;数码管个位数存放内存位置
b_bit equ 21h ;数码管十位数存放内存位置
MAIN:
LCALL GET_TEMPER;调用读温度子程序
;进行温度显示,这里我们考虑用网站提供的两位数码管来显示温度
;显示范围00到99度,显示精度为1度
;因为12位转化时每一位的精度为00625度,我们不要求显示小数所以可以抛弃29H的低4位
;将28H中的低4位移入29H中的高4位,这样获得一个新字节,这个字节就是实际测量获得的温度
;这个转化温度的方法可是我想出来的哦~~非常简洁无需乘于00625系数
MOV A,29H
MOV C,40H;将28H中的最低位移入C
RRC A
MOV C,41H
RRC A
MOV C,42H
RRC A
MOV C,43H
RRC A
MOV 29H,A
LCALL DISPLAY;调用数码管显示子程序
CPL P10
AJMP MAIN
; 这是DS18B20复位初始化子程序
INIT_1820:
SETB P22
NOP
CLR P22
;主机发出延时537微秒的复位低脉冲
MOV R1,#3
TSR1:MOV R0,#107
DJNZ R0,$
DJNZ R1,TSR1
SETB P22;然后拉高数据线
NOP
NOP
NOP
MOV R0,#25H
TSR2:
JNB P22,TSR3;等待DS18B20回应
DJNZ R0,TSR2
LJMP TSR4 ; 延时
TSR3:
SETB FLAG1 ; 置标志位,表示DS1820存在
CLR P17;检查到DS18B20就点亮P17LED
LJMP TSR5
TSR4:
CLR FLAG1 ; 清标志位,表示DS1820不存在
CLR P11
LJMP TSR7
TSR5:
MOV R0,#117
TSR6:
DJNZ R0,TSR6 ; 时序要求延时一段时间
TSR7:
SETB P22
RET
; 读出转换后的温度值
GET_TEMPER:
SETB P22
LCALL INIT_1820;先复位DS18B20
JB FLAG1,TSS2
CLR P12
RET ; 判断DS1820是否存在若DS18B20不存在则返回
TSS2:
CLR P13;DS18B20已经被检测到!!!!!!!!!!!!!!!!!!
MOV A,#0CCH ; 跳过ROM匹配
LCALL WRITE_1820
MOV A,#44H ; 发出温度转换命令
LCALL WRITE_1820
;这里通过调用显示子程序实现延时一段时间,等待AD转换结束,12位的话750微秒
LCALL DISPLAY
LCALL INIT_1820;准备读温度前先复位
MOV A,#0CCH ; 跳过ROM匹配
LCALL WRITE_1820
MOV A,#0BEH ; 发出读温度命令
LCALL WRITE_1820
LCALL READ_18200; 将读出的温度数据保存到35H/36H
CLR P14
RET
;写DS18B20的子程序(有具体的时序要求)
WRITE_1820:
MOV R2,#8;一共8位数据
CLR C
WR1:
CLR P22
MOV R3,#5
DJNZ R3,$
RRC A
MOV P22,C
MOV R3,#21
DJNZ R3,$
SETB P22
NOP
DJNZ R2,WR1
SETB P22
RET
READ_18200: ; 读DS18B20的程序,从DS18B20中读出两个字节的温度数据
MOV R4,#2 ; 将温度高位和低位从DS18B20中读出
MOV R1,#29H ; 低位存入29H(TEMPER_L),高位存入28H(TEMPER_H)
RE00:
MOV R2,#8;数据一共有8位
RE01:
CLR C
SETB P22
NOP
NOP
CLR P22
NOPNOP
NOP
SETB P22
MOV R3,#8
RE10:
DJNZ R3,RE10
MOV C,P22
MOV R3,#21
RE20:
DJNZ R3,RE20
RRC A
DJNZ R2,RE01
MOV @R1,A
DEC R1
DJNZ R4,RE00
RET
;显示子程序
display: mov a,29H;将29H中的十六进制数转换成10进制
mov b,#10 ;10进制/10=10进制
div ab
mov b_bit,a ;十位在a
mov a_bit,b ;个位在b
mov dptr,#numtab ;指定查表启始地址
mov r0,#4
dpl1: mov r1,#250 ;显示1000次
dplop: mov a,a_bit ;取个位数
MOVC A,@A+DPTR ;查个位数的7段代码
mov p0,a ;送出个位的7段代码
clr p27 ;开个位显示
acall d1ms ;显示1ms
setb p27
mov a,b_bit ;取十位数
MOVC A,@A+DPTR ;查十位数的7段代码
mov p0,a ;送出十位的7段代码
clr p26 ;开十位显示
acall d1ms ;显示1ms
setb p26
djnz r1,dplop ;100次没完循环
djnz r0,dpl1 ;4个100次没完循环
ret
;1MS延时
D1MS: MOV R7,#80
DJNZ R7,$
RET
;实验板上的7段数码管0~9数字的共阴显示代码
numtab: DB 0CFH,03H,5DH,5BH,93H,0DAH,0DEH,43H,0DFH,0DBH
END
我这有个现成的C源程序,你参考一下吧!
三通道18B20温度测量数码管显示。-55-+125℃,用1位数码管显示当前通道号,4位数码管显示18B20当前通道温度值(一位小数),负号位与正温度百位1用同一位数码管显示,该位为0不显示,如:0 279、1 1231、2 -356。连接方法:三个18B20均接P37,P0口(JP10)接8位数码管段码口(J12)。
#include <reg52h>
#include <intrinsh>
typedef unsigned char uint8;
typedef unsigned int uint16;
sbit ADDR0 = P2^2;
sbit ADDR1 = P2^3;//定义38译码器地址
sbit ADDR2 = P2^4;
uint8 x,h;//定义通道
uint16 ans,ansb[3],f,g,p; //ans各通道温度值,f符号值,g为小数部分,p为1秒的计数变量
code uint8 number[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67,0x40,0x00,0x80};//0,1,2,3,4,5,6,7,8,9,-,灭,小数点
sbit DQ = P3^7; //温度DQ一线输入口
#define nops(); {_nop_(); _nop_(); _nop_(); _nop_();} //定义空指令
uint8 romid[3][8]={//romid二维数组存放每个芯片ROM编号
{0x28,0xA2,0xb4,0x0A,0x00,0x00,0x00,0x83},//0通道
{0x28,0xA2,0xb4,0x0A,0x03,0x00,0x00,0x83},//1通道
{0x28,0xA2,0xb4,0x0A,0x05,0x00,0x00,0x83},//2通道
};
// 定时器初始化
void T1_init(void)
{
TMOD = 0x10; //定时器1工作在方式1(显示扫描定时)
TH1 = 0xfc;
TL1 = 0x67;//T1定时1ms初值
TR1 = 1;//启动T1
}
void delay(uint16 n)
{
while (n--);
}
// 18B20复位函数
void DS18b20_reset(void)
{
bit flag=1;
while (flag)
{
while (flag)
{
DQ = 1;
delay(1);
DQ = 0;
delay(50); // 550us
DQ = 1; //给18B20发出复位信号
delay(6); // 66us
flag = DQ; //检测18B20发出的存在脉冲"0",判断复位是否成功
}
delay(45); //延时500us
flag = ~DQ; //18B20存在脉冲过后变"1",取反后仍为"0"
}
DQ=1;
}
//18B20写1个字节函数 向1-WIRE总线上写一个字节
void write_byte(uint8 val)
{
uint8 i;
for (i=0; i<8; i++)
{
DQ = 1;
_nop_();
DQ = 0;
nops(); //4us,110592晶振时每个时钟周期约1us
DQ = val & 0x01; //最低位移出
delay(6); //66us
val >>= 1; //右移一位
}
DQ = 1;
delay(1);
}
//18B20读1个字节函数 从1-WIRE总线上读取一个字节
uint8 read_byte(void)
{
uint8 i, value=0;
for (i=0; i<8; i++)
{
DQ=1;
_nop_();
value >>= 1;
DQ = 0;
nops(); //4us
DQ = 1;
nops(); //4us
if (DQ)
value|=0x80;
delay(6); //66us
}
DQ=1;
return(value);
}
// 启动温度转换
void start_temp_sensor(void)
{
DS18b20_reset();
write_byte(0xCC); // 发Skip ROM命令
write_byte(0x44); // 发转换命令
}
// 读出温度,多点多个18B20测温主程序:
void read_temp() //读取通道x的温度值
{
uint8 i,temp_data[2];//读出温度暂放
uint16 temp;
for(x=0;x<3;x++)
{
DS18b20_reset(); //复位
write_byte(0x55); // 发匹配ROM命令
for(i=0;i<8;i++)
write_byte(romid[x][i]);//写8位器件ID(从左到右),如:28 A2 b4 0A 03 00 00 83。
write_byte(0xBE);//读RAM命令,共9个字节,只取前两温度字节
temp_data[0]=read_byte(); //温度低8位
temp_data[1]=read_byte(); //温度高8位
temp=temp_data[1];//温度高字节
temp=temp<<8;//移到高8位中
temp+=temp_data[0];//温度低字节
ansb[x]=temp;
}
}
// 刷新5位数码管程序
void refresh()
{
static uint8 j = 0,a;//j为数码管位数,a为临时存放红外数据高或低4位
P0 = 0x00;//防止重影
switch(j)
{
case 0: ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;j++;//最右边一位数码管,一位小数
a=g625/1000;//只取小数点后一位,625把16进制换算成对应的10进制
P0 = number[a];break;
case 1: ADDR0 = 0;ADDR1 = 1;ADDR2 = 1;j++;
a = ans%10;//取个位
P0 = number[a];break;
case 2: ADDR0 = 1;ADDR1 = 0;ADDR2 = 1;j++;
a = ans/10%10;//取十位
P0 = number[a];break;
case 3: ADDR0 = 0;ADDR1 = 0;ADDR2 = 1;j++;
a = ans/100%10;//取百位
if (f!=0){a=10;}//若为负显示-号
else if (a!=1){a=11;}//若小于100度该位熄灭
P0 = number[a];break;//为1则正常显示
case 4: ADDR0 = 0;ADDR1 = 1;ADDR2 = 1;j++;
a = 12;//个位显示小数点
P0 = number[a];break;
case 5: ADDR0 = 0;ADDR1 = 1;ADDR2 = 0;j=0; //通道显示
P0 = number[h];break;//显示通道号
default: break;
}
}
main()
{
T1_init();//定时器初始化
while(1)
{
if(TF1==1)
{
TF1 = 0;
TH1 = 0xfc;
TL1 = 0x67;
start_temp_sensor();//启动温度转换
p++;
if(p==1000)// 延时约1秒
{
read_temp();//读各通道温度值
switch(h)
{//切换温度显示通道
case 0: ans=ansb[1];h++;break;//1通道
case 1: ans=ansb[2];h++;break;//2通道
case 2: ans=ansb[0];h=0;break;//0通道
default: break;
}
f=ans&0xF800;//取符号位
g = ans&0x000f;//取小数部分
ans>>=4;//去除小数部分
if (f!=0)
{
ans=~ans+1;
}
p=0;
}
refresh();
}
}
}
以上就是关于温度传感器DS18B20的读写一个字节的子程序全部的内容,包括:温度传感器DS18B20的读写一个字节的子程序、基于单片机msp430和温度传感器ds18b20的水温度控制系统的c语言源程序(不是测量,要有加热跟制冷)、使用温度传感器DS18B20设计一温控系统,当温度超过35度或低于20度时,LED红灯闪烁,蜂鸣器发出报警声。等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)