IGKBoard(imx6ull)-文件IO之DS18B20温度传感器采样


如果不了解DS18B20温度传感器的小伙伴可以看这篇文章,里面介绍了DS18B20的相关知识(功能结构,操作时序,代码实现等)

STM32一线协议-DS18B20温度传感器采样实现
这篇文章就介绍一下如何利用IGKBoard(imx6ull)开发板实现温度采样。

1- 硬件模块介绍以及连接说明

DS18B20传感器的工作电压范围为3~5.5v,所以其电源连接3.3v和5v都可以。这样DS18B20在与开发板相连时,主要连接如下三个引脚:

  • GND:该引脚要连到开发板的GND扩展引脚上;
  • VDD:该引脚要连到开发板的3.3v 或 5v 供电引脚上;
  • DQ:是DS18B20的数据通信引脚,该引脚应该连开发板上具有1-Wire 协议功能的GPIO引脚上;

在IGKBoard开发板上,提供了与树莓派兼容的 40Pin扩展引脚,其定义如下。
其中物理引脚#7 (GPIO1_IO18) 在Linux系统启动时如果启用了 w1 overlay 后,它将会默认作为 DS18B20 传感器的一线协议接口使用。这样,DS18B20的 DQ 引脚应该连接它上。
在这里插入图片描述

连接之后就是如下图所示:
在这里插入图片描述


2- 驱动配置使用说明

在前面,我们将DS18B20的DQ引脚连到了IGKBoard开发板扩展接口的 #7 引脚上(GPIO01_IO18),该引脚在系统启动时有可能默认作为GPIO功能使用。如果想作为DS18B20的通信引脚使用的话,我们需要修改开发板上的DTOverlay配置文件,添加该引脚的1-Wire 协议支持。

具体方法为修改 eMMC 启动介质的 boot 分区下的 config.txt文件,在 dtoverlay_extra 选项中添加 w1 支持即可。具体操作如下:

vi /run/media/mmcblk1p1/config.txt

在 dtoverlay_extra 选项中添加 w1 支持即可。没有直接新建,直接复制进去就可。

# Enable extra overlays
dtoverlay_extra=w1

修改完成后重启系统,系统启动时将会自动加载1-wire 协议驱动。待系统启动完成后,我们可以使用 dmesg 命令确认驱动是否成功加载。

root@igkboard:~# dmesg | grep 1-wire
[    1.819225] Driver for 1-wire Dallas network protocol.

3- 查看 DS18B20 温度传感器的相关文件

重启系统之后,我们应该可以在/sys/bus/w1/devices/路径下,看到 DS18B20 温度传感器的相关文件28-xxxxxx,事实上它是一个链接到其它文件夹的符号连接,我们暂时不关心。如下命令执行的结果所示,其中 0121a3a5758a 为现在所使用的DS18B20芯片的产品序列号。需要注意的是,板子上连接不同的DS18B20芯片这个值就不同。

root@igkboard:~# ls /sys/bus/w1/devices/
28-0121a3a5758a  w1_bus_master1

我们使用 ls 命令看看,这个文件夹下有哪些文件。
在这里,最重要的一个文件是 w1_slave 文件。当我们在Linux下开始读该文件时,它将触发Linux内核中的 DS18B20 驱动开始采样。在采样完成之后,Linux内核驱动将会把采样温度值写入到该文件中,这样我们读取该文件里的内容即可。

root@igkboard:/sys/bus/w1/devices/28-0121a3a5758a# ls
alarms     driver      ext_power  hwmon  name   resolution  temperature  w1_slave
conv_time  eeprom_cmd  features   id     power  subsystem   uevent

我们可以使用 cat 命令查看 w1_slave 文件里的内容,注意这里只能使用 cat 命令而不能使用 vim 命令查看,因为该文件是只读的。
另外在执行这个命令的时候,我们会发现执行 cat 命令之后,结果需要延时一会才会显示出来。这是因为,Linux内核在触发传感器采样,并等待采样完成、写入采样温度值到该文件中还需要一段时间。

root@igkboard:/sys/bus/w1/devices/28-0121a3a5758a# cat w1_slave 
09 01 55 00 7f ff 0c 10 a1 : crc=a1 YES
09 01 55 00 7f ff 0c 10 a1 t=16562

在上面的输出结果中:

  • crc=a1:它是DS18B20采样时传输数据的CRC校验和,主要用来校验传感器将采样数据发送给CPU时是否出错;
  • t=16562:后面的16562就是采样温度值,其中16是整数部分,562为小数部分,即本次采样温度为16.562℃。
    所以我们要获取温度的话,一般都是获取“t=”后面的数值,然后转换为小数显示出来。

4- 编写代码获取温度

(1)ds18b20获取温度代码

在前面我们知道,DS18B20采样后的温度值存放在 /sys/bus/w1/devices/28-0121a3a5758a/w1_slave 文件中,这里的28-0121a3a5758a 是DS18B20的产品序列号,不同的DS18B20芯片其序列号不同。所以在编写代码时,我们不能直接读这个路径的文件来获取温度,因为传感器或设备换了之后,我们的代码就不能工作了。

这样,我们在编程时就应该能够根据不同的芯片来动态获取这个文件路径。因为DS18B20的温度传感器文件总是在 /sys/bus/w1/devices/ 路径下,并且传感器文件夹名是以 “28-” 开头,所以我们可以通过打开文件夹 /sys/bus/w1/devices/ ,并在里面找到以 “28-” 开头的文件。然后再使用相应的字符串处理函数把它们组合成一个完整的路径: /sys/bus/w1/devices/28-xxxxxxxxxxxx/w1_slave

接下来,我们编写 DS18B20传感器采样获取温度的代码如下。

/*************************************************************************
    > File Name: ds18b20.c
    > Author: WangDengtao
    > Mail: 1799055460@qq.com 
    > Created Time: 2023年01月12日 星期一四15时25分51秒
 ************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
#include <time.h>
#include <errno.h>

int ds18b20_get_temperature(float *temp);/*获取温度的函数,返回负数失败,否则成功*/

int main(int argc, char *argv[])
{
    float       temp; /*温度*/
    
    if( ds18b20_get_temperature(&temp) < 0 )
    {
        printf("ERROR: ds18b20 get temprature failure\n");
        return 1;
    }

    printf("DS18B20 get temperature: %f 'C\n", temp);
    
    return 0;
}
/*获取温度的函数,传入&temp*/
int ds18b20_get_temperature(float *temp)
{
    const char     *w1_path = "/sys/bus/w1/devices/";
    char            ds_path[50]; /* DS18B20 采样文件路径 */
    char            chip[20];    /* DS18B20 芯片序列号文件名 */
    char            buf[128];    /* read() 读数据存储 buffer */
    DIR            *dirp;        /* opendir()打开的文件夹句柄 */
    struct dirent  *direntp;     /* readdir()读文件夹内容时的目录项*/
    int             fd =-1;      /* open()打开文件的文件描述符 */
    char           *ptr;         /* 一个字符指针,用来字符串处理 */
    int             found = 0;   /* 是否找到DS18B20的标志,默认设置为没找到(0) */
    int             rv = 0;      /* 函数返回值,默认设置为成功返回(0) */


    /* 进入函数的第一件事应该进行函数参数的合法性检测,检查参数非法输入。
     * 否则调用者"不小心"通过 $temp 传入一个空指针,下面的代码就有可能出现段错误。
     */
    if( !temp )
    {
        return -1;
    }
    
    /* 打开 "/sys/bus/w1/devices/" 文件夹,如果打开失败则打印错误信息并退出。 */
    if((dirp = opendir(w1_path)) == NULL)
    {
        printf("opendir error: %s\n", strerror(errno));
        return -2;
    }

    /* 
    使用while()循环读取/sys/bus/w1/devices/,使用 strstr() 函数判断文件名中是否包含 "28-",如果找到则将完整的文件名通过strcpy()函数保存到 chip 中;并设置 found 标志为1,跳出循环。
     */
    while((direntp = readdir(dirp)) != NULL)
    {
        if(strstr(direntp->d_name,"28-"))
        {
            strcpy(chip,direntp->d_name);
            found = 1;
            break;
        }
    }
    
    /* 文件夹打开用完后,要记得第一时间关闭 */
    closedir(dirp);
      
    /*found标记,本身为0,找到了就置为1,否则返回-3没找到*/
    if( !found )
    {   
        printf("Can not find ds18b20 in %s\n", w1_path);
        return -3;
    }    

    /* 使用snprintf()函数生成完整路径/sys/bus/w1/devices/28-xxxxx/w1_slave
     * 并保存到 ds_path 中。 
     */
    snprintf(ds_path, sizeof(ds_path), "%s/%s/w1_slave", w1_path, chip);

    /* 接下来打开 DS18B20 的采样文件,如果失败则返回相应的错误码-4。 */
    if( (fd=open(ds_path, O_RDONLY)) < 0 )
    {
        printf("open %s error: %s\n", ds_path, strerror(errno));
        return -4;
    }

    /* 读取文件中的内容将会触发 DS18B20温度传感器采样,这里读取文件内容保存到buf中 */
    if(read(fd, buf, sizeof(buf)) < 0)
    {
        printf("read %s error: %s\n", ds_path, strerror(errno));
        rv = -5;
        goto cleanup;
    }

    /* 采样温度值是在字符串"t="后面,这里我们从buf中找到"t="字符串的位置并保存到ptr指针中 */
    ptr = strstr(buf, "t=");
    if( !ptr )
    {
        printf("ERROR: Can not get temperature\n");
        rv = -6;
        goto cleanup;
    }

    /* 因为此时ptr是指向 "t="字符串的地址(即't'的地址),那跳过2个字节(t=)后面的就是采样温度值 */
    ptr+=2;

    /* 接下来我们使用 atof() 函数将采样温度值字符串形式,转化成 float 类型。*/
    *temp = atof(ptr)/1000;
    
cleanup: 
    close(fd);
    return rv;
}

在这里插入图片描述

(2)交叉编译运行代码

大家不了解交叉编译的可以查看这篇文章:交叉编译介绍以及测试讲解
我是在自己的虚拟机上编写的,编写好之后交叉编译。
在这里插入图片描述
编译好之后并且用file命令检查一下是否是ARM开发板Linux系统上运行的程序。
然后在我们的开发板上使用tftp命令将文件传过来运行:

root@igkboard:~# tftp -gr ds18b20 192.168.1.7
root@igkboard:~# chmod a+x ds18b20 
root@igkboard:~# ./ds18b20                   
DS18B20 get temperature: 17.000000 'C

可以看到获取到了温度。


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值