RM3100 stm32驱动(硬件i2c)

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);
  }
}

其他功能没写,后面慢慢补上

最终效果

在这里插入图片描述
在这里插入图片描述

  • 18
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
RM3100是一种高精度、低功耗的磁传感器,常用于姿态检测、导航、机器人等领域。为了让RM3100能够正常工作,我们需要安装相应的驱动程序。 首先,我们可以从RM3100的官方网站或者供应商的网站上下载到最新版本的驱动程序。下载后,我们需要将驱动程序解压缩到计算机的特定文件夹中。 接下来,我们需要连接RM3100与计算机。如果我们使用的是I2C接口连接,我们需要将RM3100与计算机的I2C总线相连。如果使用SPI接口,我们则需将RM3100与计算机的SPI接口相连。此外,在连接之前,还需要确保供电电压与电流符合RM3100的要求。 一旦确保连接正确,我们可以打开计算机上的设备管理器,并找到RM3100磁传感器。如果驱动程序没有正确安装,设备管理器将显示黄色感叹号或问号。 在设备管理器中,我们可以选择更新驱动程序,选择手动安装驱动程序,并选择我们之前解压缩的驱动程序所在的文件夹。 一旦我们完成安装,设备管理器将显示磁传感器设备的名称,并且没有任何错误标志。 现在,我们可以在计算机上编写程序,使用RM3100磁传感器进行姿态检测、导航或机器人控制等应用。在编写代码时,我们需要调用相应的接口进行数据读取和处理。 总的来说,安装RM3100的驱动程序是使用该磁传感器进行正常工作的必要步骤。在正确安装驱动程序后,我们就可以利用RM3100进行各种应用领域的开发和研究。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值