单片机控制DS18B20自制简易电子温度计(测试通过)(二)

本文介绍了一种使用DS18B20温度传感器测量温度,并通过LED数码管动态显示温度值的方法。包括温度传感器的初始化、读写操作及LED显示控制等内容。

二、软件部分

#include <reg51.h>
#include <intrins.h>
// 此表为 LED 的字模(共阴极)      0 1     2     3     4     5     6     7    8     9  灭   a     b     c    d     e      f
unsigned char code LED7Code[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x77,0x7C,0x39,0x5E,0x79,0x71};
unsigned char flag,xiao=0;
unsigned char wendu[2];
sbit DQ=P3^7;

/******************************************************

DS18B20初始化        温度计函数

***********************************************************/
unsigned char INI() //温度计复位
{unsigned char flag,time;      
DQ = 1;           //先将数据线拉高
for(time=0;time<2;time++); //延时6+2微秒   
DQ = 0;           //再将数据线从高拉低,要求保持480~960us
for(time=0;time<240;time++);  //延时720+2微秒                                              
DQ = 1;           //释放数据线
for(time=0;time<12;time++);  //延时36+2us
flag=DQ;          //让单片机检测是否输出了存在脉冲(DQ=0表示存在)      
for(time=0;time<200;time++) ; //延时足够长时间,必须大于480-(36+2) us  
return (flag);    //返回检测成功标志
}

/******************************************************

DS18B20写一个字节        温度计函数

***********************************************************/

void DS_WRITE_BYTE(unsigned char command)//写入一个字节
{unsigned char time;
 unsigned char i=0;
        for (i=0; i<8; i++)
                 {
                          DQ =1;         // 设置初始状态
                          _nop_();             //等待一个机器周期         
                          DQ=0;          //将数据线从高拉低时即启动写时序
 _nop_();//拉低DQ至少1us       
                          DQ=command&0x01;   //先送低位        
                         for(time=0;time<10;time++)        ;//延时约30us,DS18B20在拉低后的约15~60us期间从数据线上采样
                          DQ=1;          //释放数据线                    
                          for(time=0;time<10;time++);//延时30+2us,写一位至少60us
                          command=command>>1;       //将command中的各二进制位数据右移1位
                 }
         for(time=0;time<4;time++); //稍作延时
}

****************************************************************************************************************

详情请咨询:                                                 http://shop108408772.taobao.com/

**************************************************************************************************************

/******************************************************

DS18B20读一个字节        温度计函数

***********************************************************/

unsigned char DS_READ_BYTE()//读入一个字节
{unsigned char i,temp=0,time;
for(i=0;i<=7;i++)
{ DQ =1;       // 设置初始状态
   _nop_();            
    temp=temp>>1; 
    DQ=0;   //拉低DQ至少1us
_nop_();
_nop_();
DQ=1;   //释放总线
for(time=0;time<2;time++) ;//延时6+2us
if(DQ==1)temp=temp|0x80;   //从拉低DQ开始,在15us之内完成数据采样
for(time=0;time<17;time++); //延时51+2us,每读1位至少用60us
}
return temp;
}

/******************************************************

使用中断定时读取数据        温度计函数

***********************************************************/

void timer0() interrupt 1   //使用中断定时读取温度数据
{TL0=0;
TH0=0;
flag=flag+1;
if(flag==16)
{unsigned char time; //中断服务程序
INI();
DS_WRITE_BYTE(0xCC); //跳过读ROM指令
DS_WRITE_BYTE(0x44); //转换温度
for(time=0;time<100;time++);  //等待转换完毕
INI();
DS_WRITE_BYTE(0xCC); //跳过读ROM指令
DS_WRITE_BYTE(0xBE); //转换温度
wendu[0]=DS_READ_BYTE();   //低字节
wendu[1]=DS_READ_BYTE(); //高字节
INI();//终止接收数据
flag=0;
}
}

****************************************************************************************************************

详情请咨询:                                                 http://shop108408772.taobao.com/

**************************************************************************************************************

/******************************************************

LED动态显示      显示函数

***********************************************************/

void display(unsigned char number,unsigned char shuzi) //动态显示
{unsigned char temp,i;
temp=number<<2;
P2=temp&0x1c;
if(number==1)P1=(LED7Code[shuzi])|0x80;
else
P1=(LED7Code[shuzi])&0x7f;
for(i=0;i<=100;i++);
}

/******************************************************

        主函数

***********************************************************/

void main() //使用动态显示将温度显示在LED上
{ unsigned char i;
unsigned char shijian[8]={8,8,0,10,10,10,10,10};
unsigned char temperature;
TMOD=1;                                      //定时器0模式为1,使用的是16位计数器
EA=1;                                       //总中断开启
ET0=1;                            //定时器中断打开
TR0=1;                          //定时器开始计数
do{
temperature=(wendu[0]>>4)|((wendu[1]<<4)&0x7f); //将温度整数部分组装好
if(wendu[0]&0x08)xiao=1;                                           //精确到0.5摄氏度
else xiao=0;
shijian[0]=temperature/10;                                        //获取十位

shijian[1]=temperature%10;                                        //获取个位
if(xiao==1)shijian[2]=5;                                              //小数部分
else shijian[2]=0; 
//shijian[0]=wendu[0]/100; //测试使用
//shijian[1]=(wendu[0]%100)/10;
//shijian[2]=(wendu[0]%100)%10;
//P0=~wendu[1];
for(i=0;i<=7;i++)                                  //将读到的数据送到LED显示
{display(i,shijian[i]);
}
}while(1);
}

****************************************************************************************************************

详情请咨询:                                                 http://shop108408772.taobao.com/

**************************************************************************************************************

三、调试中遇到的问题

1>延时函数使用如下方式:

unsigned char i;

for(i=0;i<n;i++);                //本句实现延时 3*n+2 us,我通过断点调试验证(晶振为12MHZ)

2>查看具体延时时间工具的使用

通过在keil中设置好晶振,在要测试处设置断点,在下一行设置断点,开启调试,使用快捷键F5进行查看时间。使用后断点处运行时间减去该断点处时间即为实际该句运行时间。

3>注意找写1与写0时序的共同部分时序,按此缩减程序

四、测试结果


****************************************************************************************************************

详情请咨询:                                                 http://shop108408772.taobao.com/

**************************************************************************************************************

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值