【超详细】磁力计数据读取--以IST8310为例

2023-05-16

这里以iSentek公司产出的IST8310型号的磁力计为例,尺寸为 3.0 * 3.0 * 1.0mm,支持快速 I2C 通信,可达 400kHz,14 位磁场数据,测量范围可达1600uT(x,y-axis)和 2500uT(z-axis), 最高 200Hz 输出频率

同时这里的磁力计是安装在大疆公司出产的RoboMaster开发板C型,单片机芯片是STM32F407IGH6,其外围电路已经设计好,只需要读取磁力计数据即可。

本篇不会介绍SPI、I2C等嵌入式通信协议,需要有一定嵌入式开发基础的同学来看

文末附代码

零、数据手册分析

第一章讲了IST8310的特性,I2C通信,最高支持400kHz通信速率,14位或者16位自适应数据输出等特性

image-20221203143646334

第二章讲了内部结构

image-20221203143810184

第三章讲了电气特性

image-20221203143859175

第四章讲了如何联系他们

image-20221203144121246

然后数据手册就没了。。。在大疆的开发手册中找到了寄存器的手册,如下:

image-20221203165413897

image-20221203165444657

image-20221203165507558

image-20221203165822701

image-20221203165838781

image-20221203165849045

一、CubeMX配置

点开I2C配置选项, 下图是配好的:

image-20221203165955297

观察IST8310的数据手册,发现其支持最大400kHz的I2C通信速率,也就是快速I2C模式,所以第一行I2C Speed Mode我们选Fast Mode

image-20221203170120553

同时不要忘记了在C板中I2C3的两个IO口分别是PA8和PC9(一般来说都是这两个)

image-20221203170657996

之后观察大疆和IST8310的数据手册,发现控制IST8310重启的是PG6的GPIO口,低电平为重启,所以我们将其设置为高电平上拉输出模式

image-20221203170402663

image-20221203170428263

image-20221203170517446

image-20221203170602068

因为我们读取IST8310的程序运行在1kHz的freertos线程中,无需使用中断方式,所以我们不配置中断口

二、数据读取

总代码附在文末,这里放一些核心函数

IST8310初始化:

void IST8310_INIT(ist8310_data_t* ist8310_data) {
    memset(ist8310_data, 0, sizeof(ist8310_data_t));

    ist8310_data->meg_error = IST8310_NO_ERROR;

    // 把磁力计重启
    HAL_GPIO_WritePin(IST8310_GPIOx, IST8310_GPIOp, GPIO_PIN_RESET);
    HAL_Delay(50);
    HAL_GPIO_WritePin(IST8310_GPIOx, IST8310_GPIOp, GPIO_PIN_SET);
    HAL_Delay(50);

    // 基础配置
    // 不使能中断,直接读取
    WriteSingleDataFromIST8310(IST8310_CNTL2_ADDR, IST8310_STAT2_NONE_ALL);
    // 平均采样四次
    WriteSingleDataFromIST8310(IST8310_AVGCNTL_ADDR, IST8310_AVGCNTL_FOURTH);
    // 200Hz的输出频率
    WriteSingleDataFromIST8310(IST8310_CNTL1_ADDR, IST8310_CNTL1_CONTINUE);

    ist8310_data->meg_error |= VerifyMegId(&ist8310_data->chip_id);
}

读取单个数据:

uint8_t ReadSingleDataFromIST8310(uint8_t addr) {
    uint8_t data;
    HAL_I2C_Mem_Read(&IST8310_I2C, (IST8310_I2C_ADDR << 1), addr, I2C_MEMADD_SIZE_8BIT, &data, 1, 10);
    return data;
}

读取多个数据:

void ReadMultiDataFromIST8310(uint8_t addr, uint8_t* data, uint8_t len) {
    HAL_I2C_Mem_Read(&IST8310_I2C, (IST8310_I2C_ADDR << 1), addr, I2C_MEMADD_SIZE_8BIT, data, len, 10);
}

写入单个数据:

void WriteSingleDataFromIST8310(uint8_t addr, uint8_t data) {
    HAL_I2C_Mem_Write(&IST8310_I2C, (IST8310_I2C_ADDR << 1), addr, I2C_MEMADD_SIZE_8BIT, &data, 1, 10);
}

写入多个数据:

void WriteMultiDataFromIST8310(uint8_t addr, uint8_t* data, uint8_t len) {
    HAL_I2C_Mem_Write(&IST8310_I2C, (IST8310_I2C_ADDR << 1), addr, I2C_MEMADD_SIZE_8BIT, data, len, 10);
}

这里会发现一个比较有意思的事情,就是这里的地址都左移了一位,是因为根据I2C协议,[7:0]的一个字节的数据,前七位是地址,后一位是代表读或者写的位,这样子就需要把地址左移

读取磁力计数据:

void ReadIST8310Data(ist8310_raw_data_t* meg_data) {
    uint8_t buf[6];
    int16_t temp_ist8310_data = 0;
    ReadMultiDataFromIST8310(IST8310_DATA_XL_ADDR, buf, 6);
    temp_ist8310_data = (int16_t)((buf[1] << 8) | buf[0]);
    meg_data->x = MAG_SEN * temp_ist8310_data;
    temp_ist8310_data = (int16_t)((buf[3] << 8) | buf[2]);
    meg_data->y = MAG_SEN * temp_ist8310_data;
    temp_ist8310_data = (int16_t)((buf[5] << 8) | buf[4]);
    meg_data->z = MAG_SEN * temp_ist8310_data;
}

这里乘了一个系数MAG_SEN,它的值是0.3,是将读取到的数据转化为单位为uT的磁场值

下面就是源码,把IST8310_INIT()函数放在程序开始的地方,然后剩下的读取函数放在不断执行的线程里,就可以得到磁力计数据了

ist8310.c

/**
 * @Author         : Minghang Li
 * @Date           : 2022-12-03 14:29
 * @LastEditTime   : 2022-12-03 16:52
 * @Note           :
 * @Copyright(c)   : Minghang Li Copyright
 */
#include "ist8310.h"

#include <string.h>

#include "i2c.h"
#include "ist8310reg.h"

void IST8310_INIT(ist8310_data_t* ist8310_data) {
    memset(ist8310_data, 0, sizeof(ist8310_data_t));

    ist8310_data->meg_error = IST8310_NO_ERROR;

    // 把磁力计重启
    HAL_GPIO_WritePin(IST8310_GPIOx, IST8310_GPIOp, GPIO_PIN_RESET);
    HAL_Delay(50);
    HAL_GPIO_WritePin(IST8310_GPIOx, IST8310_GPIOp, GPIO_PIN_SET);
    HAL_Delay(50);

    // 基础配置
    // 不使能中断,直接读取
    WriteSingleDataFromIST8310(IST8310_CNTL2_ADDR, IST8310_STAT2_NONE_ALL);
    // 平均采样四次
    WriteSingleDataFromIST8310(IST8310_AVGCNTL_ADDR, IST8310_AVGCNTL_FOURTH);
    // 200Hz的输出频率
    WriteSingleDataFromIST8310(IST8310_CNTL1_ADDR, IST8310_CNTL1_CONTINUE);

    ist8310_data->meg_error |= VerifyMegId(&ist8310_data->chip_id);
}

uint8_t ReadSingleDataFromIST8310(uint8_t addr) {
    uint8_t data;
    HAL_I2C_Mem_Read(&IST8310_I2C, (IST8310_I2C_ADDR << 1), addr, I2C_MEMADD_SIZE_8BIT, &data, 1, 10);
    return data;
}

void WriteSingleDataFromIST8310(uint8_t addr, uint8_t data) {
    HAL_I2C_Mem_Write(&IST8310_I2C, (IST8310_I2C_ADDR << 1), addr, I2C_MEMADD_SIZE_8BIT, &data, 1, 10);
}

void ReadMultiDataFromIST8310(uint8_t addr, uint8_t* data, uint8_t len) {
    HAL_I2C_Mem_Read(&IST8310_I2C, (IST8310_I2C_ADDR << 1), addr, I2C_MEMADD_SIZE_8BIT, data, len, 10);
}

void WriteMultiDataFromIST8310(uint8_t addr, uint8_t* data, uint8_t len) {
    HAL_I2C_Mem_Write(&IST8310_I2C, (IST8310_I2C_ADDR << 1), addr, I2C_MEMADD_SIZE_8BIT, data, len, 10);
}

void ReadIST8310Data(ist8310_raw_data_t* meg_data) {
    uint8_t buf[6];
    int16_t temp_ist8310_data = 0;
    ReadMultiDataFromIST8310(IST8310_DATA_XL_ADDR, buf, 6);
    temp_ist8310_data = (int16_t)((buf[1] << 8) | buf[0]);
    meg_data->x = MAG_SEN * temp_ist8310_data;
    temp_ist8310_data = (int16_t)((buf[3] << 8) | buf[2]);
    meg_data->y = MAG_SEN * temp_ist8310_data;
    temp_ist8310_data = (int16_t)((buf[5] << 8) | buf[4]);
    meg_data->z = MAG_SEN * temp_ist8310_data;
}

ist8310_error_e VerifyMegId(uint8_t* id) {
    *id = ReadSingleDataFromIST8310(IST8310_CHIP_ID_ADDR);
    if (*id != IST8310_CHIP_ID_VAL) {
        return MEG_ID_ERROR;
    } else {
        return IST8310_NO_ERROR;
    }
}

ist8310.h

/**
 * @Author         : Minghang Li
 * @Date           : 2022-12-03 14:29
 * @LastEditTime   : 2022-12-03 16:49
 * @Note           :
 * @Copyright(c)   : Minghang Li Copyright
 */
#pragma once

#include <stdint.h>

typedef struct ist8310_raw_data_t {
    float x;
    float y;
    float z;
} ist8310_raw_data_t;

typedef enum ist8310_error_e {
    IST8310_NO_ERROR = 0x00,
    MEG_ID_ERROR = 0x01,
} ist8310_error_e;

typedef struct ist8310_data_t {
    uint8_t chip_id;
    ist8310_raw_data_t meg_data;
    ist8310_error_e meg_error;
} ist8310_data_t;

/*-----整形向uT转换-----*/
#define MAG_SEN 0.3f

/*-----I2C接口定义-----*/
#define IST8310_I2C_ADDR 0x0E
#define IST8310_I2C hi2c3

/*-----GPIO口定义-----*/
#define IST8310_GPIOx GPIOG
#define IST8310_GPIOp GPIO_PIN_6

void IST8310_INIT(ist8310_data_t* ist8310_data);

// 基础读取函数
uint8_t ReadSingleDataFromIST8310(uint8_t addr);
void WriteSingleDataFromIST8310(uint8_t addr, uint8_t data);
void ReadMultiDataFromIST8310(uint8_t addr, uint8_t* data, uint8_t len);
void WriteMultiDataFromIST8310(uint8_t addr, uint8_t* data, uint8_t len);

// 功能函数
void ReadIST8310Data(ist8310_raw_data_t* meg_data);

// 校验函数
ist8310_error_e VerifyMegId(uint8_t* id);

ist8310reg.h

/**
 * @Author         : Minghang Li
 * @Date           : 2022-12-03 15:27
 * @LastEditTime   : 2022-12-03 16:53
 * @Note           :
 * @Copyright(c)   : Minghang Li Copyright
 */
#pragma once

/*-----IST8310寄存器地址-----*/
#define IST8310_CHIP_ID_ADDR 0x00
#define IST8310_CHIP_ID_VAL 0x10

#define IST8310_STAT1_ADDR 0x02

#define IST8310_DATA_XL_ADDR 0x03
#define IST8310_DATA_XH_ADDR 0x04
#define IST8310_DATA_YL_ADDR 0x05
#define IST8310_DATA_YH_ADDR 0x06
#define IST8310_DATA_ZL_ADDR 0x07
#define IST8310_DATA_ZH_ADDR 0x08

#define IST8310_STAT2_ADDR 0x09

#define IST8310_CNTL1_ADDR 0x0A
#define IST8310_CNTL1_SLEEP 0x00
#define IST8310_CNTL1_SINGLE 0x01
#define IST8310_CNTL1_CONTINUE 0x0B

#define IST8310_CNTL2_ADDR 0x0B
#define IST8310_STAT2_NONE_ALL 0x00

#define IST8310_SELF_CHECK_ADDR 0x0C

#define IST8310_TEMPL_ADDR 0x1C
#define IST8310_TEMPH_ADDR 0x1D

#define IST8310_AVGCNTL_ADDR 0x41
#define IST8310_AVGCNTL_TWICE 0x09
#define IST8310_AVGCNTL_FOURTH 0x12

效果如下:
image-20221203171539401

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【超详细】磁力计数据读取--以IST8310为例 的相关文章

  • 我的2014

    弹指间2014过去了 xff0c 在过去的一年里 xff0c 或许你收获了成功 xff0c 取得了令人瞩目的成绩 又或许你失意落魄 xff0c 躲在角落了自舔伤口 但这些都不重要 xff0c 重要的是今年是2015不是2014 新的一年里有
  • 51单片机实现串口偶校验

    1 STC单片机串口 2 PSW是一个8位寄存器 PSW的全称是Program Status Word xff0c 即程序状态字 奇偶标志位P 每执行一条汇编指令 xff0c 单片机都能根据A中1的个数的奇偶自动令P置位或清零 xff0c
  • SLAM十四讲第二版ch7位姿估计实践的编译问题

    在看ch7中遇到了g2o OptimizableGraph Vertex clone const 未定义的引用的问题 为了方便以后复现 xff0c 记录如下 我的环境配置 Pangolin 0 5 Opencv 3 4 16 cere 1
  • SLAM十四讲第二版ch6的未定义的引用问题

    在使用slam十四讲第二版做题的时候发现 xff0c ch6编译问题 xff0c 特此记录如下 make时遇到问题如下 xff1a 对 g2o OptimizableGraph Vertex clone const 未定义的引用 对 g2o
  • Ubuntu18.04配置ORB_SLAM3(ROS)

    一 安装ROS 建议按照官网操作 cn melodic Installation Ubuntu ROS Wiki http wiki ros org cn melodic Installation Ubuntu 二 安装eigen3 3 7
  • Semantic Visual Simultaneous Localization and Mapping: A Survey阅读笔记

    Abstract xff1a 通过语义和vslam结合可以很好解决动态和复杂环境中良好定位 首先回顾了语义vslam发展 xff0c 关注优势和差异 其次探讨了 xff1a 语义信息提取和关联 语义的应用和语义的优势然后收集分析了最先进的s
  • git上传到gitee的记录

    一 安装和配置 sudo apt get install git git config global user email 你的邮箱 git config global user name 64 你的昵称 二 上传 先在github或者gi
  • Burst Imaging for Light-Constrained Structure-From-Motion论文翻译记录

    准备开始2022ICRA的SLAM论文阅读记录 Abstract 在极低光照条件下拍摄的图像受噪声限制 xff0c 会导致现有的机器人视觉算法失效 在本文中 xff0c 我们开发了一种图像处理技术 xff0c 用于从弱光条件下采集的图像中辅
  • ROS常用指令

    非代码 一 创建工作空间 mkdir p catkin ws src cd catkin ws src catkin init workspace 二 创建功能包 cd workspace src catin create pkg name
  • 【Matlab】线性跟踪微分器

    线性跟踪微分器介绍 xff1a 线性跟踪微分器出自自抗扰控制ADRC xff0c 线性跟踪微分器有两个作用 xff0c 一是可以用来滤波 xff0c 而是可以用来求取输入的微分 这里有一篇文章可以推荐看看 xff1a https blog
  • FreeRTOS启动流程

    Reset Handler xff1a 芯片上电默认进Reset Handler SystemInit xff1a 初始化时钟及中断向量映射 main xff1a main函数入口 main xTaskCreate xff1a pvPort
  • 基于STM32F411使用SPI+DMA驱动LCD

    先看效果 F411CE 硬件SPI xff0b DMA驱动LCD 基于HAL库 其实HAL库我用不太习惯 xff0c 一直也是用的标准库 但HAL库确实是好上手一些 xff0c 就迅速创建一个新的template 这次就当尝试一下吧 xff
  • 动手深度学习-环境配置(手动安装,一步一步教你,有截图可看)

    一 xff1a 官网教程 这一部分对应了书中的第二讲 xff1a 预备知识部分 因为我是Windows用户 xff0c 所以这里先只讲Windows部分的安装过程 1 xff1a 第一步是根据操作系统下载并安装Miniconda xff0c
  • 机器学习算法原理与实践(三)、卡尔曼滤波器算法浅析及matlab实战

    协方差矩阵 状态协方差矩阵传递 状态协方差的更新 Matlab 实现 Matlab效果 测试代码 测试效果 原创 Liu LongPo 转载请注明出处 CSDN http blog csdn net llp1992 卡尔曼滤波器是一种利用线
  • Pixhawk之获取传感器数据并更新姿态

    博主 xff1a UAV 声明 xff1a 尊重版权 xff0c 转载请注明出处 原文地址 xff1a 联系方式 xff1a 595493514 64 qq com 技术交流QQ xff1a 595493514 read AHRS 是负责更
  • 类与对象以及类的继承

    类与对象以及类的继承 Java是一门面向对象的语编程言 世界上有众多对象 xff0c 我们把具有相同属性和方法的对象归为一个类 因此 xff0c 类 便是Java代码中的基本单位 下面是对一些名词的解释 类 类是一个模板 xff0c 用来定
  • 如何使用 Apache IoTDB 触发器

    Apache IoTDB 触发器提供了一种侦听序列数据变动的机制 配合用户自定义逻辑 xff0c 可完成告警 数据转发等功能 触发器基于 Java 反射机制实现 用户通过简单实现 Java 接口 xff0c 即可实现数据侦听 IoTDB 允
  • Apache IoTDB 查询引擎源码阅读——数据异步传输模块

    本文参考了 Apache IoTDB 社区成员田原和王中的设计文档 xff0c 由于飞书链接限制 xff0c 本文没有贴出参考链接 背景 Apache IoTDB 查询引擎目前采用 MPP 架构 xff0c 一条查询 SQL 大致会经历下图
  • strchr字符查找函数族;strchrnul()

    https blog csdn net jasonchen gbd article details 80069134 Linux中的字符串和字节序列处理函数 Y 字符串查找 xff0c 有库函数 xff0c 可以起到事半功倍的效果 xff0
  • 【Matlab】线性二次型最优控制问题(LQR控制)

    前面介绍了变分法与极小值原理的基础思想 xff0c 之后有一个非常重要的应用就是线性二次型的最优控制问题 假如系统是线性的 xff0c 性能泛函是状态变量与控制变量的二次型函数的积分 xff0c 那么这样的问题称之为线性二次型最优控制问题

随机推荐

  • 什么是回调函数?为什么要使用回调函数?如何使用回调函数?

    1 什么是回调函数 xff1a 函数指针的调用 xff0c 即是一个通过函数指针调用的函数 xff1b 如果你把函数的指针 xff08 地址 xff09 作为参数传递给另一个函数 xff0c 当这个指针被用来调用其所指向的函数时 xff0c
  • android.mk编译规则,1个mk文件编译多个模块

    目录 Android mk 自我理解 Android mk 是什么 Android mk 语法规则 规则解释 xff1a Android mk 编译多个模块实例 xff0c 详见如下 xff1a Android mk 语法规则 xff1a
  • Wireshark抓包分析 TCP三次握手/四次挥手详解

    Wireshark抓包分析 TCP三次握手 四次挥手详解 2019 11 13阅读 1 9K0 作者 xff1a 踏歌追云 来源 xff1a https urlify cn jYVZn2 本文结合wireshark抓包 xff0c 对TCP
  • tls1.3【转载】

    tr tls1 3 发表于 2021 01 04 20 39 更新于 2021 04 29 17 15 tls1 3翻译备忘 摘要 该文档定义了TLS Transport Layer Security 协议的1 3版本 TLS可以让C S应
  • TLS中ChangeCipherSpec为什么是个单独的协议类型【转】

    发表于 2020 03 14 22 27 更新于 2021 04 29 17 15 RFC5246中说 Note To help avoid pipeline stalls ChangeCipherSpec is an independen
  • linux下多线程获取互斥锁,多线程运行时机

    linux内核 CPU 调度决定的线程运行的时间是难以预见 若在复杂程序中发生这一不确定行为 xff0c 则意味着此类错误将偶尔发作 xff0c 难以重现 xff0c 因此也很难发现
  • 数字签名算法MD5和SHA-1的比较

    什么是MD5 xff0c 什么是SHA 1 xff0c 如何校验这些Hash 还有拿单个ISO文件的MD5 xff0c SHA 1讯问是不是原版的问题 xff0c 在这里 xff0c 对以上问题做一个终结解释 xff01 了解 hash H
  • JavaEE.sql.Delete删除语句

    DELETE 语法格式 DELETE FROM table name WHERE condition S1 常用用法 DELETE FROM test master WHERE bindNo 61 39 bn002 39 S2 清空表 DE
  • Docker 容器使用

    Docker 容器使用 可以通过命令 docker command help 更深入的了解指定的 Docker 命令使用方法 容器使用 获取镜像 如果我们本地没有 ubuntu 镜像 xff0c 我们可以使用 docker pull 命令来
  • 【ADRC】跟踪微分器

    在上一篇文章中 xff0c 分析了PID算法的基本数学原理 xff0c 从PID算法的原理与实际应用 xff0c 是可以看出其PID的优点与缺点的 xff0c ADRC算法 自抗扰控制 也可以说是针对PID算法的一些缺点 xff0c 或者说
  • 树莓派3B+安装系统(Raspbian)以及配置环境

    1 硬件准备 1 树莓派3B 43 xff08 E14 xff09 2 一张64G的闪迪存储卡 3 一个读卡器 4 普通电脑显示器 xff0c 键盘 xff0c 鼠标 5 一台可以正常工作的Window系统的电脑 2 安装系统 1 树莓派系
  • 微策略的笔试题

    觉得在收获Offer的季节应该为自己积累些人品了 xff0c 在这里将今天的情况向所有求Offer的童鞋分享下 从上个周末开始反应迟钝的我终于有了些求Offer的感觉 xff0c 几天参加了4场面试 xff0c 基本上没觉得有很大的挑战 x
  • 【无标题】嘉立创EDA,stm32F4控制板。

  • 使用docker-compose连接mysql以及8.0版本遇到的身份验证问题解决方案

    docker compose 使用Docker部署环境非常方便 xff0c Compose项目是 Docker 官方的开源项目 xff0c 负责实现对 Docker 容器集群的快速编排 它允许用户通过一个单独的docker compose
  • EKF—SLAM推导

    转自 http blog csdn net qq 30159351 article details 53408740 这是SLAM最传统的基础 xff0c 是SLAM最原始的方法 xff0c 虽然现在使用较少 xff0c 但是还是有必要了解
  • PX4原生固件源码分析(挖坑)--1、代码结构

    写在开头 最近开始学习PX4源码 xff0c 并进行二次开发 xff0c 苦于网上缺少有关PX4源码的分析 xff0c 于是在这开个坑 xff0c 记录自己学习PX4的过程 xff0c 以此自勉 xff0c 笔者第一次写博客 xff0c 若
  • PX4原生固件源码分析(开填)--2、uORB消息

    写在开头 众所周知 xff0c PX4是通过Mavlink协议进行通信 xff0c 但是Mavlink只是用于外部的通信 xff0c 也就是和QGC地面站进行通信 xff0c 那么PX4中各任务模块相对独立 xff0c 它们之间是怎么通信的
  • 【超详细】基于大疆RoboMaster开发板C型的BMI088数据读取

    超详细 基于大疆RoboMaster开发板C型的BMI088数据读取 这里以博世传感器公司产出的BMI088型号的IMU为例 xff0c 其里面有3轴高精度加速度计和3轴高精度陀螺仪 xff0c 其他的特性不再介绍 同时这里的IMU是安装在
  • IMU综述

    IMU xff08 Inertial measurement unit xff09 xff0c 惯性测量单元 其作用是测量本身的加速度以及角速度 xff0c 有时还通过磁力计来测量朝向 xff0c 当包含磁力计时 xff0c IMU一般被称
  • 【超详细】磁力计数据读取--以IST8310为例

    这里以iSentek公司产出的IST8310型号的磁力计为例 xff0c 尺寸为 3 0 3 0 1 0mm xff0c 支持快速 I2C 通信 xff0c 可达 400kHz xff0c 14 位磁场数据 xff0c 测量范围可达1600