一、DS18B20模块与树莓派的连接
二、使能内核一线协议驱动模块
该传输采用一线协议传输模式
配置内核启动后自动加载一线协议驱动
从上面结果可以看到,温度值为24.375℃
三、编程思路
在"/sys/bus/w1/devices/"下寻找是否有以"28-"开头的序列号,若有,将其和其下的"/w1_slave"放到之前定义的路径数组w1_path下,
再用文件操作函数打开文件获取温度。
四、C程序读取DS18B20温度源码
linlan@raspberrypi:~/ds18b20 $ vim ds18b20.c
/**********************************************************************
> File Name: ds18b20.c
> Author: linlan
> Created Time: Tue 18 Sep 2018 15:33:12 UTC
***********************************************************************/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <time.h>
#include <fcntl.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 temperature failure.\n");
return 1;
}
printf("Ds18b20 get temperature is %f\n",temp);
return 0;
}
int ds18b20_get_temperature(float * temp)
{
char buf[256];
char w1_path[200] = "/sys/bus/w1/devices/";
DIR * dirp;
char serial_number[100];
struct dirent * direntp;
char * p;
int fd = -1;
int found = 0;
float value;
if(!temp)
{
return -1;
}
if((dirp = opendir(w1_path)) == NULL)
{
printf("Opendir failure:%s.\n",strerror(errno));
return -2;
}
while((direntp = readdir(dirp)) != NULL)
{
if(strstr(direntp->d_name,"28-"))
{
strncpy (serial_number,direntp->d_name,sizeof(serial_number));
found = 1;
}
}
closedir(dirp);
if (!found)
{
printf("Can't find ds18b20 in %s.\n",w1_path);
return -3;
}
strncat(w1_path,serial_number,sizeof(w1_path));
strncat(w1_path,"/w1_slave",sizeof(w1_path));
if((fd = open(w1_path,O_RDONLY)) < 0)
{
printf("open %s error:%s\n",w1_path,strerror(errno));
return -4;
}
if((read(fd,buf,sizeof(buf)))< 0)
{
printf("read %s error:%s\n",w1_path,strerror(errno));
return -5;
}
p = strstr(buf,"t=");
if(!p)
{
printf("Can not get the temperature.\n");
return -6;
}
p = p+2;
*temp = atof(p)/1000;
return 0;
}
编译、连接、运行,结果显示
linlan@raspberrypi:~/ds18b20 $ gcc ds18b20.c -o ds18b20
linlan@raspberrypi:~/ds18b20 $ ./a.out
Ds18b20 get temperature is 24.625000
五、问题与解决方案
while((direntp = readdir(dirp)) != NULL)
{
if(strstr(direntp->d_name,"28-"))
{
strncpy (serial_number,direntp->d_name,sizeof(serial_number));
found = 1;
}
}
开始while语句使用的if语句,编译没有报错,但结果显示如图
原因:利用strstr找子串时,需要将文件遍历,所有目录中都查找一遍看是否有出现"-28"。
while和if的区别
while循环语句,可以执行多次,if是条件语句,只是单次执行。
while(表达式) 语句组; 计算表达式,若为真,执行语句,并重复该过程,直到为假时,执行下一条语句。
例如:while(k>0)i++;表示只要k>0,就执行i++;直到等到k<=0时,不执行i++;程序执行下面的语句。