树莓派——DS18B20获取温度

1 DS18B20简介

(1) ds18b20介绍

DS18B20是常用的数字温度传感器,其输出的是数字信号,具有体积小,硬件开销低,抗干扰能力强,精度高的特点,是通过一线协议来配置的传感器,刚好拿实验室的树莓派来做一下获取温度的小项目。

(2) DS18B20连接树莓派

配置内核启动后自动加载一线协议驱动

  • 连接引脚
    在这里插入图片描述

  • 输入命令进行配置

pi@raspberrypi:~ $ sudo raspi-config  //打开配置选项

在这里插入图片描述
按Enter选中
在这里插入图片描述
继续按Enter选中
在这里插入图片描述

  • 打开内核文件
pi@raspberrypi:~ $ vim /boot/config.txt

在最后添加连接的引脚,我们连接了22(BCM编码)

dtoverlay=w1-gpio-pullup,gpiopin=22

在这里插入图片描述

  • 重启树莓派
pi@raspberrypi:~ $ sudo reboot
  • 重启系统后,确认系统有自动加载一线协议的驱动模块
pi@raspberrypi:~/ds18b20 $ lsmod | grep w1

在这里插入图片描述
当树莓派配置好DS18B20数字温度传感器后,该温度信息通常保存在下面路径中,我们只需要读取文件中的温度即可:

/sys/bus/w1/devices/28-XXXXXXXX/w1_slave

查看路径文件下温度数据:
在这里插入图片描述

(3) 流程简述

1 调用opendir()和readdir()来打开读取文件路径(默认文件路径“/sys/bus/w1/devices/”)
在这里我们注意到为什么不是全部路径 (/sys/bus/w1/devices/28-XXXXXXXX/w1_slave) 而是只截取到 (/sys/bus/w1/devices/),这是因为“28-XXXXX”是产品序列号,如果我们换了一个DS18B20进行获取温度,产品序列号XXXXX改变,那此路径就不能用了,而这一产品序列号XXXXX目录无论变成什么永远在(/sys/bus/w1/devices/)路径下,所以我们只打开读取路径到这里

2 寻找“28-”开头的文件,将其存入缓冲区
接下来在(默认文件路径“/sys/bus/w1/devices/”)下通过strstr()函数找到“28-”打头的文件,并且存入缓冲区,方便更改

3 调用closedir()关闭文件**

4 通过strncat链接文件路径
调用strncat将(默认文件路径“/sys/bus/w1/devices/”)和存入缓冲区的(“28-XXXXX”)连接起来,然后再调用strncat()将“/w1_slave”路径连接起来,此时需要读取数据的路径就完整了,进行实时获取产品序列号的文件目录,以便实时读取温度

5 调用open()和read()来打开文件,读取文件,找到温度(t=)打头的数据
利用strstr()再匹配(“t=”)打头的数据

6 调用close()关闭文件

7 将数据进行处理然后打印即可
将获得的字符类型数据转换成单精度类型数据,只打印数据,不打印“t=”

2 项目代码介绍

(1)文件I/O的API函数

open()

 int open(const char *path, int oflag, ... /*mode_t mode*/);

open()系统调用用来打开一个文件,并且返回一个文件描述符(fd),并且该文件描述符是当前进程最小,并未使用的文件描述符数值,即3,因为0是标准输入,1是标准输出,2是标准出错。

参数: path: 要打开的文件、设备的路径
oflag: 由多个选项进行“或”运算构造oflag参数 。
必选: O_RDONLY (只读)、 O_WRONLY(只写)、 O_RDWR(读写)
可选: O_APPEND 每次写时都追加到文件的尾端。
O_CREAT 文件不存在则创建它,使用该选项需要第三个参数mode
O_TRUNC 如果文件存在,而且为只写或读写成功打开,则将其长度截取为0;
O_NONBLOCK 如果path是一个FIFO、块设备、字符特殊文件则此 选项为文件的本次打开和后续的I/O操作

设置非阻塞模式方式:
O_EXEC、O_SEARCH、O_CLOEXEC、O_NOCTTY…
mode: oflag带O_CREAT选项时可以用来创建文件,这时必须带该参数用来指定创建文件的权限模式,如066。 否则不需要。

使用示例代码:
int fd;
fd = open(“text.txt”, O_RDWR|O_CREAT|O_TRUNC, 0666);
fd = open(“text.txt”, O_WRONLY|O_APPEND);

read()

ssize_t read(int fd, void*buf, size_t nbytes);

read()函数是用来打开文件描述符对应的文件中读取数据放到buf指向的内存空间中去,最多不要超过nbytes个字节,这里的nbytes一般指的是buf剩余空间的大小。如果read成功,则返回实际读到的字节数(由nbtyes或读懂到文件尾决定,其中EOF宏用来判断是否到了文件尾),如果返回值小于0则表示出错,如哦尝试读取一个没有权限读取的文件时就会抛错。

close()

int close(int fd);

该函数用来关闭一个打开的文件描述符,关闭一个文件时还会释放该进程加载该文件上的所有记录锁。当一个进程终止时,内核将会自动关闭它所打开的文件。

opendir()

DIR *opendir(const char *pathname)

opendir()是用来打开指定的目录文件,并返回DIR *形态的目录流,和open()类似,接下来对目录的搜索和读取都要使用此返回值,该返回值是指向DIR结构体的指针,失败返回 NULL。

readdir()

struct dirent *readdir(DIR *dirp)

readdir()函数的参数是opendir()返回的DIR *结构体指针也就是dirp,通过这个结构体,我们可以读取文件夹的相关信息(文件名,长度等),并返回一个direntp的指针,该结构体就用来存放这些信息,失败时返回NULL

struct dirent
{   
    long d_ino; /* inode number 索引节点号 */   
    off_t d_off; /* offset to this dirent 在目录文件中的偏移 */   
    unsigned short d_reclen; /* length of this d_name 文件名长 */   
    unsigned char d_type; /* the type of d_name 文件类型 */   
    char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符*/
}

closedir()

关闭目录路流

(2)项目代码

   #include <stdio.h>
   #include <string.h>
   #include <stdlib.h>
   #include <errno.h>
   #include <sys/types.h>
   #include <sys/stat.h>
   #include <unistd.h> 
   #include <dirent.h>
   #include <fcntl.h>
  
  
  int main(int argc, char *argv[])
  {
      char                path[100] = "/sys/bus/w1/devices/";  //局部变量存储大概路径
      char                buf1[1024];  
      char                buf2[100];   
      char                *ptr = NULL;  
      int                 fd = -1;  
      int                 rv = -1; 
      int                 flag = 0;  
      float               temp;  
      DIR                 *dirp;  
      struct dirent       *direntp;
  
      if((dirp = opendir(path)) == NULL)
      {
          printf("Opendir %s error: %s\n",path,strerror(errno));
          return -1;
      }
  
      while((direntp = readdir(dirp)) != NULL)
      {
      
          if(strstr(direntp->d_name, "28-"))
          {
              strncpy(buf2, direntp->d_name, sizeof(buf2));
              flag = 1;
          }
     }
 
     closedir(dirp);

     if(!flag)
      {
         printf("Can not find 28- in the path\n");
          return -2;
      }
  
      strncat(path, buf2, sizeof(path)-strlen(path));
      strncat(path, "/w1_slave",sizeof(path)-strlen(path));
  
      if((fd = open(path,O_RDONLY)) < 0)
     {
           printf("Open %s failure: %s\n",path,strerror(errno));
           return -3;
     }
  
      if((rv = read(fd,buf1,sizeof(buf1))) < 0)
      {
         printf("Read %s failure;%s\n",path,strerror(errno));
          return -4;
      }
  
      close(fd);
  
      if((ptr = strstr(buf1,"t=")) != NULL)
      {
          temp = atof(ptr+2)/1000;
          printf("The current temperature: %.2f℃\n",temp);
      }
      else
      {
          printf("Can not get the current temperture\n");
          return  -5;
      }
  
      return 0;
  }

· 运行结果
在这里插入图片描述
获取到了我们想要的温度!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值