写在前面
本次学习将分为两个部分解释说明如何使用DS18B20以及编写Onewire.c的文件,第一部分是解释编写Onewire.c的原理,第二部分会针对如何在蓝桥杯比赛时快速建立底层作说明。
设计思路
一、单总线初始化
Delay_onewire
void Delay_onewire(unsigned int t)//延时函数1~2us
{
unsigned char i;
while(t--)
{
for(i=0;i=12;i++);
}
}
Init_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;
}
二、单总线读写数据
Read_DS18B20
unsigned char Read_DS13B20(void)//读
{
unsigned char i;
unsigned char dat;
for (i=0;i<8;i++)
{
DQ = 0;
dat>>=1;
DQ = 1;
if(DQ)
{
dat|=0x80;
}
}
return dat;
}
Write_DS18B20
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);
}
三、DS18B20温度读取
查阅DS18B20的手册(详见附件)
跳过 ROM [CCh]指令允许主设备在不发送任何 ROM 代码信息的情况下同时寻址总线上的所有设备。例如,主设备可以通过发出跳过 ROM 指令后跟一个转换温度 [44h] 指令来使总线上的所有 DS18B20 同时执行温度转换。
需要注意的是,仅当总线上只有一个从设备时,才能在跳过 ROM 指令后跟随读取 Scratchpad [BEh] 指令。在这种情况下,通过允许主设备从从设备读取数据而不发送设备的 64 位 ROM 代码,节省了时间。但是,如果总线上有多个从设备,则跳过 ROM 指令后跟一个读取 Scratchpad 指令将导致总线上的数据冲突,因为多个设备将尝试同时传输数据。
转换温度 [44h] 指令启动单次温度转换。在转换完成后,生成的热数据存储在scratchpad存储器中的2字节温度寄存器中,然后DS18B20返回到其低功耗空闲状态。如果设备正在使用寄生功率模式,在发出此命令后的10µs(最大)内,主设备必须在转换期间(tCONV)在1-Wire总线上启用强拉电阻,如“为DS18B20供电”部分所述。如果DS18B20由外部供电,则主设备可以在转换T命令后发出读取时间槽,并且DS18B20将在温度转换进行中发送一个0,转换完成时发送一个1作为响应。在寄生功率模式下,由于总线被高拉电阻拉高,因此无法使用此通知技术。
读取内容[BEh]。数据传输从第一个字节的最低有效位开始,一直延续到第九个字节(第八个字节是CRC)。如果只需要部分刮板数据,主设备可以随时发送复位命令来终止读取。
SKIP ROM //0xcc
CONVENT T //0x44
READ SCRATCHPAD //0xbe
Read_temp
float Read_temp()//温度读取
{
unsigned char low,high;
Init_DS18B20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Init_DS18B20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low = Read_DS18B20();
high = Read_DS18B20();
return ((high<<8) | low) / 16.0;
}
快速建立底层
基本原理掌握了以后,下面我们来了解一下如何在蓝桥杯比赛时快速建立模板
首先比赛时会提供一部分底层文件,包括ds1302.c,onewire.c,iic.c,在2023年以后这三个文件都需要经过自己加上一些代码,这里只说明onewire.c如何改编。
一、onewire.c
下面是比赛官方给的onewire.c文件
/* # 单总线代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
//
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;
}
如果我们直接对其进行编译,keil会报错,这是因为没有定义DQ引脚和引入头文件,我们需要做的就是在这段代码之前加上这两个步骤,并且写一个读取温度的函数Read_temp
#include "onewire.h"
#include "reg52.h"
sbit DQ = P1^4;
//单总线内部延时函数
void Delay_OneWire(unsigned int 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;
}
float Read_temp()//读温度
{
unsigned char low,high;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low = Read_DS18B20();
high = Read_DS18B20();
return ((high<<8) | low) / 16.0;
}
二、onewire.h
float Read_temp()
到这里单总线通信以及DS18B20温度读取就写完了,具体如何使用我们后面再来说明。
无限进步