单总线协议简介
1-wire 单总线是Maxim 全资子公司Dallas 的一项专有技术。与目前多数标准串行数据通信方式,如SPI/I2C/MICROWIRE 不同,它采用单根信号线,既传输时钟,又传输数据而且数据传输是双向的。它具有节省I/O 口线资源、结构简单、成本低廉、便于总线扩展和维护等诸多优点。 单总线的数据传输速率一般为16.3Kbit/s,最大可达142 Kbit/s,通常情况下采用100Kbit/s以下的速率传输数据 1-Wire线端口为漏极开路构或三态门的端口,因此一般需要加上拉电阻Rp,通常选用5K~10KΩ。 有关单总线的详细介绍参考此文。 参加蓝桥杯或者通单片机使用DS18B20的同学肯定是比较熟悉这个协议的,在获取温度的过程中使用的步骤是先初始化,然后写命令;然后再初始化,读命令获取温度。整个单总线的通信步骤:初始化1-wire器件、识别1-wire器件和交换数据。 由于它们是主从结构,只有主机呼叫从机时,从机才能应答,因此主机访问1-wire器件都必须严格遵循单总线命令序列,即1.初始化、2.ROM、3.命令功能命令。 今天使用的DHT11他只是采用单总线数据格式,具体的命令序列与DS18B20这些严格遵循初始化、ROM、命令功能命令三部曲的器件有所不同。DHT11只是采用单总线的通信步骤:初始化1-wire器件、识别1-wire器件和交换数据。
树莓派4B+DHT11(1-Wire协议)
DHT11简介
接口定义
数据格式
DATA脚 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明: 8bit湿度整数数据+8bit湿度小数数据 +8bi温度整数数据+8bit温度小数数据 +8bit校验和 数据传送正确时校验和数据等于“ 8bit 湿度整数数据 +8bit 湿度小数数据 +8bi 温度整数数据 +8bit 温度小数数据 ”所得结果的末8位。
通信流程
1.总线初始化;(拉低总线时长不小于18ms,然后释放,总线回到高电平) 2.DHT11应答;(DHT11应答将总线拉低) 3.输出数据帧(一次完整的数据传输为40bit,高位先出。) 数据帧格式: 通讯时序图:
硬件连接
树莓派 | DHT11 |
---|
5V | vcc | 7号引脚(板载编码) | DATA | GND | GND |
开启树莓派1-Wire接口
此步骤和之前SPI、I2C操作一样,不再贴图,为了保险起见,建议开启口重启一下树莓派 sudo reboot。
编程实现
由于DHT11的读取相对简单,就是按照时序控制IO口的输入输出即可。 代码来自此文。 笔者只是简单的根据时序图添加了注释 打开Geany,输入以下代码:
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef unsigned long uint32;
#define HIGH_TIME 32
int pinNumber =7;
uint32 databuf;
uint8 readSensorData(void)
{
uint8 crc;
uint8 i;
pinMode(pinNumber,OUTPUT);
digitalWrite(pinNumber, 0);
delay(25);
digitalWrite(pinNumber, 1);
pinMode(pinNumber, INPUT);
pullUpDnControl(pinNumber,PUD_UP);
delayMicroseconds(27);
if(digitalRead(pinNumber)==0)
{
while(!digitalRead(pinNumber));
for(i=0;i<32;i++)
{
while(digitalRead(pinNumber));
while(!digitalRead(pinNumber));
delayMicroseconds(HIGH_TIME);
databuf*=2;
if(digitalRead(pinNumber)==1)
{
databuf++;
}
}
for(i=0;i<8;i++)
{
while(digitalRead(pinNumber));
while(!digitalRead(pinNumber));
delayMicroseconds(HIGH_TIME);
crc*=2;
if(digitalRead(pinNumber)==1)
{
crc++;
}
}
return 1;
}
else
{
return 0;
}
}
int main (void)
{
printf("Use GPIO1 to read data!\n");
if (-1 == wiringPiSetup()) {
printf("Setup wiringPi failed!");
return 1;
}
pinMode(pinNumber, OUTPUT);
digitalWrite(pinNumber, 1);
printf("Enter OS-------\n");
while(1) {
pinMode(pinNumber,OUTPUT);
digitalWrite(pinNumber, 1);
delay(3000);
if(readSensorData())
{
printf("Congratulations ! Sensor data read ok!\n");
printf("RH:%d.%d\n",(databuf>>24)&0xff,(databuf>>16)&0xff);
printf("TMP:%d.%d\n",(databuf>>8)&0xff,databuf&0xff);
databuf=0;
}
else
{
printf("Sorry! Sensor dosent ans!\n");
databuf=0;
}
}
return 0;
}
效果如下:
利用单总线与DS18B20通信获取温度
由于大佬们早已制作了DS18B20的读取文件,因此在利用DS18B20获取温度时,只需调用文件接口即可获得温度信息,也不需要想STM32和其他单片那样去对着时序图一点一点的初始化,写数据/指令,读数据了。c语言实现详细步骤参考此文;Python参考此文。
总结
有关单总线的使用就记录到此,有不妥之处欢迎批评指正。
Wire单总线的基本原理
|