title: STM32移植BNO055(各种单片机都适用)
date: 2020-07-26
tags:
categories: STM32学习记录


背景

听说BNO055很牛逼,买一个来摸一摸。集成了磁力计,不需要自己再去配置外围电路,并且9轴陀螺仪能比6轴获取更多的信息,数据的精度也会好得多,最最重要的,这个模块除了有详细的官方文档,博世还写了快速使用手册,这极大的方便了用户的使用,缩短了产品的设计周期,无疑是它在消费电子领域兴起的重要原因之一,总之50块的价格绝对不吃亏。

准备

首先BNO055肯定要有一片,虽然相对于传统的MPU6XXX要贵上不少,但是上面的特性我也说过了,用过的人都说好。

另外,STM32开发板,仿真器,串口模块这些就不多说了,并且我是默认你有基本的STM32开发能力的,

前导认识

这里我使用HAL库+CubeMX编程,标准库或者寄存器编程的原理都一样,甚至使用德州仪器和NXP的单片机,移植方法都是类似的,走一个流程就能正常调用官方的API进行快速的开发和应用。

这里主要参考两个BNO055的官方文档,一个是Data Sheet数据手册,另一个是User Guide用户快速上手,相当于极简版的数据手册,最重要的是附加了手把手教你用API的步骤,可谓非常贴心。

下面粘贴官方的介绍,以及这款传感器支持的模式:

BNO055 是一款封装系统(SiP)芯片,包括一个 3 轴 14 位加速计,一个 3 轴 16 位陀螺仪,一个 3 轴磁 力计,和一个运行 BSX3.0 FusionLib 软件的 32 位 Cortex M0 +微控制器。 除了可以访问单个传感器信号(如加速度,旋转和磁场强度)之外,传感器还总共提供了五种不同的传感 器融合模式。具体模式下表:

非融合就不多说了,都看得懂,由于这款芯片中集成了一个CortexM0+内核,这赋予了它低功耗的情况下还能快速处理融合并输出融合结果的能力,所以我们通常使用的都是它自带的融合模式,减轻了外部处理单元的处理压力,使它的应用领域更加广泛。

融合模式:

  • IMU 或惯性测量单元是加速度计和陀螺仪的融合

  • COMPASS 是加速度计和磁力计的融合,也被称为倾斜补偿指南针

  • M4G(陀螺仪磁体)是加速度计和磁力计的融合体,但输出数据类似于 IMU 模式,因此陀螺仪的限制在 这种模式下得到了补偿。

  • NDOF_FMC_OFF 是所有三种传感器(加速度计,陀螺仪和磁力计)的融合,从而提供了九自由度 (NDOF)。在此模式下,“FMC(快速磁性校准)”功能被禁用,因此传感器需要类似于“图 8 模式”的移动来 校准磁力计。

  • NDOF 也是所有三种传感器的融合,但启用了“FMC”功能。通过 启用此功能,快速移动(即使不完整的“数字 8 模式”)将完全校准磁力计。

上图中也可以看到这些融合模式会输出什么样的数据供我们使用。具体的数据融合方式可以参考数据手册,里面有很详细的说明。这里我只是演示一遍具体的应用,关于应用主要的参考是快速应用手册中的一遍步骤。

Go

首先当然是创建或者自己准备一份可以正常运行的单片机源代码,需要注意的是,这个程序应该至少可以运行I2C模块,不管是软件模拟的还是硬件外设,例如我的代码就是这样,当然不可能放全部,这是该有的部分:

  #include "main.h"#include "i2c.h"#include "usart.h"#include "gpio.h"MX_GPIO_Init();MX_I2C1_Init();MX_USART1_UART_Init();

下一步是下载官方的API源文件,地址:https://github.com/BoschSensortec/BNO055_driver,其实主要的东西就是两个头文件,那个C文件是演示如何使用的,我们用不到。下载后复制这两个头文件到自己的工程中,直接把官方文件夹copy到你的工程文件夹,便于管理就像下面这样:

然后我们就按照官方的指导走一遍:

  • 第1步不用多说,启动BNO055电源,之后如果不进行任何操作,就处于Config模式,不会输出数据,详见数据手册。

  • 第2步:创建BNO的句柄结构体,这个句柄将装载BNO055的各种配置数据。但是这个结构体类型的声明在头文件里,所以首先我们需要添加头文件,再按照说明声明句柄:

    #include "bno055.h"struct bno055_t myBNO;     //全局变量
    
  • 第3步:给这个控制块的结构体成员赋值,或者说传参更准确。这是最最关键的一步,这一步有问题的话一定会出玄学问题。我们进入结构体定义的地方看看:

    struct bno055_t
    {u8 chip_id; /**< chip_id of bno055 */u16 sw_rev_id; /**< software revision id of bno055 */u8 page_id; /**< page_id of bno055 */u8 accel_rev_id; /**< accel revision id of bno055 */u8 mag_rev_id; /**< mag revision id of bno055 */u8 gyro_rev_id; /**< gyro revision id of bno055 */u8 bl_rev_id; /**< boot loader revision id of bno055 */u8 dev_addr; /**< i2c device address of bno055 */BNO055_WR_FUNC_PTR; /**< bus write function pointer */BNO055_RD_FUNC_PTR; /**<bus read function pointer */void (*delay_msec)(BNO055_MDELAY_DATA_TYPE); /**< delay function pointer */
    };
    

    其实我们这一步是给最后三个成员进行配置,可以看到是三个宏,我们再转到宏定义的地方:

    /***************************************************************/
    /**\name    BUS READ AND WRITE FUNCTIONS           */
    /***************************************************************/
    #define BNO055_WR_FUNC_PTR       s8 (*bus_write) \(u8, u8, u8 *, u8)#define BNO055_BUS_WRITE_FUNC(dev_addr, reg_addr, reg_data, wr_len) \bus_write(dev_addr, reg_addr, reg_data, wr_len)#define BNO055_RD_FUNC_PTR       s8 \(*bus_read)(u8, u8, u8 *, u8)#define BNO055_BUS_READ_FUNC(dev_addr, reg_addr, reg_data, r_len) \bus_read(dev_addr, reg_addr, reg_data, r_len)#define BNO055_DELAY_RETURN_TYPE void#define BNO055_DELAY_PARAM_TYPES u32#define BNO055_DELAY_FUNC(delay_in_msec) \delay_func(delay_in_msec)
    

    从变量的简写就已经很清晰了吧,两个结构体成员是为了和用户的IIC读写函数进行对接的,应该传入用户IIC读写函数的地址,也就是函数名,我们已经有读写函数了,那就是HAL库的读写函数,但是这个读写函数是不符合要求的,参数的数量和意义与API需要的函数都有些出入,所以我们需要定义一个用户函数,用来对接用户函数和模块API。

    s8 BNO_read(u8 dev_addr,u8 reg_addr,u8 *reg_data,u8 wr_len)
    {HAL_StatusTypeDef ret;ret = HAL_I2C_Mem_Read(&hi2c1, dev_addr << 1, reg_addr, sizeof(reg_addr), reg_data, wr_len, 0xFF);return 0;
    }s8 BNO_write(u8 dev_addr,u8 reg_addr,u8 *reg_data,u8 wr_len)
    {HAL_StatusTypeDef ret;ret = HAL_I2C_Mem_Write(&hi2c1, dev_addr << 1, reg_addr, sizeof(reg_addr), reg_data, wr_len, 0xFF);return 0;
    }
    

    这个也很好理解,函数指针的类型必须和API指定的类型一致,剩下的就是把对应的参数填入HAL库的IIC读写函数,这里使用STM32平台进行移植的读者需要注意两点,第一点就是,写函数必须使用HAL_I2C_Mem_Write(),函数的作用是在阻塞状态下向器件写入大量数据,同理,读函数也需要HAL_I2C_Mem_Read(),而不是HAL库的主机读写模式:HAL_I2C_Master_Transmit和HAL_I2C_Master_Receive;第二点就是,STM32的HAL库的读写函数并不会自动移位,所以我们需要在器件地址上手动左移2位。然后就可以将函数指针传入API的初始化句柄了:

      myBNO.bus_read = BNO_read;                        //再main函数中进行myBNO.bus_write = BNO_write;myBNO.delay_msec = HAL_Delay;myBNO.dev_addr = BNO055_I2C_ADDR1;
    

    这里我直接把第4步一起做了。

  • 第4步,关于地址的头文件在bno055.h头文件中定义

    /* bno055 I2C Address */
    #define BNO055_I2C_ADDR1 (0x28)
    #define BNO055_I2C_ADDR2 (0x29)
    

    这里主要看模块的IIC_Arr引脚,如果拉低就是0x28的器件地址,拉高就是0x29。

  • 第5步,初始化配置

    bno055_init(&myBNO);
    
  • 第6步,自检并设置模式

      bno055_set_sys_rst(BNO055_BIT_ENABLE);HAL_Delay(700);bno055_set_operation_mode(BNO055_OPERATION_MODE_IMUPLUS);
    

    模式的宏定义也在头文件

  • 如果要读融合数据的角度,定义储存三轴角度的结构体,然后调用官方函数:

    while(1){bno055_get_gyro_calib_stat(&gyro_calib_status);if (gyro_calib_status == 3) {break;}HAL_Delay(500);HAL_UART_Transmit(&huart1, (uint8_t *)waiting, sizeof(waiting), 0xFF);}
    

    注意这个在main函数中,但是不在while(1)的死循环中,目的是判断获取是否成功。比如这里我要读取Gyro陀螺仪,那么就要等到设置完毕才可以继续。所以就有了这个判断过程。

  • 可以开始读取数据了:

      while (1){HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);s8 stat = bno055_convert_float_euler_hpr_deg(&buff); if (stat == BNO055_SUCCESS)                                 //接收成功{sprintf(temp, "%.1f, %.1f, %.1f\r\n", buff.h, buff.r, buff.p);HAL_UART_Transmit(&huart1, (uint8_t *)temp, sizeof(temp), 0xFF);}else        //接收失败{HAL_UART_Transmit(&huart1, (uint8_t *)error, sizeof(error), 0xFF);}//HAL_Delay(50);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
    }
    

总结

对于应用BNO055来说还是很简单的,主要是没有MPU6XXX那样的漂移,并且数据稳定,传输速度较快,自动融合,自带滤波,这些特性使它成为了现在比较优秀的民用陀螺仪传感器。

BNO55移植到STM32平台及其他单片机平台相关推荐

  1. 12864移植到STM32平台

    利用串口方式将原本51单片机上的串口程序移植到STM32上,调试了两天终于可以显示了 1. 排查IO的初始化是否有问题,在STM32平台上需要对IO口时钟使能,IO口模式配置,一些特殊的管脚还需要做特 ...

  2. U8G2库移植到STM32平台上

    U8G2库简介 U8g2是嵌入式设备的单色图形库,一句话简单明了.主要应用于嵌入式设备,包括我们常见的单片机: 建议先看这篇博客的介绍,写的比较好u8g2库的使用 这篇博客介绍了对于u8g2的使用,但 ...

  3. stm32 移植java_把Lua移植到stm32上,效果不错! (amoBBS 阿莫电子论坛)

    因为我们产品的需要满足不同行业需求,所以一直在寻找一个脚本语言,以便灵活配置. 前段时间还自己花时间去实现一个C语言解释器,看了一堆编译原理的东西,以及虚拟机等,头都搞大了,把基本功能实现了,但总是不 ...

  4. harmonyos能否移植到MCU,HarmonyOS(LiteOs_m) 官方例程移植到STM32初体验

    HarmonyOS(LiteOs_m) 官方例程移植到STM32初体验 硬件平台 基于正点原子战舰V3开发板 MCU:STM32F103ZET6 片上SRAM大小:64KBytes 片上FLASH大小 ...

  5. ucos移植到stm32上的中断小小改进

    uCosII移植到stm32上的文章和demo已经很多了,细节上建议大家可以看官方的移植文档( 当然是E文的).网上流传的各种移植版本基本都是基于官方的移植版本做了小改进.这些改进基本都限制在更适合自 ...

  6. 【STM32+ESP-12S连接腾讯云物联网开发平台 1】云平台的创建和AT固件烧录

    腾讯云物联网开发平台创建和ESP-12S的固件烧录 前言 一.腾讯云物联网开发平台的创建 1. 创建产品 2. 配置产品和创建设备 3. 设备三元组说明 二.ESP-12S固件烧录 1.固件获取 2. ...

  7. uc/OS-II操作系统移植:uc/OS-II移植到STM32流程(文章末尾附实例)

    一.实验目的 1.掌握在STM32上移植嵌入式实时操作系统uC/OS-II的方法 2.掌握在STM32上移植uC/OS-II的基本步骤 3.掌握uC/OS-II的文件OS_CPU.H编写 4.掌握uC ...

  8. 带你开发一个远程控制项目---->STM32+标准库+阿里云平台+传感器模块+远程显示。

    目录 本次实验项目: 下次实验项目: 本次项目视频结果/APP/实物展示 实物展示 APP展示 视频展示 模块选择说明; 温湿度传感器模块介绍 光照传感器介绍 ESP8266-01S模块介绍 本次实验 ...

  9. Basic脚本解释器移植到STM32

    上次讲了LUA移植到STM32,这次讲讲Basic脚本解释器移植到STM32.在STM32上跑Basic脚本,同样可以跟穿戴设备结合,也可以作为初学者学习MCU的入门工具,当然前提是有人做好Basic ...

最新文章

  1. RandomForestClassifier参数min_samples_leaf和min_samples_split理解
  2. RFC 协议下载方法
  3. 第三周项目四-穷举法解决组合问题(1)
  4. 【模拟退火】解决【TSP】问题
  5. 【机器学习】机器学习基础知识常见问题详解!
  6. ubuntu卸载openjdk-11
  7. Unix原理与应用学习笔记----第六章 文件的基本属性2
  8. 小程序开发-利用canvas实现保存二维码海报到本机
  9. Day_05初始化GDT和IDT
  10. 新兴IT企业特斯拉(八)——自动辅助驾驶
  11. 大厂Android高级多套面试专题整理集合,大厂直通车!
  12. matlab遗传算法求解车辆路径问题(一)
  13. stm32cubeMx---DCMI 配置与使用
  14. 《博德之门3》的许多设计,还不如上世纪的前作
  15. 自学单片机是否先学c语言,学习单片机需要先学好C语言再去学单片机吗
  16. 织梦后台验证码显示不出来-处理办法
  17. 将Android 根目录挂载为 可读可写RW
  18. 2023最新JDK下载、安装与配置教程(jdk17.0.5以及jdk11.0.17)
  19. 二次冲击港交所,手握宝可梦、游戏王的云涌控股困于IP依赖
  20. 数据治理-从理论到实践(一)

热门文章

  1. ## 根据身份证号自动生成年龄以及性别
  2. 快速排序——785:快速排序
  3. 【TIPTOP】 接口步骤 服务端
  4. 【线程同步】 Java 同步块(synchronized)详细说明
  5. linux 制作rpm包实例,rpm制作实例 简单打包
  6. MediaPipe手势(Hands)
  7. windowsserver可以ping通ip但telnet端口失败问题排查处理
  8. Android社团活动设计界面图,基于Android的社团管理APP设计
  9. 公司为什么一定要网站定制开发,选模板不好吗?
  10. 计算机教育软件参评作品例子,2018年东莞计算机教育软件评审活动.doc