既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新
在开始之前,要使能树莓派内核的单总线协议驱动模块(1-Wire)
具体操作如下
sudo raspi-config
单总线的接口默认是GPIO 4(BCM),使用默认接口的话可以忽略下面更换引脚的操作
若想更换自己选择的端口,则需要在 /boot/config.txt 文件的最后那行中加上 “,gpiopin=你想要的端口”。
vim /boot/config.txt
在最后一行添加以下内容,这里的 gpiopin = 4 是采用BCM GPIO的标准。
如果是模块化的DS18B20,则添加以下内容【因为模块中已包含上拉电阻】
dtoverlay=w1-gpio, gpiopin=4
如果是单独的一个DS18B20芯片【也就是普通直插三极管的样子】
dtoverlay=w1-gpio-pullup, gpiopin=4
最后重启系统
sudo reboot
确认系统有自动加载单总线协议的驱动模块:
lsmod | grep w1
以下为正常加载
二、实现过程
配置好单总线的驱动协议模块后,将DS18B20接上树莓派
Raspberry Pi | DS18B20 |
---|---|
3.3V | VCC |
GND | GND |
4 (BCM) | DQ |
接上树莓派后,可以在 /sys/bus/w1/devices/ 目录下找到一个28-xxxxxx的文件夹(xxxxxxx为该DS18B20芯片的序列号)
该文件夹存放 DS18B20 的数据信息
DS18B20测量的温度数据存放在该文件夹的 w1_slave 文件中。
从图中看出,这时DS18B20测量的温度值为 31.562 ℃
1、找该DS18B20芯片的设备文件夹
- ①、打开 “/sys/bus/w1/devices/” 这个文件夹,并让dirp指向该文件夹
- ②、从该文件夹中,逐个找 “ 文件名中包含有 28- 的文件 ”
- ③、找到则将文件夹名复制给字符数组 dir_name
- ③、找不到则报错,退出函数
char path[50] = "/sys/bus/w1/devices/";
//打开文件夹"/sys/bus/w1/devices/"
if ((dirp = opendir(path)) == NULL)
{
printf("ERROR: Open Directory '%s' Failure: %s\n", path, strerror(errno));
return -1;
}
printf("Open Directory '%s' Successfully\n", path);
//在文件夹中找DS18B20的文件夹28-xx
while ((direntp = readdir(dirp)) != NULL)
{
if (strstr(direntp->d_name, "28-") != NULL)
{
strncpy(dir_name, direntp->d_name, strlen(direntp->d_name));
printf("Find file: %s\n", dir_name);
found = 1;
break;
}
}
closedir(dirp);
//找不到该文件夹
if (found == -1)
{
printf("ERROR: Can not find DS18B20 in %s\n", path);
return -2;
}
2、拼接文件夹和文件名到path中
- ①、拼接文件夹和文件名到path中,得到一个完整的文件路径【绝对路径】
- “ /sys/bus/w1/devices/28-3c01e0761972/w1_slave ”
//将文件夹名和文件名分别拼接到path上
strncat(path, dir_name, strlen(dir_name));
strncat(path, "/w1\_slave", sizeof(path)-strlen(path));
3、打开w1_slave文件
- ①、上一步骤得到 w1_slave 文件的绝对路径后,便可使用系统调用函数 open() 直接打开文件w1_slave
- ②、因为只需要读该文件中的内容,所以我们以只读的形式(O_RDONLY)打开即可
- ③、打开成功后,便会返回一个指向该文件的文件描述符fd
- 在运行最终代码的时候,会看到 fd=3 ,是因为
- 操作系统默认会打开 0、1、2 这三个文件描述符
- 0:标准输入【默认是键盘】
- 1:标准输出【默认是屏幕】
- 2:标准出错【默认是屏幕】
- 而新建的文件描述符 fd,是当前可用的文件描述符中最小的非负整数,所以这里的 fd 为 3
//打开w1\_slave文件
if ((fd = open(path, O_RDONLY)) < 0)
{
printf("ERROR: Open file '%s' Failure: %s\n", path, strerror(errno));
return -3;
}
printf("Open file '%s' fd[%d] Successfully\n", path, fd);
4、读w1_slave文件
- ①、使用系统调用函数 read() 将 fd 所指向的文件的内容读到 buf 中,一次读 sizeof(buf) 字节大小
//从w1\_slave中读取内容
if ((rv = read(fd, buf, sizeof(buf))) < 0)
{
printf("ERROR: Read data from file '%s' Failure: %s\n", path, strerror(errno));
rv = -4;
goto cleanup;
}
printf("Read %dB data from file '%s'\n", rv, path);
5、匹配数据并计算、赋值
- ①、从 buf 中匹配 “t=”这个字符串,这时 strstr() 返回的是 “t” 所存放的地址
- ②、要想最终获得的地址是数据的地址,则需要将该地址向右移 2 位,这时的地址就是数据的首地址
- ③、这时候的数据还是字符串形式,我们使用 atof() 函数将数据转为double型,并/1000,即可得到正确的温度值了
//从buf里匹配"t=",并将ptr移到数据的首地址上
if ((ptr= strstr(buf, "t=") + 2) == NULL)
{
printf("ERROR: Find data Failure: %s", strerror(errno));
rv = -5;
goto cleanup;
}
//将数据转为double型,除1000得到正常的十进制温度
\*temp = atof(ptr)/1000;
三、具体代码
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int Get\_DS18B20\_Temp(double \*temp);
/\*
\* The main function
\*/
int main(int argc, char \*\*argv)
{
double temp;
if (Get\_DS18B20\_Temp(&temp) < 0)
{
printf("ERROR: DS18B20 Get Temperature Failure\n");


**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.youkuaiyun.com/topics/618679757)**
[外链图片转存中...(img-0qijtIAy-1715689398602)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.youkuaiyun.com/topics/618679757)**