树莓派DS18B20温度获取

DS18B20温度传感器

DS18B20是常用的数字温度传感器, 其输出的是数字信号, 具有体积小, 硬件开销低, 抗干扰能力强, 单线数字温度传感器.
接下来我们将在树莓派上通过文件i/o调用来获取温度.

逻辑分析

通过寻找相关路径, 打开文件, 进行读操作. 将文件内容打印到屏幕上.
在我们的了解中, 实时温度数据在 /sys/bus/w1/devices/28-041731f7c0ff/w1_slave 这个文件中.
我们可以通过调用read()函数直接读取该文件的内容, 并找到我们所需的温度, 打印到屏幕.
每一个ds18b20的产品序列号都是不一样, 它保存温度的路径也所有变换.
在这里插入图片描述


不同的ds18b20温度传感器, 我们可以看到在存放温度的路径下, 仅仅是/28-xxxxx/ 这一个文件不同
通过opendir()与readdir(), 打开 /sys/bus/w1/devices/ 此路径的文件夹. 并读取文件夹中的内容.
找到 /28-xxxxx/ 文件, 存放到一个缓冲区, 通过函数strncat()将此文件加到固定路径中.
通过 open() 和 read() 将存放在文件的数据读出来.
使用 strstr() 找到我们需要的温度将其打印.

涉及函数

opendir()函数

// opendir()  						返回值:成功则返回DIR* 型态的目录流, 打开失败则返回NULL.
#include <sys/types.h>				
#include <dirent.h>					

DIR *opendir(const char *name);		//用来打开参数name 指定的目录, 并返回DIR*形态的目录流.

readdir()函数

//readdir()  						返回参数dir 目录流的下个目录进入点。
#include <sys/types.h>				
#include <dirent.h>					

struct dirent * readdir(DIR * dir);	//参数为opendir()返回的DIR结构体指针,获取到文件夹的相关信息

struct dirent
{
    ino_t d_ino; 					//d_ino 此目录进入点的inode
    ff_t d_off; 					//d_off 目录文件开头至此目录进入点的位移
    signed short int d_reclen; 		//d_reclen _name 的长度, 不包含NULL 字符
    unsigned char d_type; 			//d_type d_name 所指的文件类型 
    har d_name[256];				//d_name 文件名 
};

closedir()函数

#include<sys/types.h> 				
#include <dirent.h>					

closedir(DIR *dir);					//关闭打开的目录流

open()函数

#include <sys/types.h>				//open()头文件
#include <sys/stat.h>				//open()头文件
#include <fcntl.h>					//open()头文件

int open(const char *pathname, int flags);
/* 	第一个参数是需要打开文件的路径,
	第二个参数简单来说可以是打开文件的方式.	*/

read()函数

#include <unistd.h>					

ssize_t read(int fd, void *buf, size_t count);
/*	第一个参数为已经成功打开文件的返回值fd
	第二个参数为读取文件的缓冲区
	第三个参数为读多大到缓冲区	*/

close()函数

#include <unistd.h>					

int close(int fd);					//关闭已经打开的文件

strncpy函数

#include <string.h>

char * strncpy(char *dest, const char *src, size_t n);
/*	dest -- 指向用于存储复制内容的目标数组
	src -- 要复制的字符串
	n -- 要从源中复制的字符数
	特别注意: strncpy src 所指向的字符串复制到 dest, 最多复制 n 个字符.
	当 src 的长度小于 n 时,dest 的剩余部分将用空字节填充.		*/

strstr()函数

#include <stdio.h>
#include <string.h>

char *strstr(char *str1, char *str2);
/*	找出str2在str1中首次出现的位置(不包括str2的结束符). 
	若找到,返回的是该位置的指针. 否词返回NULL.	*/

strncat()函数

#include <string.h>

char *strncat(char *dest, const char *src, size_t n);
/*	将src字符串前n个字符连接到dest的尾部,‘\0’也会追加过去
	dest:目的字符串首地址
	src:源字符首地址
	n:指定需要追加字符串个数
	返回值: 成功,返回dest字符串的首地址. 失败返回NULL.	*/

atof()函数

#include <stdlib.h>

double atof (const char* str);
/*	将字符串转换为double
	返回转换后的浮点数;如果字符串 str 不能被转换为 double,那么返回 0.0。	*/

程序源码

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

#define BUFSIZE 1024

int main(int argc, char *argv[])
{
    int                 fd = -1;        //文件描述符
    int                 rv = -1;        //文件读取返回值
    int                 flag;           //读取到28-文件的标志
    char                buf[BUFSIZE];   //温度缓冲区
    char                *ptr = NULL;    //温度缓冲区指针
    char                dirbuf[100];    //目标路径缓冲区
    char                path[100] = "/sys/bus/w1/devices/";
    double              tem;            //温度
    DIR                 *dir;           //opendir的返回类型
    struct dirent       *rdirent;       //readdir返回的结构体指针
    
    if( (dir=opendir(path)) == NULL )
    {
        perror("Opendir file failed");
        return -2;
    }
    
    while((rdirent = readdir(dir)) != NULL)
    {
        if(strstr(rdirent->d_name, "28-"))  //寻找28-开头的文件
        {
            strncpy(dirbuf, rdirent->d_name, sizeof(dirbuf));  //将该文件拷贝到目标路径缓冲区
            flag = 1;
        }
    }
           
    if(flag != 1)
    {
        printf("Can not found the temperature file.\n");
        return -3;
    }

    closedir(dir);

    strncat(path, dirbuf, sizeof(path));  		//把找到的28-开头的文件追加到默认路径.
    strncat(path, "/w1_slave", sizeof(path));	//将/w1_slave/追加到路径中.
    
    printf("%s\n", path);						//打印最终路径
 	   
    if( (fd=open(path, O_RDONLY)) < 0 )
    {
        perror("Open temperature file failed");
        return -2;
    }

    lseek(fd, 0, SEEK_SET);						//将文件偏移量移动到开头
    if( (rv=read(fd, buf, sizeof(buf))) <0 )
    {
        perror("Read temperature data failed");
        return -3;
    }

    if( (ptr=strstr(buf, "t=")) != NULL)		//寻找温度所在行, 且返回t所在位置.
    {
        ptr = ptr+2;							//将地址偏移俩个字节, 得到温度.
        tem = atof(ptr);						//将字符串转换为double类型.
        tem = tem/1000;
        printf("Now the room temperature:%3.2f\n", tem);
    }
    else 
    {
        perror("Can not read temperture");
        return -4;
    }

    close(fd);
    
    return 0;
}

运行结果

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值