Linux编程实现DS18B20对树莓派温度的探测

 ̄綄美尐妖づ 提交于 2020-03-04 07:14:00

目录

(一)项目简介
(二)代码以及调试
(三)总结

(一)项目简介

     DS18B20是常用的数字温度传感器,其输出的是数字信号,具有体积小,硬件开销低,抗干扰能力强,精度高的特点,本次实验项目是依据树莓派对DS18B20 1线温度传感器的支持(一线协议),再通过编程实现温度的探测。

DQ 为数字信号输入/输出端;
GND 为电源地;
VCC 为外接供电电源输入端;
其中两者端口的连接方式如下:
树莓派 的 ground 端(pin 06脚)------------连接DS18B20的 GND的端口;
树莓派的 gpio 04 端(pin 07 脚)--------------连接DS18B20的 DQ的端口;
树莓派的 3.3V 端(pin 01脚)-------------连接DS18B20的 VCC端口;

(二)代码以及调试

1.通过SecurtCRT远程登录到树莓派服务器上,并找到该文件所在的位置,如下图在根目录下的w1_slave文件中:
文件所在位置
先调用 open() , read() , close()三个基本的文件I/O函数进行文件内容的读取:

  int main(int argc, char **argv)
  {    
     int fd;
       
     char buf[128];
      
     fd=open("/sys/bus/w1/devices/28-041731f7c0ff/w1_slave",O_RDONLY);
      
     memset(buf,0,sizeof(buf);   //初始化buf的内存,避免结果出现多余的字符
     
     read(fd,buf,sizeof(buf));   
     
     printf("buf: %s\n"buf);
 
     close(fd);
 }

运行结果如下:
在这里插入图片描述
2.如果想要过滤掉其他无关的字符,我们需要调用 strstr() 函数定位到“t="这个字符串,再利用printf()直接打印;因为温度位浮点数,为了读取方便我们需要调用atof()函数(a:ASCII码,to:转换,f: float类型)即:将字符串所对应的ASCII码转换成float类型。
代码优化结果如下:

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

int main(int argc, char **argv)
{
     int fd;
     char buf[128];
     char *ptr;
     float temp;
     
     fd=open("/sys/bus/w1/devices/28-041731f7c0ff/w1_slave",O_RDONLY);
    
     memset(buf,0,sizeof(buf);   
     
     read(fd,buf,sizeof(buf));
    
     printf("buf: %s\n"buf);
     
     ptr=strstr(buf,"t=");
     if(!ptr)
     {
         printf("can not find t=string\n");
         return -1;
     }
     
     ptr +=2;
    
     printf("ptr= %s\n",ptr);
    
     temp = atof(ptr)/1000;
    
     printf("temperature: %f\n",temp);

     close(fd);
}

运行结果如下:
在这里插入图片描述
3.实际上DS18b20芯片的序列号是不断改变的,但都是以“28-”开头,所以就需要进一步优化代码,利用strstr()函数来匹配“/sys/bus/w1/devices/”路径下含有“28-”的字符串,再利用strncat()函数拼接到该路径下,这样无论该芯片序列号如何变化都可以精确定位到相应的路径

最终代码如下:

#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<errno.h>
#include<dirent.h>
#include<stdlib.h>
int main(int argc, char **argv)
{
    int           fd=-1;
    char          buf[128];
    char          *ptr = NULL;
    float         temp;
    DIR           *dirp=NULL;
    struct dirent *direntp = NULL;
    char          w1_path[32]="/sys/bus/w1/devices/";
    char          chip_sn[32];
    int           found=0;

    dirp=opendir(w1_path);
    if(!dirp)
    {
        printf("open folder %s failure:%s\n",w1_path,strerror(errno));
        return -1;
    }
    while(NULL!=(direntp=readdir(dirp)))
    {
        if(strstr(direntp->d_name,"28-"))
        {
            strncpy(chip_sn,direntp->d_name,sizeof(chip_sn));
            found=1;
        }               

    }
    closedir(dirp);
    if(!found)
    {
        printf("can not find ds18b20 chipset\n");
        return -2;
    }
    strncat(w1_path,chip_sn,sizeof(w1_path)-strlen(w1_path));

    strncat(w1_path,"w1_slave",sizeof(w1_path)-strlen(w1_path));

    printf("w1_path:%s\n",w1_path);



    fd=open("w1_path",O_RDONLY);
    if(fd<0)
    {
        printf("open file failure: %s\n",strerror(errno));
        return -3;
    }
    memset(buf,0,sizeof(buf));   

    if(read(fd,buf,sizeof(buf))<0);
    {
        printf("read data from fd=%d failure: %s\n",fd,strerror(errno));
        return -4;
    }

    printf("buf: %s\n",buf);

    ptr=strstr(buf,"t=");
    if(!ptr)
    {
        printf("can not find t=string\n");
        return -5;
    }

    ptr +=2;

    printf("ptr= %s\n",ptr);

    temp = atof(ptr)/1000;

    printf("temperature: %f\n",temp);

    close(fd);

    return 0;
}

(三)总结

     本次项目涉及到了一些对树莓派和DS18B20硬件知识的掌握,但主要考验的是对Linux下文件IO系统调用的理解,和一定的c语言编程能力,不到位的地方还请大家多多指教,希望我的总结能对大家有所帮助。

文章链接:https://blog.csdn.net/weixin_45930204/article/details/104583400

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!