BME280简介
BME280连接睿莓1
将BME280模块的SDA接PIN3,SCL接PIN5,VCC接3V3,GND接GND

使用命令
i2cdetect -y 1
该命令查看在I2C1上挂载的设备,可以查询到BME280的地址:0x76

编写读取程序
我的程序是基于开源仓库修改、实现接口而来的。仓库地址:https://github.com/libdriver/bme280
编写bme280.c
#include <stdio.h>
#include <stdlib.h>
#include "driver_bme280.h"
#include "driver_bme280_interface.h"
#include "driver_bme280_basic.h"
int main()
{
uint8_t res;
float temperature_c;
float pressure_pa;
float humidity_percentage;
res = bme280_basic_init(BME280_INTERFACE_IIC, BME280_ADDRESS_ADO_LOW);
if (res != 0)
{
return 1;
}
while (1)
{
bme280_interface_delay_ms(1000);
res = bme280_basic_read((float *)&temperature_c, (float *)&pressure_pa, (float *)&humidity_percentage);
if (res != 0)
{
(void)bme280_basic_deinit();
return 1;
}
bme280_interface_debug_print("bme280: temperature is %0.2fC.\n", temperature_c);
bme280_interface_debug_print("bme280: pressure is %0.2fPa.\n", pressure_pa);
bme280_interface_debug_print("bme280: humidity is %0.2f%%.\n", humidity_percentage);
}
exit(0);
}
完善driver_bme280_interface_template.c
#include "driver_bme280_interface.h"
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#ifndef BME280_I2C_DEV
#define BME280_I2C_DEV "/dev/i2c-1"
#endif
static int s_i2c_fd = -1;
uint8_t bme280_interface_iic_init(void)
{
if (s_i2c_fd >= 0)
{
return 0;
}
s_i2c_fd = open(BME280_I2C_DEV, O_RDWR);
if (s_i2c_fd < 0)
{
bme280_interface_debug_print("bme280 iic init: open %s failed: %s\n",
BME280_I2C_DEV, strerror(errno));
return 1;
}
return 0;
}
uint8_t bme280_interface_iic_deinit(void)
{
if (s_i2c_fd >= 0)
{
if (close(s_i2c_fd) < 0)
{
bme280_interface_debug_print("bme280 iic deinit: close failed: %s\n",
strerror(errno));
s_i2c_fd = -1;
return 1;
}
s_i2c_fd = -1;
}
return 0;
}
uint8_t bme280_interface_iic_read(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len)
{
if (s_i2c_fd < 0)
{
bme280_interface_debug_print("bme280 iic read: bus not init.\n");
return 1;
}
if (buf == NULL || len == 0)
{
bme280_interface_debug_print("bme280 iic read: invalid param.\n");
return 1;
}
addr >>= 1;
if (ioctl(s_i2c_fd, I2C_SLAVE, addr) < 0)
{
bme280_interface_debug_print("bme280 iic read: set slave 0x%02X failed: %s\n", addr, strerror(errno));
return 1;
}
struct i2c_rdwr_ioctl_data ioctl_data;
struct i2c_msg msgs[2];
uint8_t reg_buf = reg;
msgs[0].addr = addr;
msgs[0].flags = 0;
msgs[0].len = 1;
msgs[0].buf = ®_buf;
msgs[1].addr = addr;
msgs[1].flags = I2C_M_RD;
msgs[1].len = len;
msgs[1].buf = buf;
ioctl_data.msgs = msgs;
ioctl_data.nmsgs = 2;
if (ioctl(s_i2c_fd, I2C_RDWR, &ioctl_data) < 0)
{
bme280_interface_debug_print("bme280 iic read: ioctl I2C_RDWR failed: %s\n", strerror(errno));
return 1;
}
return 0;
}
uint8_t bme280_interface_iic_write(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len)
{
if (s_i2c_fd < 0)
{
bme280_interface_debug_print("bme280 iic write: bus not init.\n");
return 1;
}
if (len == 0)
{
bme280_interface_debug_print("bme280 iic write: length 0.\n");
return 1;
}
uint8_t addr7 = addr >> 1;
if (ioctl(s_i2c_fd, I2C_SLAVE, addr7) < 0)
{
bme280_interface_debug_print("bme280 iic write: set slave 0x%02X (from 0x%02X) failed: %s\n", addr7, addr, strerror(errno));
return 1;
}
struct i2c_rdwr_ioctl_data ioctl_data;
struct i2c_msg msg;
uint8_t tx[len + 1];
tx[0] = reg;
memcpy(&tx[1], buf, len);
msg.addr = addr7;
msg.flags = 0;
msg.len = len + 1;
msg.buf = tx;
ioctl_data.msgs = &msg;
ioctl_data.nmsgs = 1;
if (ioctl(s_i2c_fd, I2C_RDWR, &ioctl_data) < 0)
{
bme280_interface_debug_print("bme280 iic write: ioctl I2C_RDWR failed: %s\n", strerror(errno));
return 1;
}
return 0;
}
uint8_t bme280_interface_spi_init(void)
{
return 1;
}
uint8_t bme280_interface_spi_deinit(void)
{
return 1;
}
uint8_t bme280_interface_spi_read(uint8_t reg, uint8_t *buf, uint16_t len)
{
return 1;
}
uint8_t bme280_interface_spi_write(uint8_t reg, uint8_t *buf, uint16_t len)
{
return 1;
}
void bme280_interface_delay_ms(uint32_t ms)
{
while (ms)
{
unsigned int slice = (ms > 1000U) ? 1000U : (unsigned int)ms;
usleep(slice * 1000U);
ms -= slice;
}
}
void bme280_interface_debug_print(const char *const fmt, ...)
{
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
编写Makefile
CC = gcc
CFLAGS = -Wall -O2
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
TARGET = bme280_demo
$(TARGET): $(OBJS)
$(CC) -o $@ $^
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
.PHONY: clean
clean:
rm -f $(OBJS) $(TARGET)
编译+运行
使用make命令
make
编译成功,结果如下所示

运行程序
./bme280_demo
