[RISC-V MCU 应用开发] 国产risc-v微控制器读取BMP280

[复制链接]
605|1
dirtwillfly 发表于 2025-9-28 14:04 | 显示全部楼层 |阅读模式
, , , ,
本帖最后由 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 模块原理图
4297868d8e476cb78d.png
模块在I2C模式下通过SDO引脚来确定器件地址,SDO接GND模块I2C地址为0x76,接高电平I2C地址为0x77.

原理图:

8952668d8e5723913e.png

第二部分:应用开发

2.1 硬件连接
使用的HPM5361开发板P1接口有两组I2C接口,这里使用I2C0接口,即PB03和PB02引脚。



这两个引脚,在开发板上已经有了10K的上拉电阻,使用的BMP280上也有上拉电阻,这里可以共存,不需要特殊处理。

2.2 驱动代码
读寄存器:
  1. int8_t bmp280_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint8_t len, const struct bmp280_dev *dev)
  2. {
  3.     int8_t rslt;

  4.     rslt = null_ptr_check(dev);
  5.     if ((rslt == BMP280_OK) && (reg_data != NULL))
  6.     {
  7.         /* Mask the register address' MSB if interface selected is SPI */
  8.         if (dev->intf == BMP280_SPI_INTF)
  9.         {
  10.             reg_addr = reg_addr | 0x80;
  11.         }
  12.         rslt = dev->read(dev->dev_id, reg_addr, reg_data, len);

  13.         /* Check for communication error and mask with an internal error code */
  14.         if (rslt != BMP280_OK)
  15.         {
  16.             rslt = BMP280_E_COMM_FAIL;
  17.         }
  18.     }
  19.     else
  20.     {
  21.         rslt = BMP280_E_NULL_PTR;
  22.     }

  23.     return rslt;
  24. }

设置寄存器:
  1. int8_t bmp280_set_regs(uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len, const struct bmp280_dev *dev)
  2. {
  3.     int8_t rslt;
  4.     uint8_t temp_buff[8]; /* Typically not to write more than 4 registers */
  5.     uint16_t temp_len;
  6.     uint8_t reg_addr_cnt;

  7.     if (len > 4)
  8.     {
  9.         len = 4;
  10.     }
  11.     rslt = null_ptr_check(dev);
  12.     if ((rslt == BMP280_OK) && (reg_addr != NULL) && (reg_data != NULL))
  13.     {
  14.         if (len != 0)
  15.         {
  16.             temp_buff[0] = reg_data[0];

  17.             /* Mask the register address' MSB if interface selected is SPI */
  18.             if (dev->intf == BMP280_SPI_INTF)
  19.             {
  20.                 /* Converting all the reg address into proper SPI write address
  21.                  * i.e making MSB(R/`W) bit 0
  22.                  */
  23.                 for (reg_addr_cnt = 0; reg_addr_cnt < len; reg_addr_cnt++)
  24.                 {
  25.                     reg_addr[reg_addr_cnt] = reg_addr[reg_addr_cnt] & 0x7F;
  26.                 }
  27.             }

  28.             /* Burst write mode */
  29.             if (len > 1)
  30.             {
  31.                 /* Interleave register address w.r.t data for burst write*/
  32.                 interleave_data(reg_addr, temp_buff, reg_data, len);
  33.                 temp_len = ((len * 2) - 1);
  34.             }
  35.             else
  36.             {
  37.                 temp_len = len;
  38.             }
  39.             rslt = dev->write(dev->dev_id, reg_addr[0], temp_buff, temp_len);

  40.             /* Check for communication error and mask with an internal error code */
  41.             if (rslt != BMP280_OK)
  42.             {
  43.                 rslt = BMP280_E_COMM_FAIL;
  44.             }
  45.         }
  46.         else
  47.         {
  48.             rslt = BMP280_E_INVALID_LEN;
  49.         }
  50.     }
  51.     else
  52.     {
  53.         rslt = BMP280_E_NULL_PTR;
  54.     }

  55.     return rslt;
  56. }

软复位:
  1. int8_t bmp280_soft_reset(const struct bmp280_dev *dev)
  2. {
  3.     int8_t rslt;
  4.     uint8_t reg_addr = BMP280_SOFT_RESET_ADDR;
  5.     uint8_t soft_rst_cmd = BMP280_SOFT_RESET_CMD;

  6.     rslt = null_ptr_check(dev);
  7.     if (rslt == BMP280_OK)
  8.     {
  9.         rslt = bmp280_set_regs(&reg_addr, &soft_rst_cmd, 1, dev);

  10.         /* As per the datasheet, startup time is 2 ms. */
  11.         dev->delay_ms(2);
  12.     }

  13.     return rslt;
  14. }

硬件初始化:
  1. int8_t bmp280_init(struct bmp280_dev *dev)
  2. {
  3.     int8_t rslt;

  4.     /* Maximum number of tries before timeout */
  5.     uint8_t try_count = 5;

  6.     rslt = null_ptr_check(dev);
  7.     if (rslt == BMP280_OK)
  8.     {
  9.         while (try_count)
  10.         {
  11.             rslt = bmp280_get_regs(BMP280_CHIP_ID_ADDR, &dev->chip_id, 1, dev);

  12.             /* Check for chip id validity */
  13.             if ((rslt == BMP280_OK) &&
  14.                 (dev->chip_id == BMP280_CHIP_ID1 || dev->chip_id == BMP280_CHIP_ID2 || dev->chip_id == BMP280_CHIP_ID3))
  15.             {
  16.                 rslt = bmp280_soft_reset(dev);
  17.                 if (rslt == BMP280_OK)
  18.                 {
  19.                     rslt = get_calib_param(dev);
  20.                 }
  21.                 break;
  22.             }

  23.             /* Wait for 10 ms */
  24.             dev->delay_ms(10);
  25.             --try_count;
  26.         }

  27.         /* Chip id check failed, and timed out */
  28.         if (!try_count)
  29.         {
  30.             rslt = BMP280_E_DEV_NOT_FOUND;
  31.         }
  32.         if (rslt == BMP280_OK)
  33.         {
  34.             /* Set values to default */
  35.             dev->conf.filter = BMP280_FILTER_OFF;
  36.             dev->conf.os_pres = BMP280_OS_NONE;
  37.             dev->conf.os_temp = BMP280_OS_NONE;
  38.             dev->conf.odr = BMP280_ODR_0_5_MS;
  39.             dev->conf.spi3w_en = BMP280_SPI3_WIRE_DISABLE;
  40.         }
  41.     }

  42.     return rslt;
  43. }
获取配置:
  1. int8_t bmp280_get_config(struct bmp280_config *conf, struct bmp280_dev *dev)
  2. {
  3.     int8_t rslt;
  4.     uint8_t temp[2] = { 0, 0 };

  5.     rslt = null_ptr_check(dev);
  6.     if ((rslt == BMP280_OK) && (conf != NULL))
  7.     {
  8.         rslt = bmp280_get_regs(BMP280_CTRL_MEAS_ADDR, temp, 2, dev);
  9.         if (rslt == BMP280_OK)
  10.         {
  11.             conf->os_temp = BMP280_GET_BITS(BMP280_OS_TEMP, temp[0]);
  12.             conf->os_pres = BMP280_GET_BITS(BMP280_OS_PRES, temp[0]);
  13.             conf->odr = BMP280_GET_BITS(BMP280_STANDBY_DURN, temp[1]);
  14.             conf->filter = BMP280_GET_BITS(BMP280_FILTER, temp[1]);
  15.             conf->spi3w_en = BMP280_GET_BITS_POS_0(BMP280_SPI3_ENABLE, temp[1]);
  16.             dev->conf = *conf;
  17.         }
  18.     }
  19.     else
  20.     {
  21.         rslt = BMP280_E_NULL_PTR;
  22.     }

  23.     return rslt;
  24. }
获取状态:
  1. int8_t bmp280_get_status(struct bmp280_status *status, const struct bmp280_dev *dev)
  2. {
  3.     int8_t rslt;
  4.     uint8_t temp;

  5.     rslt = null_ptr_check(dev);
  6.     if ((rslt == BMP280_OK) && (status != NULL))
  7.     {
  8.         rslt = bmp280_get_regs(BMP280_STATUS_ADDR, &temp, 1, dev);
  9.         status->measuring = BMP280_GET_BITS(BMP280_STATUS_MEAS, temp);
  10.         status->im_update = BMP280_GET_BITS_POS_0(BMP280_STATUS_IM_UPDATE, temp);
  11.     }
  12.     else
  13.     {
  14.         rslt = BMP280_E_NULL_PTR;
  15.     }

  16.     return rslt;
  17. }
获取电源模式
  1. int8_t bmp280_get_power_mode(uint8_t *mode, const struct bmp280_dev *dev)
  2. {
  3.     int8_t rslt;
  4.     uint8_t temp;

  5.     rslt = null_ptr_check(dev);
  6.     if ((rslt == BMP280_OK) && (mode != NULL))
  7.     {
  8.         rslt = bmp280_get_regs(BMP280_CTRL_MEAS_ADDR, &temp, 1, dev);
  9.         *mode = BMP280_GET_BITS_POS_0(BMP280_POWER_MODE, temp);
  10.     }
  11.     else
  12.     {
  13.         rslt = BMP280_E_NULL_PTR;
  14.     }

  15.     return rslt;
  16. }
设置电源模式:
  1. int8_t bmp280_set_power_mode(uint8_t mode, struct bmp280_dev *dev)
  2. {
  3.     int8_t rslt;

  4.     rslt = null_ptr_check(dev);
  5.     if (rslt == BMP280_OK)
  6.     {
  7.         rslt = conf_sensor(mode, &dev->conf, dev);
  8.     }

  9.     return rslt;
  10. }
获取原始数据:
  1. int8_t bmp280_get_uncomp_data(struct bmp280_uncomp_data *uncomp_data, const struct bmp280_dev *dev)
  2. {
  3.     int8_t rslt;
  4.     uint8_t temp[6] = { 0 };

  5.     rslt = null_ptr_check(dev);
  6.     if ((rslt == BMP280_OK) && (uncomp_data != NULL))
  7.     {
  8.         rslt = bmp280_get_regs(BMP280_PRES_MSB_ADDR, temp, 6, dev);
  9.         if (rslt == BMP280_OK)
  10.         {
  11.             uncomp_data->uncomp_press =
  12.                 (int32_t) ((((uint32_t) (temp[0])) << 12) | (((uint32_t) (temp[1])) << 4) | ((uint32_t) temp[2] >> 4));
  13.             uncomp_data->uncomp_temp =
  14.                 (int32_t) ((((int32_t) (temp[3])) << 12) | (((int32_t) (temp[4])) << 4) | (((int32_t) (temp[5])) >> 4));
  15.             rslt = st_check_boundaries((int32_t)uncomp_data->uncomp_temp, (int32_t)uncomp_data->uncomp_press);
  16.         }
  17.         else
  18.         {
  19.             rslt = BMP280_E_UNCOMP_DATA_CALC;
  20.         }
  21.     }
  22.     else
  23.     {
  24.         rslt = BMP280_E_NULL_PTR;
  25.     }

  26.     return rslt;
  27. }






桃乐丝 发表于 2025-10-4 12:00 | 显示全部楼层
很不错,在这个基础上修改下,就可以拿到项目上用的。比AI写的要靠谱多了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:欢迎进入TI MCU论坛      21ic TI技术交流1群:61549143(已满),  21ic TI技术交流2群:311421422 我的博客:http://blog.timcu.com/

1199

主题

35121

帖子

1122

粉丝
快速回复 在线客服 返回列表 返回顶部