目录
(一)项目简介
(二)代码以及调试
(三)总结
(一)项目简介
DS18B20是常用的数字温度传感器,其输出的是数字信号,具有体积小,硬件开销低,抗干扰能力强,精度高的特点,本次实验项目是依据树莓派对DS18B20 1线温度传感器的支持(一线协议),再通过编程实现温度的探测。
DQ 为数字信号输入/输出端;
GND 为电源地;
VCC 为外接供电电源输入端;
其中两者端口的连接方式如下:
树莓派 的 ground 端(pin 06脚)------------连接DS18B20的 GND的端口;
树莓派的 gpio 04 端(pin 07 脚)--------------连接DS18B20的 DQ的端口;
树莓派的 3.3V 端(pin 01脚)-------------连接DS18B20的 VCC端口;
(二)代码以及调试
1.通过SecurtCRT远程登录到树莓派服务器上,并找到该文件所在的位置,如下图在根目录下的w1_slave文件中:
先调用 open() , read() , close()三个基本的文件I/O函数进行文件内容的读取:
int main(int argc, char **argv)
{
int fd;
char buf[128];
fd=open("/sys/bus/w1/devices/28-041731f7c0ff/w1_slave",O_RDONLY);
memset(buf,0,sizeof(buf); //初始化buf的内存,避免结果出现多余的字符
read(fd,buf,sizeof(buf));
printf("buf: %s\n"buf);
close(fd);
}
运行结果如下:
2.如果想要过滤掉其他无关的字符,我们需要调用 strstr() 函数定位到“t="这个字符串,再利用printf()直接打印;因为温度位浮点数,为了读取方便我们需要调用atof()函数(a:ASCII码,to:转换,f: float类型)即:将字符串所对应的ASCII码转换成float类型。
代码优化结果如下:
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
int main(int argc, char **argv)
{
int fd;
char buf[128];
char *ptr;
float temp;
fd=open("/sys/bus/w1/devices/28-041731f7c0ff/w1_slave",O_RDONLY);
memset(buf,0,sizeof(buf);
read(fd,buf,sizeof(buf));
printf("buf: %s\n"buf);
ptr=strstr(buf,"t=");
if(!ptr)
{
printf("can not find t=string\n");
return -1;
}
ptr +=2;
printf("ptr= %s\n",ptr);
temp = atof(ptr)/1000;
printf("temperature: %f\n",temp);
close(fd);
}
运行结果如下:
3.实际上DS18b20芯片的序列号是不断改变的,但都是以“28-”开头,所以就需要进一步优化代码,利用strstr()函数来匹配“/sys/bus/w1/devices/”路径下含有“28-”的字符串,再利用strncat()函数拼接到该路径下,这样无论该芯片序列号如何变化都可以精确定位到相应的路径
最终代码如下:
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<errno.h>
#include<dirent.h>
#include<stdlib.h>
int main(int argc, char **argv)
{
int fd=-1;
char buf[128];
char *ptr = NULL;
float temp;
DIR *dirp=NULL;
struct dirent *direntp = NULL;
char w1_path[32]="/sys/bus/w1/devices/";
char chip_sn[32];
int found=0;
dirp=opendir(w1_path);
if(!dirp)
{
printf("open folder %s failure:%s\n",w1_path,strerror(errno));
return -1;
}
while(NULL!=(direntp=readdir(dirp)))
{
if(strstr(direntp->d_name,"28-"))
{
strncpy(chip_sn,direntp->d_name,sizeof(chip_sn));
found=1;
}
}
closedir(dirp);
if(!found)
{
printf("can not find ds18b20 chipset\n");
return -2;
}
strncat(w1_path,chip_sn,sizeof(w1_path)-strlen(w1_path));
strncat(w1_path,"w1_slave",sizeof(w1_path)-strlen(w1_path));
printf("w1_path:%s\n",w1_path);
fd=open("w1_path",O_RDONLY);
if(fd<0)
{
printf("open file failure: %s\n",strerror(errno));
return -3;
}
memset(buf,0,sizeof(buf));
if(read(fd,buf,sizeof(buf))<0);
{
printf("read data from fd=%d failure: %s\n",fd,strerror(errno));
return -4;
}
printf("buf: %s\n",buf);
ptr=strstr(buf,"t=");
if(!ptr)
{
printf("can not find t=string\n");
return -5;
}
ptr +=2;
printf("ptr= %s\n",ptr);
temp = atof(ptr)/1000;
printf("temperature: %f\n",temp);
close(fd);
return 0;
}
(三)总结
本次项目涉及到了一些对树莓派和DS18B20硬件知识的掌握,但主要考验的是对Linux下文件IO系统调用的理解,和一定的c语言编程能力,不到位的地方还请大家多多指教,希望我的总结能对大家有所帮助。
文章链接:https://blog.csdn.net/weixin_45930204/article/details/104583400
来源:CSDN
作者:嵌入式hys
链接:https://blog.csdn.net/weixin_45930204/article/details/104583400