天天看點

使用樹莓派GPIO17和GPIO18連接配接DS18B20溫度傳感器(關于DS18B20的時序設定)一、樹莓派自帶W1-GPIO讀取二、使用GPIO17和GPIO18進行時序配置實作資料讀取

一、樹莓派自帶W1-GPIO讀取

在樹莓派中有一種自帶的檢視DS18B20溫度資訊,已經寫好DS18B20時序,對外設裝置進行讀取資訊然後儲存的值在/sys/bus/w1/devices/28-xxxxxxxxxxx/w1_slave檔案中,将DS18B20的DQ資料線直接連接配接在樹莓派的GPIO4上就可以使用cat指令進行檢視溫度值。連接配接方式如圖1,讀取溫度如圖2。讀取到溫度為 t / 1000,圖2的溫度為23.187。

使用樹莓派GPIO17和GPIO18連接配接DS18B20溫度傳感器(關于DS18B20的時序設定)一、樹莓派自帶W1-GPIO讀取二、使用GPIO17和GPIO18進行時序配置實作資料讀取

圖1.使用w1-gpio進行溫度讀取

使用樹莓派GPIO17和GPIO18連接配接DS18B20溫度傳感器(關于DS18B20的時序設定)一、樹莓派自帶W1-GPIO讀取二、使用GPIO17和GPIO18進行時序配置實作資料讀取

圖2.使用cat讀取溫度資訊

使用C語言打開w1_slave檔案進行讀取轉換就行,代碼如下

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>

#define  BUFSIZE  128

char* addr = "/sys/bus/w1/devices/28-02161682f4ee/w1_slave";

int main(void)
{
	float temp;
	int i, j;
    int fd;
	int ret;

	char buf[BUFSIZE];
	char tempBuf[5];
	while (1){
	fd = open(addr, O_RDONLY);

	if(-1 == fd){
		perror("open device file error");
		return 1;
	}

	while(1){
		ret = read(fd, buf, BUFSIZE);
		if(0 == ret){
			break;	
		}
		if(-1 == ret){
			if(errno == EINTR){
				continue;	
			}
			perror("read()");
			close(fd);
			return 1;
		}
	}

	for(i=0;i<sizeof(buf);i++){
		if(buf[i] == 't'){
			for(j=0;j<sizeof(tempBuf);j++){
				tempBuf[j] = buf[i+2+j]; 	
			}
		}	
	}

	temp = (float)atoi(tempBuf) / 1000;

	printf("%.3f C\n",temp);

	close(fd);
	}
	return 0;
}

           

二、使用GPIO17和GPIO18進行時序配置實作資料讀取

參考文獻

溫度傳感器DS18B20應用

DS18B20通過使用DQ資料線對ROM進行寫數操作讀寫來控制操作模式及讀取數值,調用wiringPi庫。

每次操作完成後寫1為釋放總線。

①複位、應答

根據時序表先寫入1進入檢測狀态,然後寫0進入總線檢測應答,檢測應答時間為480~960us,如果應答成功則需要下一個拉高(需要人為寫1)進行應答脈沖,晶片應答成功将總線拉低,表示複位成功。

void Init_DS18B20(void)
{
	unsigned int var = 0;


	digitalWrite(DQ_OUT, HIGH);	  //開
	delayMicroseconds(1); // 微秒

	digitalWrite(DQ_OUT, LOW);	  //關
	delayMicroseconds(500);
	digitalWrite(DQ_OUT, HIGH);	  //開


	delayMicroseconds(60);
	var = digitalRead(DQ_IN);
	if (0 == var)
	{
		ds_flag = 1;
		delayMicroseconds(250);

	}
	else
	{
		ds_flag = 0;
	}

	digitalWrite(DQ_OUT, HIGH);	  //開

}

           

②寫操作模式

ROM操作模式有以下功能

ROM 功能指令

Read Rom[33h] 讀取DS18B20中ROM的内容

該指令允許總線主機讀取DS18B20的8位c産品家族碼,唯一的48位序列号和8位CRC。 隻有在總線上有一個DS18B20時才能使用此指令。 如果總線上存在多個從機,當所有從機同時嘗試往主機發送時,将發生資料沖突時(會産生線與結果)。

Match Rom[55h] ROM比對

比對ROM指令後跟64位ROM位址,允許總線主機在多點總線上尋址特定的DS18B20。 隻有與64位ROM位址完全比對的DS18B20才響應總線主機的指令。 所有與64位ROM序列不比對的從器件将等待複位脈沖。 此指令可用于總線上的單個或多個從機。

Skip Rom[CCh] 跳過ROM

該指令允許總線主機可以不提供64位ROM序列也能通路存儲器,進而可以節省單個總線系統中的時間。如果總線上存在多個從機并且主機在發出Skip ROM指令之後發出讀指令,則當多個從機同時發送時,總線上将發生資料沖突(會産生線與結果)。

Search Rom[F0h] 搜尋ROM

當系統剛啟動時,總線上的主機可能不知道單總線上的從機數量和它們的64位ROM序列号。搜尋ROM指令使總線主機識别總線上所有從機的64位ROM序列号。

Alarm Search[ECh] 警報搜尋

該指令的流程圖與Search ROM指令相同,但是,隻有在最後一次溫度測量中遇到報警條件時,DS18B20才會響應這個指令。

存儲功能指令

Write Scratchpad[4Eh] 寫暫存器

發出資料向内部RAM的第2,3,4位元組寫,内容是上限溫度資料指令、下限溫度資料指令。

Read Scratchpad [BEh] 讀暫存器

讀内部RMA中的9位元組的内容

Copy Scratchpad [48h] 複制暫存器

将RAM中的第2,3,4位元組的内容複制到EEPROM中

Convert T [44h] 溫度轉換

啟動DS18B20進行溫度轉換,轉換時間最長為500ms(典型為200ms),結果存入内部9位元組RAM中

Recall E2 [B8h] 重調EEPROM

EEPROM中的内容恢複到RAM中的第2,3,4位元組

Read Power Supply [B4h] 讀供電方式

讀DS18B20的供電模式,寄生供電時DS12B20發送“0”,外接電源供電時DS12B20發送“1”

ROM會有64位的ROM序列号如果不使用0xCC跳過則需要進行ROM比對,一把都進行跳過;

0x44為溫度轉換,轉換一般需要100ms~1s的時間延時,轉換為數值為模拟量值,還需要進行16位的分辨率轉換,即得到的值除以16。

0xBE為讀取ROM類的數值。

寫操作分為寫1和寫0但兩者的總時序都在60us完成。

void WriteOneChar(unsigned char data)
{
	unsigned char i = 0, j = 0;
	unsigned int temp = 0;


	digitalWrite(DQ_OUT, HIGH);	  //開 // Write 1
	delayMicroseconds(61);

	for (j = 1;j <= 8;j++)
	{
		digitalWrite(DQ_OUT, LOW);	  //關 // Write 0
		delayMicroseconds(15);

		temp = data & 0x01;
		data = data >> 1;

		digitalWrite(DQ_OUT, temp);	  //寫值
		delayMicroseconds(45);
		digitalWrite(DQ_OUT, HIGH);	  //釋放總線 // Write 1
		delayMicroseconds(2);


	}
	digitalWrite(DQ_OUT, HIGH);	  //釋放總線 // Write 1


}
           

③讀模式

讀模式在得到總線資源的15us内讀到資料,讀取後等待40us得到下一包資料,而我的做法是空一拍資料這樣做的好處是可以更加準确的得到總線資源

unsigned char ReadOneChar(void)
{
	unsigned char i = 0;
	unsigned char var = 0;
	unsigned char vara = 0;


	digitalWrite(DQ_OUT, HIGH);	  //開 // Write 1
	delayMicroseconds(2);
	digitalWrite(DQ_OUT, LOW);	  //關
	delayMicroseconds(3);

	digitalWrite(DQ_OUT, HIGH);	  //開 // Write 1
	delayMicroseconds(3);


	var = digitalRead(DQ_IN);
	delayMicroseconds(60); // 微秒


	return var;
}
           

讀取一個溫度值

unsigned char DS18B20_Read_Byte(void)
{
	unsigned char i, j, data;
	data = 0;
	for (i = 1;i <= 8;i++)
	{
		j = ReadOneChar();
		data = (j << 7) | (data >> 1);
	}
	return data;
}

unsigned int ReadTempetature(void)
{
	unsigned int data[3] = { 0,0,0 };
	unsigned char i = 0;

	Init_DS18B20();
	while (0 == ds_flag)
	{
		Init_DS18B20();
	}

	WriteOneChar(0xCC);
	WriteOneChar(0x44);
	delay(500); // 毫秒
	Init_DS18B20();


	WriteOneChar(0xCC);
	WriteOneChar(0xBE);
	data[0] = DS18B20_Read_Byte();
	data[1] = DS18B20_Read_Byte();
	data[2] = data[1] << 8 | data[0];
	return data[2];

}
           

最後main函數調用

int main(void)
{
	unsigned int a = 0;
	wiringPiSetupSys();

	pinMode(DQ_OUT, OUTPUT);
	pinMode(DQ_IN, INPUT);


	while (true)
	{
		a = ReadTempetature();
		a = a / 16;
		printf("temp=%d\n", a);
	}
	return 0;
}