DS18B20是常用的数字温度传感器,其输出的是数字信号,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。面对着平的那一面,左负右正,一旦接反就会立刻发热,有可能烧毁!同时,接反也是导致该传感器总是显示85℃的原因。实际操作中将正负反接,传感器立即发热,液晶屏不能显示读数,正负接好后显示85℃。另外,如果使用51单片机的话,那么中间那个引脚必须接上4.7K-10K的上拉电阻,否则,由于高电平不能正常输入/输出,要么通电后立即显示85℃,要么用几个月后温度在85℃与正常值上乱跳。
设计内容:
1.检测室内温度,显示在数码管上,格式如下图所示:
2.设置温度阈值为25℃,超过温度阈值L1点亮,否则L1熄灭。
对于单总线的操作,相对于IIC,DS1302来说要简单的多,考试的时候官方是会提供这三个驱动给我们的,不太清楚的同学可以参考蓝桥杯大赛——驱动程序,官方给我们提供了这部分程序,对我们的代码编写工作量来说确实减少了很多,但这个驱动并不是可以直接拿来用的,我们还需要再写一部分程序才能真正利用到这部分代码,下面咱们就用官方提供的驱动来编程吧。
#include
#define uchar unsigned char //定义无符号字符类型uchar
#define uint unsigned int //定义无符号整型类型uint
sbit DQ = P1^4; //单总线接口
uchar code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff,0xc6};//数字0~9,“-”,“关”,“C”
uchar yi,er,san,si,wu,liu,qi,ba; //定义字符型变量yi,er,san,si,wu,liu,qi,ba,当作数码管显示控制变量
uchar wendu;
void delayms(int ms); //延时函数
void allinit(); //初始化函数
void display1(uchar yi,uchar er); //第一、二段数码管函数
void display2(uchar san,uchar si); //第三、四段数码管函数
void display3(uchar wu,uchar liu); //第五、六段数码管函数
void display4(uchar qi,uchar ba); //第七、八段数码管函数
//单总线延时函数
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
unsigned char Tempget();
void main()//主函数
{
allinit(); //初始化函数
yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=11;ba=11;//让数码管全部熄灭
while(1)
{
wendu=Tempget(); //获取温度
liu=wendu/10;qi=wendu%10;ba=12; //把获取到的温度和标识符C显示在第六、七、八位数码管上
if(wendu>25){P2=0X80;P0=0XFE;} //温度大于25℃,L1点亮
else {P2=0X80;P0=0XFF;} //否则L1熄灭
display1(yi,er); //第一、二段数码管函数
display2(san,si); //第三、四段数码管函数
display3(wu,liu); //第五、六段数码管函数
display4(qi,ba); //第七、八段数码管函数
}
}
void delayms(int ms)//延时函数
{
uint i,j;
for(i=ms;i>0;i--)
for(j=845;j>0;j--);
}
void allinit()//初始化函数
{
P2=0XA0;P0=0X00; //关闭蜂鸣器继电器
P2=0X80;P0=0XFF; //关闭所有LED灯
P2=0XC0;P0=0XFF; //选中所有数码管段选
P2=0XFF;P0=0XFF; //关闭所有数码管
}
void display1(uchar yi,uchar er)//第一、二段数码管函数
{
P2=0XC0;P0=0X01; //选中第一个数码管段选
P2=0XFF;P0=tab[yi]; //让第一个数码管显示yi指向的值
delayms(1); //延时1ms
P2=0XC0;P0=0X02; //选中第二个数码管段选
P2=0XFF;P0=tab[er]; //让第一个数码管显示er指向的值
delayms(1); //延时1ms
}
void display2(uchar san,uchar si)//第三、四段数码管函数
{
P2=0XC0;P0=0X04; //选中第s三个数码管段选
P2=0XFF;P0=tab[san]; //让第一个数码管显示san指向的值
delayms(1); //延时1ms
P2=0XC0;P0=0X08; //选中第四个数码管段选
P2=0XFF;P0=tab[si]; //让第一个数码管显示si指向的值
delayms(1); //延时1ms
}
void display3(uchar wu,uchar liu)//第五、六段数码管函数
{
P2=0XC0;P0=0X10; //选中第五个数码管段选
P2=0XFF;P0=tab[wu]; //让第一个数码管显示wu指向的值
delayms(1); //延时1ms
P2=0XC0;P0=0X20; //选中第六个数码管段选
P2=0XFF;P0=tab[liu]; //让第一个数码管显示liu指向的值
delayms(1); //延时1ms
}
void display4(uchar qi,uchar ba)//第七、八段数码管函数
{
P2=0XC0;P0=0X40; //选中第七个数码管段选
P2=0XFF;P0=tab[qi]; //让第一个数码管显示qi指向的值
delayms(1); //延时1ms
P2=0XC0;P0=0X80; //选中第八个数码管段选
P2=0XFF;P0=tab[ba]; //让第一个数码管显示ba指向的值
delayms(1); //延时1ms
P2=0XC0;P0=0X80; //选中第八个数码管段选
P2=0XFF;P0=0XFF; //让第八个数码管熄灭
}
/*********************** DS18B20驱动程序 ************************/
//单总线延时函数
void Delay_OneWire(unsigned int t)
{
while(t--);
}
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(50);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(50);
}
return dat;
}
//DS18B20设备初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(120);
DQ = 0;
Delay_OneWire(800);
DQ = 1;
Delay_OneWire(100);
initflag = DQ;
Delay_OneWire(50);
return initflag;
}
//DS18B20温度获取
unsigned char Tempget() //温度的读取,可参照DS18B20芯片手册
{
unsigned char temp,low,high; //定义无符号字符型变量temp,low,high;
init_ds18b20(); //DS18B20设备初始化
Write_DS18B20(0xcc); //通过单总线向DS18B20写0xcc:这条命令允许总线控制器不用提供64位ROM编码就使用存储器操作命令,在单总线情况下右以节省时间。
Write_DS18B20(0x44); //这条命令启动一次温度转换而无需其他数据。
Delay_OneWire(200); //延时
init_ds18b20(); //DS18B20设备初始化
Write_DS18B20(0xcc); //通过单总线向DS18B20写0xcc:这条命令允许总线控制器不用提供64位ROM编码就使用存储器操作命令,在单总线情况下右以节省时间。
Write_DS18B20(0xbe); //这个命令读取暂存器的内容。
low=Read_DS18B20(); // 因为温度传感器是16位所以依次读取低八位和高八位
high=Read_DS18B20(); // 因为温度传感器是16位所以依次读取低八位和高八位
temp=high<<4; //高四位是符号位不要
temp|=(low>>4); //低四位是小数位不要,让去除符号的高四位或上去除小数的低四位,即温度的值
return temp; //返回temp
}