RM3100 stm32驱动(硬件i2c)
目录
- RM3100接线
- HAL库I2C函数
- HAL_I2C_Mem_Read
- HAL_I2C_Mem_Write
- HAL_I2C_Master_Transmit / HAL_I2C_Master_Receive
- 例子 HSHAKE寄存器
- cubemx配置
- RM3100寄存器
- 驱动
- 最终效果
RM3100接线
原理图


SA0 SA1接地,此时i2c设备地址为0100000,即0x20
如果SA0接高,SA1接地,地址为0100001,即0x21
如果SA0接地,SA1接高,地址为0100010,即0x22
SDA SCL正常接单片机,要上拉
I2C/SPI接高,选择I2C模式
手册下载链接
HAL库I2C函数
stm32 hal库对于i2c的操作有几个函数:
HAL_I2C_Mem_Read
hi2c:i2cx,比如 &hi2c1
DevAddress:左移一位的传感器设备地址,比如RM3100原来是0x20,要输入(0x20<<1)即0x40
MemAddress:要读取的寄存器地址,这个不用左移,按照手册里面即可,比如HSHAKE寄存器就是0x35
MemAddSize:一般I2C_MEMADD_SIZE_8BIT
后面几个正常写即可,pData传指针把读出来数据传递出来,比如HSHAKE寄存器(0x35)读出来就是0x1B
/*** @brief Read an amount of data in blocking mode from a specific memory address* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains* the configuration information for the specified I2C.* @param DevAddress Target device address: The device 7 bits address value* in datasheet must be shifted to the left before calling the interface* @param MemAddress Internal memory address* @param MemAddSize Size of internal memory address* @param pData Pointer to data buffer* @param Size Amount of data to be sent* @param Timeout Timeout duration* @retval HAL status*/
HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
HAL_I2C_Mem_Write
和上面类似,不同的是pData 变成了往里面写的数据
/*** @brief Write an amount of data in blocking mode to a specific memory address* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains* the configuration information for the specified I2C.* @param DevAddress Target device address: The device 7 bits address value* in datasheet must be shifted to the left before calling the interface* @param MemAddress Internal memory address* @param MemAddSize Size of internal memory address* @param pData Pointer to data buffer* @param Size Amount of data to be sent* @param Timeout Timeout duration* @retval HAL status*/
HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
HAL_I2C_Master_Transmit / HAL_I2C_Master_Receive
这俩成对用,可以看到他俩都么有MemAddress
先调用HAL_I2C_Master_Transmit,pData写成MemAddress地址,再调用HAL_I2C_Master_Receive收数据
/*** @brief Transmits in master mode an amount of data in blocking mode.* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains* the configuration information for the specified I2C.* @param DevAddress Target device address: The device 7 bits address value* in datasheet must be shifted to the left before calling the interface* @param pData Pointer to data buffer* @param Size Amount of data to be sent* @param Timeout Timeout duration* @retval HAL status*/
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
/*** @brief Receives in master mode an amount of data in blocking mode.* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains* the configuration information for the specified I2C.* @param DevAddress Target device address: The device 7 bits address value* in datasheet must be shifted to the left before calling the interface* @param pData Pointer to data buffer* @param Size Amount of data to be sent* @param Timeout Timeout duration* @retval HAL status*/
HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
例子 HSHAKE寄存器
两种写法,data即为读出来数据,应该是0x1B
uint8_t data=0;
HAL_StatusTypeDef status = HAL_I2C_Mem_Read(&RM3100_I2C,RM3100_ADDRESS,ADDR_HSHAKE,I2C_MEMADD_SIZE_8BIT,&data, 1, 1000);
uint8_t data=0;
uint8_t addr_hshake=ADDR_HSHAKE;//0x35
HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(&RM3100_I2C,RM3100_ADDRESS,&addr_hshake,1,1000); //addr_hshake要写成目标寄存器地址
status = HAL_I2C_Master_Receive(&RM3100_I2C,(RM3100_ADDRESS|1),&data,1,1000);
cubemx配置
正常使用I2C即可,选择fast mode,最高400k可以工作

需要上拉,最好硬件上也拉一下

RM3100寄存器

上面提示了对于I2C,读写地址不一样,因为有一位0/1标志着读/写,但是不用管,hal库帮我们搞好了,直接对着第二列填MemAddress即可

驱动
采用poll写法,参考手册5.3 5.8 5.8.2
.h文件
#ifndef __RM3100_H
#define __RM3100_H
#include "main.h"
#include "i2c.h"#define RM3100_I2C hi2c1
#define RM3100_ADDRESS 0x20<<1 //AD0 AD1都接地#define RM3100_CONVERSION_INTERVAL 10000 // Microseconds, corresponds to 100 Hz (cycle count 200 on 3 axis)
#define UTESLA_TO_GAUSS 100.0f
#define RM3100_SENSITIVITY 75.0f#define ADDR_POLL 0x00
#define ADDR_CMM 0x01
#define ADDR_CCX 0x04
#define ADDR_CCY 0x06
#define ADDR_CCZ 0x08
#define ADDR_TMRC 0x0B
#define ADDR_MX 0x24
#define ADDR_MY 0x27
#define ADDR_MZ 0x2A
#define ADDR_BIST 0x33
#define ADDR_STATUS 0x34
//#define ADDR_STATUS_READ 0xB4 //0X34|0X80
#define ADDR_HSHAKE 0x35
#define ADDR_REVID 0x36#define CCX_DEFAULT_MSB 0x00
#define CCX_DEFAULT_LSB 0xC8
#define CCY_DEFAULT_MSB CCX_DEFAULT_MSB
#define CCY_DEFAULT_LSB CCX_DEFAULT_LSB
#define CCZ_DEFAULT_MSB CCX_DEFAULT_MSB
#define CCZ_DEFAULT_LSB CCX_DEFAULT_LSB
#define CMM_DEFAULT 0x70 // No continuous mode
#define CONTINUOUS_MODE (1 << 0)
#define POLLING_MODE (0 << 0)
#define TMRC_DEFAULT 0x94
#define BIST_SELFTEST 0x8F
#define BIST_DEFAULT 0x00
#define BIST_XYZ_OK ((1 << 4) | (1 << 5) | (1 << 6))
#define STATUS_DRDY (1 << 7)
#define POLL_XYZ 0x70
#define RM3100_REVID 0x22#define NUM_BUS_OPTIONS (sizeof(bus_options)/sizeof(bus_options[0]))uint8_t RM3100ReadID(void);
uint8_t RM3100_Init(void);
uint8_t RM3100_GetData(short *x,short *y,short*z);
uint8_t RM3100_CheckDataReady(void);
#endif
.c文件
#include "RM3100.h"uint8_t RM3100ReadID(void){uint8_t data=0;uint8_t addr_hshake=ADDR_HSHAKE;
// HAL_StatusTypeDef status = HAL_I2C_Mem_Read(&RM3100_I2C,RM3100_ADDRESS,ADDR_HSHAKE,I2C_MEMADD_SIZE_8BIT,&data, 1, 1000);HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(&RM3100_I2C,RM3100_ADDRESS,&addr_hshake,1,1000); //addr_hshake要写成目标寄存器地址status = HAL_I2C_Master_Receive(&RM3100_I2C,(RM3100_ADDRESS|1),&data,1,1000);//两种写法都可以,读取0x35寄存器值,并与1b进行比较if(status!=HAL_OK){printf("RM3100 I2C Error!\r\n");return 1;}else{if(data!=0x1B){printf("RM3100 detected Error! %x\r\n",data);return 1;}else{printf("RM3100 Address = %x\r\n",data);return 0;}}
}uint8_t RM3100_Init(void){uint8_t CCR[6] = {0, 200, 0, 200, 0, 200};if(RM3100ReadID()) {return 1;}else{HAL_StatusTypeDef status = HAL_I2C_Mem_Write(&RM3100_I2C,RM3100_ADDRESS,ADDR_CCX,I2C_MEMADD_SIZE_8BIT,CCR, 6, 1000);//发送一次poll请求,开始测量uint8_t data=POLL_XYZ;HAL_StatusTypeDef status1 = HAL_I2C_Mem_Write(&RM3100_I2C,RM3100_ADDRESS,ADDR_POLL,I2C_MEMADD_SIZE_8BIT,&data, 1, 1000);if(status!=HAL_OK | status1!=HAL_OK){printf("Error!,status=%d,status1=%d\r\n",status,status1);return 1;}else{return 0;} }
}uint8_t RM3100_CheckDataReady(void)
{uint8_t cResult;HAL_I2C_Mem_Read(&RM3100_I2C,RM3100_ADDRESS,ADDR_STATUS,I2C_MEMADD_SIZE_8BIT,&cResult,1,1000);cResult = cResult&0x80;
// printf("%x\r\n",cResult);return cResult;
}uint8_t RM3100_GetData(short *x,short *y,short*z){static long Mag_Data[3] = {0};uint8_t temp[9]={0};uint8_t poll_request=POLL_XYZ;if(RM3100_CheckDataReady()==0x80){//data ready//读取9个字节HAL_StatusTypeDef status = HAL_I2C_Mem_Read(&RM3100_I2C,RM3100_ADDRESS,ADDR_MX,I2C_MEMADD_SIZE_8BIT,temp, 9, 1000);Mag_Data[0]= (long)temp[0]<<16 | (long)temp[1]<<8 | temp[2];if(Mag_Data[0] >= 0x00800000) {Mag_Data[0] |= 0xff000000;}Mag_Data[1] = (long)temp[3]<<16 | (long)temp[4]<<8 | temp[5];if(Mag_Data[1] >= 0x00800000) {Mag_Data[1] |= 0xff000000;}Mag_Data[2] = (long)temp[6]<<16 | (long)temp[7]<<8 | temp[8];if(Mag_Data[2] >= 0x00800000) {Mag_Data[2] |= 0xff000000;}*y = -Mag_Data[0];*x = -Mag_Data[1];*z = -Mag_Data[2];//发送一次poll请求,开始测量HAL_StatusTypeDef status1 = HAL_I2C_Mem_Write(&RM3100_I2C,RM3100_ADDRESS,ADDR_POLL,I2C_MEMADD_SIZE_8BIT,&poll_request, 1, 1000);if(status!=HAL_OK | status1!=HAL_OK){printf("Error!,status=%d,status1=%d\r\n",status,status1);return 1;}else{return 0;}}else{printf("Data Not Ready!\r\n");return 1;}
}
主函数:
int main(void)
{//初始化……RM3100_Init();short hx,hy,hz=0;while (1){RM3100_GetData(&hx, &hy, &hz);printf("RM3100 hx: %d, hy: %d, hz: %d\r\n", hx, hy, hz);HAL_Delay(8);}
}
其他功能没写,后面慢慢补上
最终效果


相关文章:
RM3100 stm32驱动(硬件i2c)
目录 RM3100接线HAL库I2C函数HAL_I2C_Mem_ReadHAL_I2C_Mem_WriteHAL_I2C_Master_Transmit / HAL_I2C_Master_Receive例子 HSHAKE寄存器 cubemx配置RM3100寄存器驱动最终效果 RM3100接线 原理图 SA0 SA1接地,此时i2c设备地址为0100000,即0x20 如果SA0接…...
视觉学习(7) —— 接收数据和发送数据以及全局变量和浮点数
1、前提 创建一个四个字节的地址 2、发送数据 (1)直接发送数据 再观察地址里的值 与我们想要值不一样 输入0,而实际值则为 结论:直接输入值到地址,值会发生变化 (2)走全局变量发送数据 添加全…...
leetcode 1576. 替换所有的问号(easy)(优质解法)
链接:1576. 替换所有的问号 代码: class Solution {public String modifyString(String s) {char[] charSs.toCharArray();int lengthcharS.length;//遍历找到 ?for(int i0;i<length;i){if(charS[i]?){//遍历 a ~ z 选择一个合适的字符来…...
Advanced IP Scanner - 网络扫描器
Advanced IP Scanner - 网络扫描器 1. Advanced IP ScannerReferences https://www.advanced-ip-scanner.com/cn/ 可靠且免费的网络扫描器可以分析 LAN。该程序可扫描所有网络设备,使您能够访问共享文件夹和 FTP 服务器,(通过 RDP 和 Radmin) 远程控制…...
搜索百度百科官方创建入口,怎么创建更新公司的百度百科词条呢?
在百度搜索百度百科找到百度百科官方创建入口,可以上传并创建公司类的百度百科词条,创建词条后还可以再修改更新百科词条,最终完善好的百度百科词条将会在百度上获得大量曝光。那么百度百科可以怎么创建,下面洛希爱做百科网把十多…...
大数据与人工智能|全面数字化战略与企业数字化转型(第1节 )
要点一:培养跨学科思维 在分析时,需要采用多学科的思维方式 结果不重要,重要的是如何提炼现象、分析问题和得出结论的过程。 1. 介绍了锤子精神和多学科思维方式的重要性。指出了只从自身学科出发解决问题的局限性。 2. 提倡跨学科思维方式&a…...
【四】【C语言\动态规划】地下城游戏、按摩师、打家劫舍 II,三道题目深度解析
动态规划 动态规划就像是解决问题的一种策略,它可以帮助我们更高效地找到问题的解决方案。这个策略的核心思想就是将问题分解为一系列的小问题,并将每个小问题的解保存起来。这样,当我们需要解决原始问题的时候,我们就可以直接利…...
【大数据存储与处理】开卷考试总复习笔记
文章目录 实验部分一、 HBase 的基本操作1. HBase Shell入门2. HBase创建数据库表3. HBase数据操作4. HBase删除数据库表5. HBase Python基本编程 before二、 HBase 过滤器操作1.创建表和插入数据2.行键过滤器3.列族与列过滤器4.值过滤器5.其他过滤器6.python hbase 过滤器编程…...
HTML 实操试题(一)
创建一个包含标题、段落和链接的基本HTML文档: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><ti…...
创龙瑞芯微RK3568设备树1(修改设备树GPIO和串口)
前言 最近一直在搞3568的东西,涉及到底层的设备树修改,驱动编写等等,忙的焦头烂额的,也没时间往下面写东西了。今天差不多底层的东西快弄完了,把最近的感悟给大家分享下,并且加入点设备树的基础知识。给刚刚…...
R语言【dplyr】——filter保留符合筛选条件的行,以数据的行为单位,创建子集
Package dplyr version 1.1.4 Parameters filter(.data, ..., .by NULL, .preverse FALSE) 参数【.data】:一个数据集(data frame),数据集扩展(比如:tibble),或者 lazy data fra…...
几种串口扩展电路
一、IIC串口扩展电路 LCT200 是一款可以通过 I2C 接口通讯,拓展 2 路独立串口的通讯芯片,同时也支持通过 2 路串口读写 I2C 接口的数据。LCT200 的封装为 TSSOP-20。 主要功能:⚫ 通过对 I2C 接口读写实现拓展 2 路独立串口功能 ⚫ 通过读写…...
实战10 角色管理
目录 1、角色后端接口 2、角色列表查询 2.1 效果图 2.2页面原型代码 2.3 角色api代码 role.js 2.4 查询角色列表代码 4、 新增和编辑角色 5、删除角色 6、分配权限 6.1 分配权限思路 6.2 分配权限回显接口 6.3 分配权限回显前端实现 6.4分配权限后端接口 6.4.1 R…...
Lua的底层原理与C#交互原理浅析【更新中】
目录 lua底层原理浅析 table底层原理浅析 Lua表的C语言定义 原理和实现 userdata lua和C#的交互机制(更新中) 基本介绍 Lua 与 C/C 的数据交互 Lua 调用 C/C 函数 C/C 调用 Lua 函数 基元类型传递 对象类型传递 Lua 调用 C# 总结 网上有很…...
鸿蒙项目二—— 注册和登录
此部分和上篇文章是连续剧 ,如果需要,请查看 一、注册 import http from ohos.net.http; Entry Component struct Reg {// 定义数据:State username: string "";State userpass: string "";State userpass2: string …...
Dijkstra(迪杰斯特拉)算法总结
知识概览 Dijkstra算法适用于解决所有边权都是正数的最短路问题。Dijkstra算法分为朴素的Dijkstra算法和堆优化版的Dijkstra算法。朴素的Dijkstra算法时间复杂度为,适用于稠密图。堆优化版的Dijkstra算法时间复杂度为,适用于稀疏图。稠密图的边数m和是一…...
设计模式?!
如何解决复杂性 链接:不同的设计模式实例代码(更新中) 分解 人们面对复杂性有一个常见的做法:即分而治之,将大问题分解为多个小问题,将复杂问题分解为多个简单问题。 抽象 更高层次来讲,人们处…...
Pytorch项目,肺癌检测项目之三
成功获取到数据之后,我们需要将数据放到Pytorch里面去处理,我们需要将其转换成Dataset数据集,方便去使用相同的API。要转换成Dataset数据集需要实现两个方法,方法一: 方法二: 运行比较慢的话,…...
深圳鼎信|输电线路防山火视频监控预警装置:森林火灾来袭,安全不留白!
受线路走廊制约和环保要求影响,输电线路大多建立在高山上,不仅可以减少地面障碍物和人类活动的干扰,还能提高线路的抗灾能力和可靠性。但同时也会面临其它的难题,例如森林火灾预防。今天,深圳鼎信智慧将从不同角度分析…...
【Bash/Shell】知识总结
文章目录 1. 总体认识1.1. Shell概述1.2. 第一个Shell脚本1.3. 注释 2. 变量2.1. 定义变量2.2. 使用变量2.3. 只读变量2.4. 删除变量2.5. 变量类型2.5.1. 字符串变量2.5.2. 整数变量2.5.3. 数组变量2.5.4. 环境变量2.5.5. 特殊变量 3. 输出3.1. echo命令3.2. printf命令 4. 运算…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
