我的毕业设计需要显示测量的温度、湿度、大气压数据,所以选用BME280传感器。这款传感器是基于I2C通信的,我们通过移植官方给的驱动库。这篇主要介绍整个移植过程,并没有理论方面的介绍。
整个工程文件我放到下面的链接里了,大家自取哈。
链接:https://pan.baidu.com/s/1aZyCO8cuZQ4eLKKC6_mGSQ
提取码:y1yo
一、驱动文件准备
1.我们在Github中一般都可以找到这三个驱动文件。
其中“bme280_defs.h”主要是定义bme280的寄存器的一些地址,“bme280.h”定义了一些初始化函数、功能实现函数,“bme280.c”是这些函数的实现,需要将这三个文件添加到工程中。
2.在工程里还提供的工程里面还有一个自检文件。
这个文件的目的是为了在初始化的时候确定BME280是否可以正常工作,如果通过自检,那么下面就可以开始读取数据并进行处理了。当然在这个工程中,我并没有使用这个函数,大家如果想先让传感器自检再进行工作可以使用这个函数。
二、STM32CubeMX配置
1.在“SYS”模块中,我们设置为“SW”;
2. 在“RCC”中,我们选择最后一个即可;
对于三种的区别请参考:https://www.cnblogs.com/niu-li/p/11172052.html
3.因为BME280传感器是依靠I2C来实现的,我们需要开一路I2C,其余默认即可;
4. 我们需要开一路串口,来将读取到的数据打印在串口调试助手中;
5.下面我们来配置时钟树,一定要检查自己的外部晶振是多少,需要跟自己的硬件保持一致的;
6. 我们将整个文件保存在相应的文件夹中即可;
7.我们需要选择想生成怎么的工程文件,然后点击右上角的生成工程文件即可。
三、Keil代码介绍
1.我们先需要重定向、串口,在“main.c”文件中添加以下代码:
#include "stdio.h"
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
//具体哪个串口可以更改huart1为其它串口
HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1 , 0xffff);
return ch;
}
2.我们需要将那3个文件拷贝到工程中:
3.因想用硬件I2C来实现,所以需要修改一下“i2c.c”文件:
void user_delay_ms(uint32_t period)
{
HAL_Delay(period);
}
int8_t user_i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{
int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
HAL_StatusTypeDef status = HAL_OK;
status = HAL_I2C_Mem_Read(&hi2c2, dev_id<<1, reg_addr, I2C_MEMADD_SIZE_8BIT, reg_data, len, 0xffff);
if (status == HAL_OK)
{
rslt = 0;
}
else
{
rslt = -1;
}
return rslt;
}
int8_t user_i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{
int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
HAL_StatusTypeDef status = HAL_OK;
status = HAL_I2C_Mem_Write(&hi2c2, dev_id<<1, reg_addr, I2C_MEMADD_SIZE_8BIT, reg_data, len, 0xffff);
if (status == HAL_OK)
{
rslt = 0;
}
else
{
rslt = -1;
}
return rslt;
}
我们也需要在"i2c.h"文件中添加
void user_delay_ms(uint32_t period);
int8_t user_i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len);
int8_t user_i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len);
4.回到“main.c”文件中:
(1)定义两个结构体,一个为bme280,一个用来存储数据
struct bme280_dev dev;
struct bme280_data comp_data;
(2)初始化bme280:
int8_t rslt = BME280_OK;
dev.dev_id = BME280_I2C_ADDR_PRIM;
dev.intf = BME280_I2C_INTF;
dev.read = user_i2c_read; //利用硬件I2C模式来读取数据
dev.write = user_i2c_write;
dev.delay_ms = user_delay_ms;
rslt = bme280_init(&dev);
(3)读取函数:
int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev)
{
uint8_t settings_sel;
/* Recommended mode of operation: Indoor navigation */
dev->settings.osr_h = BME280_OVERSAMPLING_1X;
dev->settings.osr_p = BME280_OVERSAMPLING_16X;
dev->settings.osr_t = BME280_OVERSAMPLING_2X;
dev->settings.filter = BME280_FILTER_COEFF_16;
settings_sel = BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL | BME280_OSR_HUM_SEL | BME280_FILTER_SEL;
bme280_set_sensor_settings(settings_sel, dev);
bme280_set_sensor_mode(BME280_FORCED_MODE, dev);
bme280_get_sensor_data(BME280_ALL, &comp_data, dev);
HAL_Delay(40);
printf("temperature:%0.2f*C pressure:%0.2fhPa humidity:%0.2f%%\r\n",comp_data.temperature, comp_data.pressure/100, comp_data.humidity);
}
(4)在while循环中进行实时读取:
总结:
通过本次实验自己学会了1个I2C传感器设备的调试,从移植官方的驱动到数据读取!!!