二、软件部分
#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/
**************************************************************************************************************