DS18B02芯片可以说是在蓝桥杯中是极为常考的一个芯片模块了,熟练掌握是必须的。
简单说明一下吧:温度读取时候呢?首先读出的是温度的低八位,其次读出的是温度的高八位,组成一个16位的二进制值就是DS18B20测量到的温度值。16位中的高5位代表着温度值的正负,一般环境下就没有必要考虑了,因为我们身边的环境温度都是高于零度的啦。最低的4位呢是小数位,需要显示小数位的时候就需要进行处理,没有这方面的要求时候可以直接忽略了。
(省赛时候会提供DS18B20 的底层驱动代码直接调用就可以了,但是小心可能会存在一点小问题,就像某一年的温度转换延时时间太小了,需要调整;还有就是可能源文件里面的函数可能没有在头文件中定义,需要定义之后才可以正常运行)
某一年的底层驱动代码延时函数如下,因为提供的驱动代码测试环境:12T, 8051, 12MHz;但是我们蓝桥杯考试的板子的环境是1T的,在速度上是51完全比不上的,所以相同的延时函数,需要把延时时间加长才行。
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
while(t--);
}
修改为
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
t = t * 12; // 放大十二倍延时时间
while(t--);
}
温度检测代码如下:
#include "reg52.h"
#include "intrins.h"
#include "onewire.h" // 调用官方提供的单总线底层驱动代码
typedef unsigned char u8;
typedef unsigned int u16;
u8 code shuma[12] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xbf};
u16 tempera;
void display_temp(); // 温度值显示函数
// 外设初始化函数
void init_system()
{
P2 = (P2 & 0x1f) | 0x80;
P0 = 0xff;
P2 = (P2 & 0x1f);
P2 = (P2 & 0x1f) | 0xa0;
P0 = 0x00;
P2 = (P2 & 0x1f);
P2 = (P2 & 0x1f) | 0xc0;
P0 = 0x00;
P2 = (P2 & 0x1f);
}
// 外设选通函数
void select(u8 local)
{
switch(local)
{
case(4): P2 = (P2 & 0x1f) | 0x80; break;
case(5): P2 = (P2 & 0x1f) | 0xa0; break;
case(6): P2 = (P2 & 0x1f) | 0xc0; break;
case(7): P2 = (P2 & 0x1f) | 0xe0; break;
}
}
// 延时函数
void delay()
{
u8 t = 200;
while(t--);
}
// 数码管显示函数,单个数码管点亮
void display(u8 local, u8 num)
{
select(6);
P0 = 0x80 >> (local - 1);
P2 = P2 & 0x1f;
select(7);
P0 = num;
P2 = P2 & 0x1f;
// 数码管延时
delay();
}
void close_display()
{
// 消隐
select(6);
P0 = 0x00;
P2 = P2 & 0x1f;
}
// 温度检测函数
void temperature()
{
u8 HT,LT;
u16 temp;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(250);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LT = Read_DS18B20(); // 先读取低位数据,后读取高位数据
HT = Read_DS18B20();
init_ds18b20();
// 一:可以直接使用读取到的十六位值进行乘上倍数;二、如果不需要小数位,可以直接把低八位的后四位移出去,之后把高八位向左移四位,之后把高八位低八位进行或运算,得出一个整数,不需要再乘以倍数;
// temp = HT&0X0F;
temp = HT << 8;
temp |= LT;
// temp = temp >> 4;
// temp = temp * 10;
// tempera = temp;
// temp = LT & 0x0f;
// tempera = tempera + (u8)(temp * 0.625);
tempera = (u16)(temp * 0.625); // 把测量到温度放大十倍显示一位小数位,如果想要多位小数,自行继续放大即可
}
void display_temp()
{
display(1,shuma[tempera%100]);
display(2,shuma[tempera/10%10] & 0x7f); // 小数点的处理,与上一个0x7f便可以把第二位的小数点显示出来了
display(3,shuma[tempera/100]);
}
void Delay1ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
void main()
{
init_system(); // 初始化外设
while(1)
{
temperature();
display_temp();
close_display();
Delay1ms(); // 延时1ms再去读取温度值,没有必要一直读取,浪费资源
}
}