树莓派
DS18B20
简要介绍项目实施情况
代码示例
基本API介绍及其详解
运行结果
-
树莓派
Raspberry Pi(中文叫树莓派,简写为RPi,(或者RasPi / RPI)[1]它是为学习计算机编程教育而设计的),只有基于信用卡大小的微型计算机。Linux。随着Windows 10 IoT我们也可以使用发布的操作Windows的树莓派。自问世以来,受到众多计算机爱好者和制造商的追捧,一度难以找到派。虽然外表娇小,内心心却很强大,视频、音频等功能都有,可谓麻雀虽小,五脏俱全。
-
DS18B20
DS18B20是一种常用的数字温度传感器,输出数字信号,体积小,硬件成本低,抗干扰能力强,精度高。[1]DS18B20数字温度传感器接线方便,包装后可应用于管道、螺纹、磁铁吸附、不锈钢包装、各种型号LTM8877,LTM8874等等。
它的外观主要根据不同的应用场合而变化。DS18B20可用于各种非极限温度场合,如电缆沟测温、高炉水循环测温、锅炉测温、机房测温、农业温室测温、洁净室测温、弹药库测温等。耐磨耐碰,体积小,使用方便,包装形式多样,适用于各种狭小空间设备的数字测温和控制。
-
项目实现的简单介绍
-
由于DS18B遵循单线协议(oneline),1-wire 单总线是Maxim 全资子公司 Dallas 专有技术。数据通信多数标准串行数据通信,如SPI/I2C/MICROWIRE 不同的是,它使用单个信号线来传输时钟和数据,数据传输是双向的。它具有节省 I/O 口线资源、结构简单、成本低、总线扩展维护方便等优点。1-wire 单总线适用于单个主机系统,可控制一个或多个从机设备。当只有一个从机位于总线时,系统可以按照单节点系统操作;当多个从机位于总线时,系统按照多节点系统操作。
-
为什么要用文件?I/O实现温度获取?
因为DS18B0将他获得的温度数据存储在文件中,并且DS18B20会有一个类似我们身份证号的特殊产品序列号,所以我们会使用它strstr函数可以找到唯一的序列号,也可以找到唯一的文件,例如:strstr(direntp->d_name,"28-")。
废话不多说,先滚代码
-
代码示例
#ifndef __DS18B20_H__ #define __DS18B20_H__ #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <stdlib.h> #define BUF_SIZE 1024 #define CHIP_SIZE 100 #define DIR_PATH_SIZE 100 #endif int ds18b20_get_temperature(float *tmp);//基于DS18B20温度获取实现函数 int main (int argc, char **argv) { float value; if((ds18b20_get_temperature(&value))<0) { printf("Get temperature failure: %s\n",strerror(errno)); } printf("T = %.2f\n",value); return 0; } int ds18b20_get_temperature(float *tmp) { if(tmp == NULL) { printf("Failure : %s",strerror(errno)); return 0; } int fd = -1; int rv = 0; char buf[BUF_SIZE]; char chip[CHIP_SIZE]; char DIR_PATH[DIR_PATH_SIZE] ="/sys/bus/w1/devices/"; //DS18B文件的实时存储温度为20 char *ptr = NULL; int find = 0; DIR *dirp = NULL; struct dirent *direntp = NULL; if((dirp = opendir(DIR_PATH))==NULL) { printf("Open %s failure %s\n\a",DIR_PATH,strerror(errno)); return -1; } while((direntp= readdir(dirp))!=NULL) { if(strstr(direntp->d_name,"28-")) ///找字串 { memset(chip,0,sizeof(chip)); strncpy(chip,direntp->d_name,sizeof(chip)); find = 1; break; } } if(!find) { puts("No such devices\a"); goto cleanup; return -2; } closedir(dirp); strncat(DIR_PATH,chip,sizeof(DIR_PATH)); strncat(DIR_PATH,"/w1_slave",sizeof(DIR_PATH)); if((fd = open(DIR_PATH,O_RDONLY))<0) { printf("open %s failure %s\a\n",DIR_PATH,strerror(errno)); goto cleanup; return -3; } memset(buf,0,sizeof(buf)); lseek(fd,0,SEEK_SET); if((rv = read(fd,buf,sizeof(buf)))<0) { printf("Read %s failure %s\n\a"DIR_PATH,strerror(errno));
goto cleanup;
return -4;
}
ptr = strstr(buf,"t=")+2;
if(!ptr)
{
puts("Gte value failure\a\n");
return -5;
}
*tmp = atof(ptr)/1000; //字符串转化位float的数据
cleanup:
close(fd);
}
-
基本API介绍及其详解
- oepndir( )
#include <sys/types.h> #include <dirent.h> DIR *opendir(const char *name); //打开指定的文件目录
- readdir( )
#include <dirent.h> struct dirent *readdir(DIR *dirp); //read open 函数打开的目录文件
- strstr( )
#include <string.h> char *strstr(const char *haystack, const char *needle); 在haystack从查找needle的子串
- strcpy()
#include <string.h> void *memset(void *s, int c, size_t n); //将s的这段内存初始化位c值,我们一般把c值设为,最后n位这段内存的大小
-
strncpy/strcpy
#include <string.h> char *strcpy(char *dest, const char *src); //这个函数一般不安全,容易导致内存溢出 char *strncpy(char *dest, const char *src, size_t n); //这个函数有最后的字节数限制,不会导致内存溢出,
- closedir
#include <sys/types.h> #include <dirent.h> int closedir(DIR *dirp); //关闭打开的文件句柄
-
strncat
#include <string.h> char *strcat(char *dest, const char *src); //同样这个函数也不安全,存在内存溢出的问题 char *strncat(char *dest, const char *src, size_t n);//将dest连接在src之后,n的大小回限制内存溢出的问题
-
atof
#include <stdlib.h> double atof(const char *nptr); //将字符串转化为float
-
至于一些其他的进本系统调用函数大家可以看看我的这篇文章(https://blog.csdn.net/qq_44045338/article/details/104587274),我就不一一例举了。
-
运行结果