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

news/2024/12/29 14:26:09/

这里以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_6void 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


http://www.ppmy.cn/news/789081.html

相关文章

Python简单爬取电影磁力链接

Python简单爬取电影磁力链接 网页的链接&#xff1a;http://www.ygdy8.net/html/gndy/dyzz/list_23_2.html 打开你想要的电影&#xff1a;http://www.ygdy8.net/html/gndy/dyzz/20181124/57807.html 找到下载地址&#xff1a; 代码&#xff1a; import requests#网络请求模块…

[初学Python]利用某网站的功能写一个磁力链转种子工具

孔子曰&#xff1a;学而时习之~ 初学python&#xff0c;一边看语法&#xff0c;一边看参考例程&#xff0c;写了一个小程序&#xff0c;做个存档&#xff0c;否则很容易忘记。 这次的目标是利用某种子下载网站&#xff0c;编写一个磁力链下载种子文件的工具。 常见的种子文件…

磁力块(分块)

题目链接 输入格式 第一行五个整数 x 0 , y 0 , p L , r L , N x_0,y_0,p_L,r_L,N x0​,y0​,pL​,rL​,N&#xff0c;表示小取酒所在的位置&#xff0c;磁石 L L L 磁力、吸引半径和原野上散落磁石的个数。 接下来 N N N 行每行五个整数 x , y , m , p , r x,y,m,p,r x,…

海洋磁力数据处理步骤

​ &#xff08;此照片乃航次获奖照片&#xff09; 前面几个章节介绍了地磁基本知识&#xff0c;由于项目紧急&#xff0c;只能边学习理论&#xff0c; 边处理。经过2个月的努力&#xff0c;基本上掌握了海洋重磁处理的基本方法。 目前&#xff0c;专项的重磁处理都是各单位自己…

磁力链接做成rar文件后怎么打开

要打开 RAR 文件&#xff0c;首先需要安装一个 RAR 解压缩软件。 Windows 系统自带的资源管理器不能直接解压 RAR 文件&#xff0c;所以需要使用第三方软件。 常用的 RAR 解压缩软件有&#xff1a; WinRAR(收费)7-Zip(免费) 安装完解压缩软件之后&#xff0c;打开 RAR 文件可以…

磁力块

题目链接 在一片广袤无垠的原野上&#xff0c;散落着 N N N块磁石。 每个磁石的性质可以用一个五元组 ( x , y , m , p , r ) (x,y,m,p,r) (x,y,m,p,r)描述&#xff0c;其中 x , y x,y x,y表示其坐标&#xff0c; m m m是磁石的质量&#xff0c; p p p是磁力&#xff0c; r r …

基于matlab使用激光雷达检测地平面和障碍物(附源码)

一、前言 此示例演示如何通过分割地平面并查找附近的障碍物来处理来自安装在车辆上的传感器的 3-D 激光雷达数据。这可以促进车辆导航的可驾驶路径规划。该示例还演示如何可视化流式激光雷达数据。 二、创建 Velodyne 文件读取器 本例中使用的激光雷达数据是使用安装在车辆上…

find和grep各个参数

find 功能&#xff1a;在目录结构中搜索文件&#xff0c;并执行指定的操作。此命令提供了相当多的查找条件&#xff0c;功能很强大。 语法: find 查找位置 匹配文件名 说明&#xff1a;find命令从指定的起始目录开始&#xff0c;递归地搜索其各个子目录&#xff0c;查找满足…