国产risc-v微控制器读取BMP280
本帖最后由 dirtwillfly 于 2025-9-30 16:48 编辑第一部分:BMP280介绍
1.1 特性
BMP280是一种数字式气压传感器,在大气压力测量、气象观测、高度测量、室内外温度、湿度、气压等方面有着广泛应用。 BMP280采用了半导体技术,可以测量气体的压力,并将结果转化为数字信号,具有高精度、低功耗、小尺寸等特点。 BMP280常用于智能手机、平板电脑、手表、健康监测器等移动设备中,可以提供气压、海拔、气温、湿度等多项数据,帮助用户获取当前环境的气象信息,提高生活质量。
1.2 关键参数
测量参数:
• 气压:测量范围 300 hPa ~ 1100 hPa(相当于海拔 -500m ~ 9000m)。
• 温度:测量范围 -40°C ~ +85°C。
高精度:
• 气压精度:±0.12 hPa(相当于 ±1m 高度误差)。
• 温度精度:±1.0°C。
低功耗:
• 工作电流:2.7 μA(低功耗模式,1Hz 采样率)。
接口:
• 支持 I²C 和 SPI 通信协议,方便与微控制器连接。
1.3 模块原理图
模块在I2C模式下通过SDO引脚来确定器件地址,SDO接GND模块I2C地址为0x76,接高电平I2C地址为0x77.
原理图:
第二部分:应用开发
2.1 硬件连接
使用的HPM5361开发板P1接口有两组I2C接口,这里使用I2C0接口,即PB03和PB02引脚。
https://bbs.21ic.com/data/attachment/forum/202507/27/204618f5qsg8tj7s7t85mi.png.thumb.jpg
这两个引脚,在开发板上已经有了10K的上拉电阻,使用的BMP280上也有上拉电阻,这里可以共存,不需要特殊处理。
https://bbs.21ic.com/data/attachment/forum/202507/27/204903dwvkdk9wzklt1wxv.png.thumb.jpg
2.2 驱动代码
读寄存器:
int8_t bmp280_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint8_t len, const struct bmp280_dev *dev)
{
int8_t rslt;
rslt = null_ptr_check(dev);
if ((rslt == BMP280_OK) && (reg_data != NULL))
{
/* Mask the register address' MSB if interface selected is SPI */
if (dev->intf == BMP280_SPI_INTF)
{
reg_addr = reg_addr | 0x80;
}
rslt = dev->read(dev->dev_id, reg_addr, reg_data, len);
/* Check for communication error and mask with an internal error code */
if (rslt != BMP280_OK)
{
rslt = BMP280_E_COMM_FAIL;
}
}
else
{
rslt = BMP280_E_NULL_PTR;
}
return rslt;
}
设置寄存器:
int8_t bmp280_set_regs(uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len, const struct bmp280_dev *dev)
{
int8_t rslt;
uint8_t temp_buff; /* Typically not to write more than 4 registers */
uint16_t temp_len;
uint8_t reg_addr_cnt;
if (len > 4)
{
len = 4;
}
rslt = null_ptr_check(dev);
if ((rslt == BMP280_OK) && (reg_addr != NULL) && (reg_data != NULL))
{
if (len != 0)
{
temp_buff = reg_data;
/* Mask the register address' MSB if interface selected is SPI */
if (dev->intf == BMP280_SPI_INTF)
{
/* Converting all the reg address into proper SPI write address
* i.e making MSB(R/`W) bit 0
*/
for (reg_addr_cnt = 0; reg_addr_cnt < len; reg_addr_cnt++)
{
reg_addr = reg_addr & 0x7F;
}
}
/* Burst write mode */
if (len > 1)
{
/* Interleave register address w.r.t data for burst write*/
interleave_data(reg_addr, temp_buff, reg_data, len);
temp_len = ((len * 2) - 1);
}
else
{
temp_len = len;
}
rslt = dev->write(dev->dev_id, reg_addr, temp_buff, temp_len);
/* Check for communication error and mask with an internal error code */
if (rslt != BMP280_OK)
{
rslt = BMP280_E_COMM_FAIL;
}
}
else
{
rslt = BMP280_E_INVALID_LEN;
}
}
else
{
rslt = BMP280_E_NULL_PTR;
}
return rslt;
}
软复位:
int8_t bmp280_soft_reset(const struct bmp280_dev *dev)
{
int8_t rslt;
uint8_t reg_addr = BMP280_SOFT_RESET_ADDR;
uint8_t soft_rst_cmd = BMP280_SOFT_RESET_CMD;
rslt = null_ptr_check(dev);
if (rslt == BMP280_OK)
{
rslt = bmp280_set_regs(®_addr, &soft_rst_cmd, 1, dev);
/* As per the datasheet, startup time is 2 ms. */
dev->delay_ms(2);
}
return rslt;
}
硬件初始化:
int8_t bmp280_init(struct bmp280_dev *dev)
{
int8_t rslt;
/* Maximum number of tries before timeout */
uint8_t try_count = 5;
rslt = null_ptr_check(dev);
if (rslt == BMP280_OK)
{
while (try_count)
{
rslt = bmp280_get_regs(BMP280_CHIP_ID_ADDR, &dev->chip_id, 1, dev);
/* Check for chip id validity */
if ((rslt == BMP280_OK) &&
(dev->chip_id == BMP280_CHIP_ID1 || dev->chip_id == BMP280_CHIP_ID2 || dev->chip_id == BMP280_CHIP_ID3))
{
rslt = bmp280_soft_reset(dev);
if (rslt == BMP280_OK)
{
rslt = get_calib_param(dev);
}
break;
}
/* Wait for 10 ms */
dev->delay_ms(10);
--try_count;
}
/* Chip id check failed, and timed out */
if (!try_count)
{
rslt = BMP280_E_DEV_NOT_FOUND;
}
if (rslt == BMP280_OK)
{
/* Set values to default */
dev->conf.filter = BMP280_FILTER_OFF;
dev->conf.os_pres = BMP280_OS_NONE;
dev->conf.os_temp = BMP280_OS_NONE;
dev->conf.odr = BMP280_ODR_0_5_MS;
dev->conf.spi3w_en = BMP280_SPI3_WIRE_DISABLE;
}
}
return rslt;
}获取配置:
int8_t bmp280_get_config(struct bmp280_config *conf, struct bmp280_dev *dev)
{
int8_t rslt;
uint8_t temp = { 0, 0 };
rslt = null_ptr_check(dev);
if ((rslt == BMP280_OK) && (conf != NULL))
{
rslt = bmp280_get_regs(BMP280_CTRL_MEAS_ADDR, temp, 2, dev);
if (rslt == BMP280_OK)
{
conf->os_temp = BMP280_GET_BITS(BMP280_OS_TEMP, temp);
conf->os_pres = BMP280_GET_BITS(BMP280_OS_PRES, temp);
conf->odr = BMP280_GET_BITS(BMP280_STANDBY_DURN, temp);
conf->filter = BMP280_GET_BITS(BMP280_FILTER, temp);
conf->spi3w_en = BMP280_GET_BITS_POS_0(BMP280_SPI3_ENABLE, temp);
dev->conf = *conf;
}
}
else
{
rslt = BMP280_E_NULL_PTR;
}
return rslt;
}获取状态:
int8_t bmp280_get_status(struct bmp280_status *status, const struct bmp280_dev *dev)
{
int8_t rslt;
uint8_t temp;
rslt = null_ptr_check(dev);
if ((rslt == BMP280_OK) && (status != NULL))
{
rslt = bmp280_get_regs(BMP280_STATUS_ADDR, &temp, 1, dev);
status->measuring = BMP280_GET_BITS(BMP280_STATUS_MEAS, temp);
status->im_update = BMP280_GET_BITS_POS_0(BMP280_STATUS_IM_UPDATE, temp);
}
else
{
rslt = BMP280_E_NULL_PTR;
}
return rslt;
}获取电源模式
int8_t bmp280_get_power_mode(uint8_t *mode, const struct bmp280_dev *dev)
{
int8_t rslt;
uint8_t temp;
rslt = null_ptr_check(dev);
if ((rslt == BMP280_OK) && (mode != NULL))
{
rslt = bmp280_get_regs(BMP280_CTRL_MEAS_ADDR, &temp, 1, dev);
*mode = BMP280_GET_BITS_POS_0(BMP280_POWER_MODE, temp);
}
else
{
rslt = BMP280_E_NULL_PTR;
}
return rslt;
}设置电源模式:
int8_t bmp280_set_power_mode(uint8_t mode, struct bmp280_dev *dev)
{
int8_t rslt;
rslt = null_ptr_check(dev);
if (rslt == BMP280_OK)
{
rslt = conf_sensor(mode, &dev->conf, dev);
}
return rslt;
}获取原始数据:
int8_t bmp280_get_uncomp_data(struct bmp280_uncomp_data *uncomp_data, const struct bmp280_dev *dev)
{
int8_t rslt;
uint8_t temp = { 0 };
rslt = null_ptr_check(dev);
if ((rslt == BMP280_OK) && (uncomp_data != NULL))
{
rslt = bmp280_get_regs(BMP280_PRES_MSB_ADDR, temp, 6, dev);
if (rslt == BMP280_OK)
{
uncomp_data->uncomp_press =
(int32_t) ((((uint32_t) (temp)) << 12) | (((uint32_t) (temp)) << 4) | ((uint32_t) temp >> 4));
uncomp_data->uncomp_temp =
(int32_t) ((((int32_t) (temp)) << 12) | (((int32_t) (temp)) << 4) | (((int32_t) (temp)) >> 4));
rslt = st_check_boundaries((int32_t)uncomp_data->uncomp_temp, (int32_t)uncomp_data->uncomp_press);
}
else
{
rslt = BMP280_E_UNCOMP_DATA_CALC;
}
}
else
{
rslt = BMP280_E_NULL_PTR;
}
return rslt;
}
很不错,在这个基础上修改下,就可以拿到项目上用的。比AI写的要靠谱多了
页:
[1]