一.DS18B20
1.DS18B20介绍
DS18B20是一种数字温度传感器,应用非常广泛。它输出的是数字信号,同时具有体积小,硬件资源耗费少,抗干扰能力强,精度高等特点。
特点:
- 采用单线接口方式:DS18B20温度传感器仅需要一条线即可实现与微处理器的双向通信。
- 测温范围: DS18B20温度传感器的测温范围可达-55℃~+125℃,在-10℃到+85℃范围内误差为±0.4°。
- DS18B20温度传感器在应用过程中不需要任何外围元件。
- DS18B20温度传感器测量温度的结果以9~12位数字量方式串行传送。(默认12位)
2.CT107D中DS18B20引脚介绍
由原理图可知P1^4连接DQ,在onewire.c中补充即可
3.DS18B20使用
参考技术手册我们可以直接了解大致的使用流程
简单来说就是:
- 初始化
- ROM指令(一般直接跳过)
- 功能指令
常用ROM指令和功能指令:
跳过ROM指令:0xcc
启动温度转化:0x44
读取温度:0xbe
DS18B20分辨率:
读取时DS18B20会返回两个8位数据(先低8位LSB后高8位MSB),使用的时候需要转化为十进制的数据.
参考数据手册我们可知默认选择的是12位分辨率,所以仅需将得到的16位数据/16即可(正数情况下)
DS18B20示例代码:
//float temp;
//unsigned char T_smg;
void Read_ds18b20_temp()
{
unsigned int temp=0;
unsigned char LSB,MSB;
init_ds18b20();//初始化
Write_DS18B20(0xcc);//跳过ROM指令
Write_DS18B20(0x44);//发送温度转化指令
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);//发送读取温度指令
LSB=Read_DS18B20();//读取低位
MSB=Read_DS18B20();//读取高位
temp=(MSB<<8)|LSB;//还原数据
T=temp/16.0;//计算温度
T_smg=T;
}
这段代码在使用的过程中由点小问题,就是数码管会一闪一闪的,原因是其中有些指令比较耗时,导致数码管刷新速率减慢
代码改进:
void Read_ds18b20_temp()
{
unsigned int temp=0;
unsigned char LSB,MSB;
init_ds18b20();
Display_dynamic();//适当的加入一下数码管显示提高刷新率
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Display_dynamic();
init_ds18b20();
Display_dynamic();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB=Read_DS18B20();
MSB=Read_DS18B20();
Display_dynamic();
temp=(MSB<<8)|LSB;
T=temp/16.0;
T_smg=T;
}
二.练习:
main.c
#include <REGX52.H>
#include "onewire.h"
unsigned char code SMG_NoDot[18]={0xc0,0xf9,
0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
float T;
unsigned char T_smg;
void DelaySMG(unsigned int t)
{
while(t--);
}
void Select_HC573(unsigned char channel,unsigned char dat) //573 ????
{
switch(channel)
{
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;
case 0:
P2=(P2&0x1f)|0x00;
break;
}
P0=dat;
P2=(P2&0x1f)|0x00;
}
void SMG_Displaybit(unsigned char pos,unsigned char dat)//???????
{
Select_HC573(6,0x01<<(pos-1));
Select_HC573(7,dat);
DelaySMG(500);
Select_HC573(6,0x01<<(pos-1));
Select_HC573(7,0xff);
}
void Display_dynamic() //???????
{
SMG_Displaybit(7,SMG_NoDot[T_smg/10]);
SMG_Displaybit(8,SMG_NoDot[T_smg%10]);
}
void Read_ds18b20_temp()
{
unsigned int temp=0;
unsigned char LSB,MSB;
init_ds18b20();
Display_dynamic();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Display_dynamic();
init_ds18b20();
Display_dynamic();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB=Read_DS18B20();
MSB=Read_DS18B20();
Display_dynamic();
temp=(MSB<<8)|LSB;
T=temp/16.0;
T_smg=T;
}
void Sys_Init()
{
Select_HC573(4,0xff);
Select_HC573(5,0x00);
}
void main()
{
Sys_Init();
while(1)
{
Read_ds18b20_temp();
Display_dynamic();
}
}
onewire.c
/* # 单总线代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <REGX52.H>
sbit DQ=P1^4;
//
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
//
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//
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(5);
}
return dat;
}
//
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;
}
onewire.h
#ifndef __ONEWIRE__H
#define __ONEWIRE__H
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
#endif
附:开始的时候出现85在不加处理的情况下是正常状态,手册里有这么一句话