/*<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
温度传感器DS18B20的控制程序
从一blog里找的程序,感觉好用
这里给大家发出来,有少许改动
大家改改也可以自己用,硬件电
路很简单,只要把B20的DQ端接
P1.4就可以了。但是要注间,个
人在调试中发现B20对时序要求
相当严格,所用调用读温度程序
时,关了中断,不然得到的结果
与实际相差万分。本程序用来做
与计时有关的程序不太好用。但
也能让大家更好的了解B20,故在
此帖出来。
注意:B20一定要外接电源,否则
下面的程序不可用。至于单片机,
可任意选用,51都行。P0口有上拉。
用作LED段选,P00~P07->a~dp.
P2口接LED位选。P20~P27接1~8
位LED,1在右,7在左。
*/
#define uchar unsigned char
#define uint unsigned int
#include<reg51.h>
#include <intrins.h> // _nop_()function
#define NOP _nop_();_nop_();_nop_()
uchar code ledcode[]={0x<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00,0x40,0x80
};
uchar code ledbitselect[8]={1,2,4,8,0x10,0x20,0x40,0x80};
uchar dispbuf[8]={16,16,16,16,16,16,16,12};
uchar cnt_t;
uint count_int;
sbit PORT_BIT_1820=P1^4;
/**********************************/
void wr_1820(uchar val);
float get_tmpr(void);
void init_1820(void);
void wr_1820(uchar val);
float rd_1820(void);
void delay1(uchar t);
void start(void);
//********************************************
void delay1(uchar t)
{
uchar i;
for (i=0;i<t;i++)
{
_nop_();
}
}
//********************************************
void start(void)
{
init_1820();
wr_1820(0xcc); //跳过读ROM
wr_1820(0x44);
}
float get_tmpr(void)
{
float tmpr;
uchar cnt,i;
cnt=0;
ag: EA="0"; //慎用
init_1820();
wr_1820(0xcc); //跳过读序列号的操作
wr_1820(0x44); //启动温度转换
delay1(125);
init_1820();
wr_1820(0xcc); //跳过读序列号的操作
wr_1820(0xbe); //读温度寄存器
tmpr=rd_1820(); //读温度
init_1820();
wr_1820(0xcc);
wr_1820(0x44); /* start convert */
EA=1; //慎用
if (tmpr<-10.0) tmpr="25".0;
return tmpr;
}
void init_1820(void)
{
uchar i;
PORT_BIT_1820=1; //1.6us
PORT_BIT_1820=0; /* 1--8+7us */
for(i=0;i<100;i++);/* delay 400--960us */ //300us
PORT_BIT_1820=1;
for(i=0;i<200;i++) /* delay 15--60us */
{ if (PORT_BIT_1820==0) break;}
for(i=0;i<=200;i++)
{ if (PORT_BIT_1820==1) break;
}
for(i=0;i<60;i++); /* delay 480us */
}
void wr_1820(uchar val)
{
uchar i,j;
PORT_BIT_1820=1; //1.6us
NOP; //3.6us
for (j=0;j<8;j++)
{ PORT_BIT_1820=0;
NOP;
NOP; /* delay 6us */
if ((val&0x01)==1)
PORT_BIT_1820=1;
else
PORT_BIT_1820=0;
for(i=0;i<6;i++); /* delay 5-6 us */ //20.6us
PORT_BIT_1820=1;
val=val>>1;
}
}
float rd_1820(void)
{ uchar j,i,k,tt[9],vv;
float tmpr;
vv=0;
for(k=0;k<9;k++)
{ for(j=0;j<8;j++)
{
PORT_BIT_1820=0;
NOP;NOP;NOP;NOP; //delay 12 us
PORT_BIT_1820=1;
vv=vv>>1;
if(PORT_BIT_1820) vv="vv|0x80";
for(i=0;i<6;i++);/*delay 120 us */
PORT_BIT_1820=1;
}
tt[k]=vv;
}
i=tt[1]&0xf8;
if( (i!=0)&&(i!=0xf8)) return -100.0;
tmpr=tt[1]*256.0;
tmpr=(tmpr+tt[0])/16.0;
if(tmpr>100.0 ) return -100.0;
return tmpr;
}
/**********************************/
//************************************
main()
{
float tt;
uchar i;
TMOD=0X02;
TL0=0X06;
TH0=0X06;
IE=0x82;
TR0=1; //设好了定时器,方便调试,但使用时要小心。
EA=0;
init_1820();
wr_1820(0x33);
start();
count_int=0;
cnt_t=0;
while(1)
{
tt=get_tmpr();
_nop_();
dispbuf[7]=(uchar)tt/10;
dispbuf[6]=(uchar)tt%10;
dispbuf[5]=(uchar)tt*10%10;
dispbuf[4]=(uchar)tt*100%10;
//
for(i=0;i<8;i++)
{
P2=ledbitselect;
P0=ledcode[dispbuf];
if(i==6)P0=ledcode[dispbuf]|0x80;
delay1(100);
}
//
}
}
void time0() interrupt 1
{
count_int++;
if(count_int=200)
{
count_int=0;
cnt_t++;
if(cnt_t==8)cnt_t=0;
P2=ledbitselect[cnt_t];
P0=ledcode[dispbuf[cnt_t]];
if(cnt_t==6)P0=ledcode[dispbuf[cnt_t]]|0x80;
}
}
/*
这个程序中用的分辨率是12位,程序我本人都没有完全消化,还不会改分辨率,如果有会的朋友,希望能给我留言或者emailto:lbj_01@163.com。
这里的中断用来扫描显示。但闪烁,反不如用主函数中的显示程序。
中断对B20读数有很大的影响,希望大家在使用中注意。
*/
文章评论(0条评论)
登录后参与讨论