疫情过境,好好学习!
一、结构图
DS18B20结构非常简单,在蓝桥杯单片机板子上也并不起眼,但是它的作用可不小噢,可以测温度、精度也不算低的器件。
(当我第一次拿DS18B20测得我手的温度,我觉得我还是挺暖的人哈哈哈哈)
结构上就是一个接地线,一个电源线,接了一个上拉电阻,还有一个信号线。
可想而知,之后对于这个器件的控制基本上就是对P1^4口的操作。
二、芯片手册解读
根据我们比赛时可以拿到的DS18B20的英文芯片手册,首先:
看一下DS18B20如何使用,
【如果不习惯英文芯片手册,两个办法:①熟练的记住这个器件的用法,②多读多看芯片手册】
可以看到DS18B20的使用方法分为三个步骤:
Step1:初始化
Step2:操作寄存器指令
Step3:功能操作指令
那么在对DS18B20的每次操作都要对应这样的三个步骤!
下面结合底层驱动谈谈如何理解初始化、写、读函数
一般在比赛中,DS18B20的底层程序会直接给出【onewire的c、h文件】,但是为了我自己理解,我就结合芯片手册重新写了一遍底层函数。
底层都会有的单总线延时函数
void Delay_OneWire(uint t)
{
uchar num;
while(t--)
{
for(num=0;num<12;num++);
}
}
这是STC15的写法,如果是52,则不用这个12次的循环
- 初始化
上图为初始化时序图,可看出:
从总线先为高电平,再最少先拉低总线480us,然后拉高总线
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1; //总线先是高电平
Delay_OneWire(12);
DQ = 0; //拉低总线
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag; //是否初始化成功的标志
}
- 写
上图为写时序图:
先将总线拉低60us——120us,然后拉高总线,再一位一位的写入,将总线拉低时写入,然后再拉高总线
void Write_DS18B20(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
DQ = 0; //先拉低总线
DQ = dat & 0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
- 读
由时序图可看出:
先拉低总线,延时一会再拉高总线,等待数据
uchar Read_DS18B20(void)
{
uchar i;
uchar dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
三、温度读取函数
读取温度就是通过DS18B20来进行,那么就按照芯片手册上的三个步骤。
整数温度
uchar Temperature_Get()
{
uchar high,low;
uchar temprature;
if(init_ds18b20())
{
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(50);
}
if(init_ds18b20())
{
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
high = Read_DS18B20();
low = Read_DS18B20();
temprature = high<<4;
temprature |= (low >>4);
}
return temprature;
}
根据芯片手册可知,
这是这个温度传感器的精度和范围。
解决一下语句的问题:
①为什么写0xcc?
根据芯片手册中,
一般的单总线上可能串接有很多DS18B20,但是在蓝桥杯板子上只有一个,那么就可以省略区分DS18B20的过程,写0xcc也就是这个意思。
②为什么写0x44?
0x44在这里是将温度这个模拟量转换为数字量,延时是为了给它转换的时间。
③为什么写0xbe?
这个是用于从转换好的存在暂存器里的温度读出来
【如果之后还有多余的时间,我会更新非整数温度的读取函数,今天到这啦!】