树莓派下DS18B20获取实时温度
文章目录
- 1. DS18B20温度传感器
- 2. DS18B20安装及配置
- 3.基础代码逻辑分析
- 3.1 逻辑分析
- 3.2 阶段代码示例
- 4. 代码及运行结果
- 4.1 全部代码
- 4.1 运行结果
1. DS18B20温度传感器
DS18B20是比较常用到的温度传感器,采用单总线控制。是美国DALLAS半导体公司继DS1820之后最新推出的一种改进型智能温度传感器。
这里对于它就不进行过多的讲解,主要讲解如何在树莓派上用它来获取温度。详细资料参考:DS18B20介绍。
2. DS18B20安装及配置
DS18B20的接线连接参照下图,VCC接3.3v的引脚,GND接地,DQ线连在GPIO04上。
接好线之后,我们要配置内核启动后自动加载一线协议驱动,在命令行键入sudo raspi-config,依次选择如下选项,就可以使能内核以一线协议(1-wire)驱动模块。
然后命令行键入vim /boot/config.txt,并在最后一行添加 dtoverlay=w1-gpio-pullup,gpiopin=4。(这里的4就是pin7,应该是采用BCM GPIO的标准)。
随后sudo reboot重启系统,键入 lsmod | grep w1 检查系统是否已经自动加载一线协议的驱动模块。
我们知道Linux下“一切皆文件”,DS18B20的文件就在“/sys/bus/w1/devices/”下
这个叫“28-041731f7c0ff”的文件夹是我用的这个DS18B20的产品序列号,然后在这个文件夹里面的“w1_slave”里就存放着实时的温度,我们可以看一看
前面那些数据我们不管他,可以看到“t=11250”,这个就是我这个设备上的实时温度(11.25℃)。了解到这些之后,我们来捋一捋代码里面要用什么样的方式来读取这个温度,并显示出来。
3.基础代码逻辑分析
3.1 逻辑分析
如果我们人为的想要在树莓派上读取温度,我们需要转到相应路径下去,查看相应的文件即可,但是我们编写程序的时候,为了得到更广泛的适用性,并不能直接简单粗暴地用read()去读取相应路径下的文件,因为每个DS18B20的产品序列号不一样,那么温度保存文件的路径也就会不一样。
因为序列号不同的缘故,我们的代码需要逐步实现如下功能:
step1. 用opendir()和readdir()的组合,打开每个设备都一样的默认路径(/sys/bus/w1/devices/),并读取路径下的内容。
step2. 找出默认路径下“28-”开头的的文件夹,并将其名称保存到一个缓存区中,然后用这个缓存区的内容来更新目标路径。
step3. 用open()和read()读取目标路径的内容,找出其中“t=”的部分,并记录下来。随后便可以简单粗暴的一个printf()将实时温度打印到标准输出上。
3.2 阶段代码示例
依照上面的思路,我们可以先做出前两部分寻找目标路径的代码,这里我用了strstr()来找以“28-”开头的文件夹。还用了strncat()来更新目标文件路径。
strstr()的作用是判断前者字符串中是否包含有后者字符串的内容,若包含,返回其第一次出现的首地址,若无则返回NULL
strncat()的作用是在一个字符串的后面加上另一个字符串,并且能保证前者的剩余空间足够放下后者。
if((dir = opendir(path)) == NULL ) //打开文件夹并判断成败{printf("Open directory failed: %s", strerror(errno)); //失败打印提示return -1;}while((direntp = readdir(dir)) != NULL) //读取文件夹内容,用direntp保存其地址{/***************************步骤1和步骤2的假想分割线********************************/if(strstr(direntp->d_name, "28")); //用if循环找“28-”开头的文件夹{strcpy(dstfile, direntp->d_name); //将目标路径文件夹保存到缓冲区flag = 1; //成功找到“28-”开头的文件夹的标志,}}closedir(dir); //关闭文件夹if(flag != 1) //利用标志判断有没有成功找到“28-”开头的文件夹{printf("Can not found the temperature file.\n"); return -2;}strncat(path, dstfile, sizeof(path)); //给默认路径加上找到的“28-”开头的文件夹strncat(path, "/w1_slave", sizeof(path)); //继续加上需要打开的文件“w1_slave”,这样就完成了目标路径的更新
简单介绍一下opendir()、readdir() 和 closedir() 这几个函数的使用,他们的原型和介绍如下:
#include <sys/types.h> //opendir()的头文件
#include <dirent.h> //opendir()的头文件
DIR *opendir(const char *name); //打开参数name指定的目录,并返回DIR*类型的目录流,类似于文件描述符#include<sys/types.h> //readdir()的头文件
#include <dirent.h> //readdir()的头文件
struct dirent *readdir(DIR *dir); //读取某个文件夹里的内容,保存到结构体dirent里,返回该结构体的地址struct dirent //readdir返回的结构体内容
{ino_t d_ino; // 此目录进入点的inodeff_t d_off; // 目录文件开头至此目录进入点的位移signed short int d_reclen; // 文件的的长度, 不包含NULL 字符unsigned char d_type; // 文件类型 har d_name[256]; // 文件名(这里我们只关心这个!)
};#include<sys/types.h> //closedir()的头文件
#include <dirent.h> //closedir()的头文件
closedir(DIR *dir); //类似cloes,简单粗暴,用完就关
有了目标路径,那接下来就好办了,用一套open()、read() 和 close() 的组合就能很简单的读出来,同样用strstr()来找到文件中“t=”开头的字符串首地址,但是我们在打印温度的时候需要将这个地址向后偏移两个字节,去掉“t=”
if((fd = open(path, O_RDONLY)) < 0 ) //根据目标路径以只读的形式打开文件,同样加上错误判断{printf("Open temperature file failed: %s\n", strerror(errno)); //出错提醒return -3;}if((rv = read(fd, buf, sizeof(buf))) < 0) //读取文件内容,并保存在buf里{printf("Read temperature data failed: %s\n", strerror(errno));return -4;}close(fd);if((ptr = strstr(buf, "t=")) != NULL) //strstr()找到温度存放的地址,并保存起来{tem = atof(ptr+2)/1000; //这里加2是将地址偏移两个字节,跳过文件中的“t=”,只保留有用的温度数据printf("The temperature in LingYun Studio is %f now.\n", tem); //简单粗暴,快哉!}else{printf("Can not read the temperature data: %s.\n", strerror(errno)); //buf里面没有读取到温度数据,就会报错return -5;}
4. 代码及运行结果
4.1 全部代码
给上面的代码加上头文件,并声明相关参数,就可以得到完整的代码:
#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 PATH "/sys/bus/w1/devices/" //宏定义默认路径
#define BUF_SIZE 128
#define PATH_SIZE 100int main(int argc, char **argv[])
{char path[PATH_SIZE] = PATH; //局部变量保存默认路径DIR *dir; //opendir的返回类型,用来指定打开的文件夹struct dirent *direntp; //readdir返回的结构体指针,用来指向打开文件夹的内容char dstfile[48]; //目标路径缓存区int flag = -1; //初始化文件夹读取成败标志int fd = -1; //初始化文件描述符int rv = -1; //初始化文件读取返回值char buf[BUF_SIZE]; //实时温度缓冲区double tem = 0.00; //初始化实时温度数据 char *ptr = NULL; //初始化实时温度缓冲区指针if((dir = opendir(path)) == NULL ) //打开文件夹并判断成败{printf("Open directory failed: %s", strerror(errno)); //失败打印提示return -1;}while((direntp = readdir(dir)) != NULL) //读取文件夹内容,用direntp保存其地址{if(strstr(direntp->d_name, "28")); //找到“28-”开头的文件夹{strcpy(dstfile, direntp->d_name); //将目标路径文件夹保存到缓冲区flag = 1; //成功找到“28-”开头的文件夹的标志,}}closedir(dir); //关闭文件夹if(flag != 1) //利用标志判断有没有成功找到“28-”开头的文件夹{printf("Can not found the temperature file.\n"); return -2;}strncat(path, dstfile, sizeof(path)); //给默认路径加上找到的“28-”开头的文件夹strncat(path, "/w1_slave", sizeof(path)); //继续加上需要打开的文件“w1_slave”,这样就完成了目标路径的更新if((fd = open(path, O_RDONLY)) < 0 ) //根据目标路径以只读的形式打开文件,同样加上错误判断{printf("Open temperature file failed: %s\n", strerror(errno)); //出错提醒return -3;}if((rv = read(fd, buf, sizeof(buf))) < 0) //读取文件内容,并保存在buf里{printf("Read temperature data failed: %s\n", strerror(errno));return -4;}close(fd);if((ptr = strstr(buf, "t=")) != NULL) //strstr()找到温度存放的地址,并保存起来{tem = atof(ptr+2)/1000; //这里加2是讲地址便宜两个字节,跳过文件中的“t=”,只保留有用的温度数据printf("The temperature in LingYun Studio is %f now.\n", tem); //简单粗暴,快哉!}else{printf("Can not read the temperature data: %s.\n", strerror(errno)); //buf里面没有读取到温度数据,就会报错return -5;}return 0; // ending
}
4.1 运行结果
编译后运行就可以得到如下结果:
树莓派下DS18B20获取实时温度相关推荐
- DS18B20温度传感器在树莓派下获取实时温度
目录 1. DS18B20温度传感器的介绍 2.代码流程分析 2.1获取实时温度值 2.2获取温度值存放路径 2.3用到的库函数 3.完整代码 4.输出结果 1. DS18B20温度传感器的介绍 DS ...
- 树莓派与DS18B20获取环境温度(Linux)
树莓派与DS18B20获取环境温度(Linux) 前言 一.硬件准备 1.1 树莓派4B 1.2 DS18B20温湿度传感器 1.4 项目展示效果 二.软件准备 2.1 Vim(Linux) 2.2 ...
- STM32+MAX6675利用io口模拟SPI获取实时温度数据程序及代码
STM32+MAX6675利用io口模拟SPI获取实时温度数据程序及代码 本文采用的芯片为STM32F103RCT6 温度芯片为MAX6675 因为芯片的spi口只有3个,有部分需要外接W25Q128 ...
- STM32+MAX6675利用SPI获取实时温度数据程序及代码
之前写的STM32+MAX6675利用io口模拟SPI获取实时温度数据程序及代码 本文采用的芯片为STM32F103RCT6 温度芯片为MAX6675 模拟spi之前写过 里面的部分代码摘取的正点原子 ...
- linux 下如何获取 cpu 温度
直接读取系统信息 可以通过读取如下路径中的数据来获取cpu的温度信息,不过读取的数据没有经过处理. cpu0: cat /sys/class/thermal/thermal_zone0/temp cp ...
- max6675 c语言程序,STM32+MAX6675利用SPI获取实时温度数据程序及代码
标签: 本文采用的芯片为STM32F103RCT6 温度芯片为MAX6675 模拟spi之前写过 里面的部分代码摘取的正点原子的函数库:sys.uart.delay等文件 原理图 max6675.h ...
- python获取cpu温度_如何获得树莓派CPU实时温度值
[前言] 任何的电子设备在工作过程中必定会产生发热的现象,而不控制好设备的温度的话,很有可能会损坏设备,或者照成设备的性能下降,本文将通过学习如何读取树莓派CPU温度值,方便后期对树莓派做一些相应的控 ...
- 如何获得树莓派CPU实时温度值
如何获得树莓派CPU实时温度值 [前言] 任何的电子设备在工作过程中必定会产生发热的现象,而不控制好设备的温度的话,很有可能会损坏设备,或者照成设备的性能下降,本文将通过学习如何读取树莓派CPU温度值 ...
- Java免费获取实时汇率API
最近在做项目,涉及到实时汇率的获取,查了很多方法.下面写下自己获取实时汇率的心得,希望帮到有需要的人. 我使用的是聚合数据,免费的货币汇率API https://www.juhe.cn/docs/ap ...
最新文章
- 还不会用 K8s 集群控制器?那你会用冰箱吗?(多图详解)
- jquery.easing.js(转)
- 找出数组中前K大的值
- 约瑟夫问题C语言加注释,用链表实现约瑟夫环【有注释,有很多注释】
- 第四次作业 孙保平034 李路平029
- ROS----小乌龟之你追我赶
- thinkphp多表查询两表有重复相同字段解决方法
- prime算法-最小生成树
- 在 Windows XP Embedded 中使用 Enhanced Write Filter (EWF)[微软影子系统]
- 如何用python 巡检华为交换机?
- c语言使用三种方法计算圆周率,求用三种方法计算圆周率(C语言)
- 11种服务器编程语言对比(附游戏服务器框架) 2020.06
- 微信聊天记录的图片在哪查看
- 条件与循环Phython
- Unity制作出《超级马里奥》的2D和3D混合效果
- nginx实现对css,js文件缓存
- 仿soul交友盲盒1.0全开源源码/完整盲盒交友系统源码
- 了解Oracle历史
- 六级高频词汇——Group06
- Java三种多线程实现睡眠排序