BMP390大气压强传感器Arduino

最近从网上购买了一块BMP390L的大气压强传感器,从客服那里得到了一个驱动程序(和Arduino提供的Adafruit BMP3XX Lirary的驱动库程序差不多)。看了那些官方程序,动辄大几千行,想着能不能自己写一个驱动程序,精简一下。

先上我的代码。先声明一下,这个传感器真正的驱动代码仅有十几行,在你的电脑中可能会跑不起来,接下来我将详细地记录一下自己的改码的过程。

#include <Wire.h>

void setup() {
  Serial.begin(9600);
  delay(10);
  Wire.begin();

  int8_t data[4] = {0};
  data[0] = 0xb6;
  bmp3_set_regs(0x7e, data, 1, 0x77);  //reset
  data[0] = 0x03;
  bmp3_set_regs(0x1b, data, 1, 0x77);  //pwr_ctrl_settings
  data[0] = 0x09; data[1] = 0x1d; data[2] = 0x01; data[3] = 0x04; 
  bmp3_set_regs(0x1c, data, 4, 0x77);  //odr_filter_settings
  data[0] = 0x62;
  bmp3_set_regs(0x19, data, 1, 0x77);  //int_ctrl_settings
  data[0] = 0x33;
  bmp3_set_regs(0x1b, data, 1, 0x77);  //pwr_ctrl_settings
  delay(100);
}

void loop() {
    uint8_t data[4] = {0}; 
    bmp3_get_regs(0x03, data, 4, 0x77);

    uint32_t pdata = ((uint32_t)data[3] << 16) | ((uint32_t)data[2] << 8) | (uint32_t)data[1];
    Serial.println(pdata);
    delay(5000);
}

/***************************************************************************************************************
I2C
****************************************************************************************************************/
int8_t bmp3_get_regs(uint8_t reg, uint8_t *read_data, uint32_t len, int8_t intf_ptr)
{
    uint8_t dev_addr = intf_ptr;
    uint8_t count = 0;
    Wire.beginTransmission(dev_addr);
    Wire.write(reg);
    Wire.endTransmission();
    delay(15);
    Wire.requestFrom(dev_addr, len);

    while (Wire.available())
    {
        read_data[count++] = Wire.read();
    }
    return 0;
}

int8_t bmp3_set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, int8_t intf_ptr)
{
    uint8_t dev_addr = intf_ptr;
    Wire.beginTransmission(dev_addr);
    Wire.write(reg_addr);
    for (size_t i = 0; i < length; i++)
    {
        Wire.write(reg_data[i]);
    }
    Wire.endTransmission();
    return 0;
}

  • 官方驱动的分析

这个官方程序有六个文件,总工大约五千行的代码。这六个文件的关系如图所示:

第一层的bmp3xx_test.ino是Arduino的用户应用接口,用户只要把BMP390连接到Arduino开发板的IIC接口(SCL接在A5,SDA接在A4),就可以源源不断地获取到传感器中获得的大气压强了。

进入第二层的是rtobot_bmp3.h和rtobot_bmp3.cpp,这两个文件时负责开发板和传感器之间通讯的驱动(硬件驱动接口)。在这里生成一个BMP3的对象(指软件部分,就是后面第三层的传感器驱动程序),Arduino开发板把这个传感器驱动程序保存在“硬盘”中,并把它当成一个可以操作的虚拟对象。同时启动了开发板的IIC接口,用于连接传感器,并与传感器进行数据交换。

最后进入的第三层有三个文件,这些文件是用C语言写的,是真正的BMP390传感器驱动程序(官方的这个程序采用C语言,应该是为了能移植到各种平台来考虑的吧,比如把传感器用于ESP8266、STM32、51系列等等,甚至是Python,主打一个通用性、普适性)。

我花了三天的时间对这个C语言驱动程序进行阅读理解,因为之前没有正经地学过C,里面又涉及到内存、堆栈等操作,愣是没有全部弄懂,只是了解了一下大致的工作原理:

这个BMP390传感器的驱动方法,与其他大多数的传感器驱动相似,在传感器上电之后,就进行了一系列的初始化,模块的初始化是Arduino开发板通过IIC连线,往模块中的一些特殊地址的内存,写入指定的值。初始化完成后,模块就能源源不断地测量出大气压强,并写入到指定地址的内存中(保存测量结果的内存地址是0x04—0x09,一共是六个,前面三个是气压的值,后面三个是温度的值。三个数据中地位在前,高位在后)。这时候,Arduino开发板只要通过IIC读取这六个的数值,就能获得相关的数据了。

  • 获取IIC传输的数据

也就是说,我们只要知道BMP390初始化时,究竟往哪些特殊地址的内存,写入了哪些初始值,就能完成模块的初始化工作。这就是解读官方程序,实现自己的程序改写的意义。

我花了三天的时间,对这个官方程序的代码进行阅读理解,尝试读懂初始化程序中的算法,但是由于这个程序过于庞大,又是纯粹的C语言写的,和Arduino中的C又有所不同,一些内存操作的代码表达方式也不一样。因此这个程序的阅读一直没有读懂。

接着我想到了一个办法,要不到网上去借鉴一下别人写的程序,发现优快云上确实有人发过BMP390的基于STM32开发板的程序,于是直接抄袭别人的初始化数据,把这些数据写入BMP390中,结果发现模块不能够正常工作了。其实也是可以理解的,我们不怀疑别人的程序,那个程序在作者的电脑里面一定是能正常跑起来的,但是由于我们买的BMP390和作者的不是同一厂家同一批次的,初始化的数值也会不同,所以这个程序能适用于作者买的模块,却不适合你买的,所以就不能正常了。这也是我在文章开头的时候就说了,这个代码对于我买的模块能跑起来,但对于你买的模块,很大概率是会出问题的。

最后,我想到了一个“截胡”的办法。在Arduino开发板重启的时候,会运行初始化程序,通过IIC的端口,往BMP390的一些特殊地址,写入一些初始数值,如果我们能在IIC发送数据的时候,把这些数据截获,这样我们不就能知道了吗?

于是我在rtrobot_bmp3.cpp这个文件中,找到了IIC的读写代码模块,然后在这个IIC的写模块中,增加了一行代码,把Arduino开发板通过IIC端口发送给BMP390的初始化数据,再次用串口打印的方法,拷贝一份发送给电脑,这样,我们就可以在电脑中,获得了初始化的数据了。经过电脑的串口接收,知道了初始化的过程是:

往地址0x7e写入数值0xb6(这个是模块初始化RESET);

往地址0x1b写入数值0x03(这个是电源模式pwr_ctrl_settings);

往地址0x1c—0x1f连续写入数值0x09、0x1d、0x01、0x04四个数值(这个是运行参数设置odr_filter_settings);

往地址0x19写入数值0x62(这个是模块中断设置int_ctrl_settings);

往地址0x1b写入数值0x33(这个是更新电源模式pwr_ctrl_settings);

    这样我们在自己的驱动程序中,只要按顺序写入响应的数据,就能完成模块初始化。然后我们就可以从0x04地址开始,读取六个数据,这写数据就是大气压强和空气温度的数据了。这样我们仅用十几行的代码,就能完成BMP390模块的驱动了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tongyue

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值