一、硬件电路
1.DS18B20内部电路
主要三大部分:64ROM、暂存器、EEPROM存储器
①:64位ROM:存放地址码,包括8位CRC校验码+48位序列号+8位序列码
②:暂存器
③:EEPROM(带电可擦可编程存储器):包括TH、TL寄存器和配置寄存器CR
TH、TL:规定最高温度和最低温度。CR:规定分辨率与最大转换时间
2.板子电路图
1、3脚供电,2接上拉电阻
二、命令
①:ROM命令:
由于蓝桥杯板子只有一个DS18B20,因此只需用0xCC跳过ROM操作
②:功能命令:
三、具体操作
1.复位:
①:先将总线拉低480us,产生复位脉冲,再释放总线。
②:DS18B20检测到请求之后,会将总线拉低60-240us,来表示应答,最后释放总线。
③:在第一次释放总线后的60-240us去读取总线的电平,如果是低电平,则初始化成功。
2.写操作:
①:写“0”:将总线拉低60-120us,再释放总线
②:写“1”:将总线拉低小于15us,再释放总线
③:一个写操作总时长要大于60us,每两个写操作之间间隔1us
3.读操作:
①:先将总线拉低然后释放,让DS18B20知道要开始读数据了,然后DS18B20就会开始传数据。
②:在15us内读走数据
③:一个读操作总时间大于60us,每两个读操作之间间隔1us
四、实验:
(1)注意事项:
1.熟悉DS18B20读取温度的流程:
①:初始化→跳过ROM(0xcc)→转换温度(0x44);
②:初始化→跳过ROM(0xcc)→读取暂存器(0xbe)→调用两次fRead_DS18B20(先读低位再读高位)
2.注意修改官方提供onewire.c中的延时程序,扩大延时12倍
3.学会数码管显示小数,“段码|0x80”;
4.学会DS18B20保留多位小数的写法
5.无需在单片机发送完“转换温度”指令后加上Delay延时,会阻塞程序,如果不加延时,读取的是上一次温度转换的结果。
(2)代码编写:
1.onewire模块:
#include "reg52.h"
sbit DQ = P1^4;
单总线延时函数
void Delay_OneWire(unsigned int t)
{
t = t*12;
while(t--);
}
//写一个字节
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;
}
//DS18B20初始化
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;
}
//DS18B20温度采集程序
float fRead_temperature(void)
{
unsigned char low,high;
float temp;
init_ds18b20();
Write_DS18B20(0xCC); //跳过ROM
Write_DS18B20(0x44); //开始温度转换
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0xBE); //读取寄存器
low = Read_DS18B20(); //低8位
high = Read_DS18B20(); //高8位
temp = (high<<8|low)*0.0625;
return temp;
}
2.main函数:
#include <STC15F2K60S2.H>
#include <INTRINS.h>
#include "system.h"
#include "Device.h"
#include "Timer2.h"
#include "SMG.h"
#include "onewire.h"
HexToBin led_ctrl;
//系统初始化函数
void vSystem_Init(void)
{
vDevice_Ctrl(0xa0,0);
led_ctrl.hex=0xff;
vDevice_Ctrl(0x80,led_ctrl.hex);
}
//读取温度程序
u8 temperature; //显示整数
u32 temp_float; //显示小数
u8 cnt_temp;
void vDS18B20_Read()
{
if(cnt_temp>=100)
{
cnt_temp=0;
//temperature=(u8)fRead_temperature();
temp_float=(u32)(fRead_temperature()*10000); //最高四位小数 0.0625
}
}
//数码管操作函数
u8 smg_buf[8];
void vSMG_Process()
{
smg_buf[0]=smg_code[temperature/10];
smg_buf[1]=smg_code[temperature%10];
smg_buf[2]=smg_code[temp_float/100000];
smg_buf[3]=smg_code[temp_float/10000%10]|0x80;
smg_buf[4]=smg_code[temp_float/1000%10];
smg_buf[5]=smg_code[temp_float/100%10];
smg_buf[6]=smg_code[temp_float/10%10];
smg_buf[7]=smg_code[temp_float%10];
}
void main()
{
vSystem_Init();
Timer2Init();
while(1)
{
vSMG_Process();
vDS18B20_Read();
}
}
void Timer2_Routine(void) interrupt 12
{
cnt_temp++;
vSmg_Display();
}
(3)现象: