陈拓 2020.09.22/2020.09.24
1. 概述
本文讲述树莓派用C语言程序采集温度传感器DS18B20数据,并存入SQLite和MySQL数据库。之前我们已经用Shell脚本程序实现了这些功能。
为顺利阅读本文,应先看后面参考文档中的相关内容。
《树莓派采集温度数据并存入数据库(Shell版)》树莓派采集温度数据并存入数据库(Shell版)_shell 读取 dth11 温湿度 到数据库-优快云博客
- 硬件连接和基本操作
细节请看参考文档《树莓派+温度传感器DS18B20》一文。
树莓派+温度传感器DS18B20_设备树dtb中 温度传感器-优快云博客
- 查看DS18B20序列号
每个传感器有一个唯一的序列号。
ls /sys/bus/w1/devices/
![]()
我的DS18B20温度传感器序列号是28-000004d6162f。下面我们通过序列号读传感器的温度值。
- 读温度值
cat /sys/bus/w1/devices/28-000004d6162f/w1_slave

第二行的t=23125就是当前的温度值,要換算成攝氏度,除以1000,即当前温度为23125/1000=23.125攝氏度。
2. 获取数据库编程头文件和链接库
我们的温度数据将写入SQLite和MySQL两个数据库,需要相应的文件。
2.1 SQLite头文件和库文件
在C语言编程时需要头文件sqlite3.h和动态链接库文件libsqlite3.so。
- 下载sqlite3.h
在编译时会用到sqlite3.h,可以到SQLite官网下载。

SQLite目前最新版本是3.33.0。
右击sqlite-autoconf-3330000.tar.gz(2.78 MiB),复制链接地址:
https://www.sqlite.org/2020/sqlite-autoconf-3330000.tar.gz
下载:
wget -c https://www.sqlite.org/2020/sqlite-autoconf-3330000.tar.gz

安装ca-certificates包:
sudo apt-get install -y ca-certificates
![]()
重新下载:sqlite-autoconf-3330000.tar.gz
![]()
解压缩:
tar zxvf sqlite-autoconf-3330000.tar.gz
复制sqlite3.h到当前目录:
cp sqlite-autoconf-3330000/sqlite3.h .
![]()
- 查看sqlite3动态链接库

![]()
libsqlite3.so.0是一个指向libsqlite3.so.0.8.6的软链接,也就是一个快捷方式。
- 再创建一个libsqlite3.so.0.8.6的软链接libsqlite3.so
sudo ln -s libsqlite3.so.0.8.6 /usr/lib/arm-linux-gnueabihf/libsqlite3.so

3.2 MySQL头文件和库文件
在C语言编程时需要头文件mysql.h和动态链接库文件libmariadbclient.so。
- 安装库文件
sudo apt-get install libmariadb-dev
![]()
- 查找mysql.h
sudo find / -name mysql.h

/usr/include/mariadb/mysql.h
- 查找libmariadbclient.so
sudo find / -name libmariadbclient.so
![]()
/usr/lib/arm-linux-gnueabihf/libmariadbclient.so
4. 编写C程序
在《树莓派采集温度数据并存入数据库(Shell版)》一文中我们用Shell程序实现了温度采样和数据存储功能,在本文中我们用C语言实现同样的功能。
4.1 创建数据库
- 进入工作目录
cd idata

在《树莓派安装使用数据库SQLite》一文中我们已经创建了SQLite的数据库文件:smarthome.db。
在《树莓派安装使用数据库MariaDB (MySQL)》一文中我们也已经创建了数据库smarthome。
read_data.sh是我们在《树莓派采集温度数据并存入数据库(Shell版)》一文中写的shell脚本程序。
4.2 写C程序
nano read_data.c
![]()
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include "sqlite3.h"
#include <mysql.h>
// 保存数据到SQLite数据库
int save_data_sqlite(char sql[]) {
sqlite3 *pdb = NULL; /*数据库连接指针*/
char *error_msg = 0; /*错误信息指针*/
int rc, return_value;
rc=sqlite3_open("smarthome.db",&pdb);
if(rc) {
fprintf(stderr , "can't open database: %s\n",sqlite3_errmsg(pdb));
return_value = -1;
} else {
// 插入或更新命令
rc = sqlite3_exec(pdb,sql,0,0,&error_msg); // sqlite3_exec()是sqlite3_ prepare(), sqlite3_step(), and sqlite3_finalize() 三个函数的一个封装,最好的方法是直接使用sqlite3_exec()。
if (rc == SQLITE_OK) {
//printf("Insert data OK! rc=%d\n", rc); //测试
return_value = 0;
} else {
//printf("Insert data Error! rc=%d\n", rc); //测试
return_value = -2;
}
}
sqlite3_close(pdb);
return return_value;
}
static inline void _mysql_check(MYSQL * con) {
fprintf(stderr, "%s\n", mysql_error(con));
mysql_close(con);
exit(EXIT_FAILURE);
}
// 保存数据到MySQL数据库
void save_data_mysql(char sql[]) {
int rc;
// 创建数据连接对象,需要和 mysql_close成对出现
MYSQL *con = mysql_init(NULL);
if (con == NULL) {
fprintf(stderr, "%s\n", mysql_error(con));
exit(EXIT_FAILURE);
}
// 创建TCP常连接对象
if (!mysql_real_connect(con, "127.0.0.1", "ct", "ct", "smarthome", 0, NULL, 0)) {
_mysql_check(con);
}
//puts("mariadb is connect and run succesed!");
// 插入或更新命令
rc = mysql_real_query(con, sql, strlen(sql));
if (0 != rc) {
_mysql_check(con);
}
mysql_close(con);
}
int main(int argc, char *argv[])
{
char itime[255];
char buf[128];
char path[64] = "/sys/bus/w1/devices/28-000004d6162f/w1_slave";
char *itemp;
float ftemp;
int fd = -1;
char sql[256];
char deviceid[10] = "temp001";
int ibattery_voltage = 3333;
// 设置时区
setenv("TZ", "GMT-8", 1);
while(1) {
// 取系统时间
time_t t = time( 0 );
strftime(itime, 255, "%Y-%m-%d %H:%M:%S", localtime(&t)); //format date and time.
printf("%s\n", itime);
// 读传感器数据
if((fd = open(path, O_RDONLY)) < 0) {
printf("Open temperature file error! Please check /sys/bus/w1/devices/28-00000xxxxxxx file! \n");
} else {
if(read(fd, buf, sizeof(buf)) < 0) {
printf("Read temperature error!\n");
} else {
itemp = strchr(buf,'t');
sscanf(itemp, "t=%s", itemp);
ftemp = atof(itemp)/1000;
printf(" temp=%3.2f°C\n", ftemp);
// 构造SQL语句
sprintf(sql, "INSERT INTO temperature(deviceid, time, battery_voltage, celsius_temp) VALUES('%s', '%s', %d, %f);", deviceid, itime, ibattery_voltage, ftemp);
puts(sql);
puts(" ");
// 保存数据到SQLite数据库
save_data_sqlite(sql);
// 保存数据到MySQL数据库
save_data_mysql(sql);
sleep(300); // 延时300秒
}
}
}
return 0;
}
数据同时写入SQLite和MySQL数据库,具体项目可根据情况取舍。
- 编译
gcc -I /usr/include/mariadb read_data.c -o read_data -lmariadbclient -lsqlite3

3.3 运行C程序
./read_data

3.4 查看数据库
- 查看SQLite数据库
具体操作请看《树莓派安装使用数据库SQLite》
树莓派安装使用数据库SQLite_树莓派 sqlite 客户端-优快云博客
查看最后一条数据:
select * from temperature where id=(select max(id) from temperature);
![]()
- 查看MySQL数据库
具体操作请看《树莓派安装使用数据库MariaDB (MySQL)》树莓派安装使用数据库MariaDB (MySQL)_树莓派5代 5数据库-优快云博客

参考文档
- 树莓派采集温度数据并存入数据库(Shell版) 树莓派采集温度数据并存入数据库(Shell版)_shell 读取 dth11 温湿度 到数据库-优快云博客
- 树莓派安装使用数据库SQLite 树莓派安装使用数据库SQLite_树莓派 sqlite 客户端-优快云博客
- 树莓派安装使用数据库MariaDB (MySQL) 树莓派安装使用数据库MariaDB (MySQL)_树莓派5代 5数据库-优快云博客
- 树莓派+温度传感器DS18B20 树莓派+温度传感器DS18B20_设备树dtb中 温度传感器-优快云博客
- ESP8266_SDK发送温度数据到阿里云 ESP8266_SDK发送温度数据到阿里云_单片机向阿里云发送json格式数据-优快云博客
- 树莓派系列教程14:单总线控制DS18B20 树莓派系列教程14:单总线控制DS18B20 - 树莓派入门教程 微雪课堂

本文介绍如何使用树莓派及C语言程序从DS18B20温度传感器采集数据,并将其存储到SQLite和MySQL数据库中。包括硬件连接、数据读取、数据库编程头文件和链接库的准备、C程序编写及编译运行等步骤。
1708






