目录

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接高,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);

}

}

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

最终效果

好文链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。