1.数据手册地址
2.芯片介绍
-
设备的7位地址为0x1e,读地址为0x3d,写地址为0x3c。如图
2.主要需要配置的寄存器有3个。分别是配置寄存器A(0x00),配置寄存器B(0x01)和模式寄存器(0x03)- 配置寄存器A(0x00)是用来配置该装置设置的数据输出速率和测量配置. 要注意的是:
CR7 要设为0。
CRA6到CRA5用来设置采样平均数。
CRA4到CRA2用来设置输出速率。
CRA1到CRA0用来设置测量模式。
具体配置参数如图
2.配置寄存器B(0x01)
CRB7到CRB5用来配置测量范围的。
CRB4到CRB0要设为0。
- 配置寄存器A(0x00)是用来配置该装置设置的数据输出速率和测量配置. 要注意的是:
3.模式寄存器(0x03)
MR7到MR2要设为0
MRA1到MRA0设置测量模式。
测试代码如下:
//i2c.c
//i2c.c#include "stm32f4xx_hal.h"
#include "iic.h"void i2c_init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = I2C_SCL_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;HAL_GPIO_Init(I2C_PORT, &GPIO_InitStruct);}void SDA_INPUT(void)
{ GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = I2C_SDA_Pin;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;HAL_GPIO_Init(I2C_PORT, &GPIO_InitStruct);
}void SDA_OUTPUT(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = I2C_SDA_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;HAL_GPIO_Init(I2C_PORT, &GPIO_InitStruct);}void i2c_Delay(void)
{uint8_t i;for (i = 0; i < 50; i++);
}void delay_us(uint16_t time)
{uint16_t i;for (i = 0 ; i < time ; i++){__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();}}void delay_ms(uint8_t time)
{uint8_t i;for (i = 0 ; i < 10 * time ; i++){delay_us(255);delay_us(255);delay_us(200); }
}void i2c_Start(void)
{SDA_OUTPUT();I2C_SDA_1(); delay_us(20); I2C_SCL_1();delay_us(50); I2C_SDA_0(); delay_us(50); I2C_SCL_0(); delay_us(10);
}void i2c_Stop(void)
{SDA_OUTPUT();I2C_SDA_0(); //STOP:when CLK is high DATA change form low to highdelay_us(20); I2C_SCL_1();delay_us(50);I2C_SDA_1();delay_us(30);
}void i2c_Ack(void)
{SDA_OUTPUT();I2C_SDA_0(); delay_us(20);I2C_SCL_1(); delay_us(50);I2C_SCL_0(); delay_us(10);
}void i2c_NoAck(void)
{SDA_OUTPUT();I2C_SDA_1(); delay_us(20);I2C_SCL_1(); delay_us(50);I2C_SCL_0(); delay_us(10);
}bool i2c_WaitAck(void)
{uint8_t ucErrTime = 0x00;SDA_INPUT(); I2C_SDA_1();delay_us(30);I2C_SCL_1(); delay_us(30); while (I2C_SDA_READ()){ucErrTime++;if (ucErrTime > 250){I2C_SCL_0();delay_us(30);i2c_Stop();return (FALSE);}}I2C_SCL_0();delay_us(30); return (TRUE);
}void i2c_SendByte(uint8_t _ucByte)
{uint8_t i;SDA_OUTPUT();for (i = 0; i < 8; i++){ if (_ucByte & 0x80)I2C_SDA_1();elseI2C_SDA_0();_ucByte <<= 1; delay_us(10); I2C_SCL_1();delay_us(30);I2C_SCL_0();delay_us(10);}
}uint8_t i2c_ReadByte(void)
{uint8_t i;uint8_t value = 0x00;for (i = 0; i < 8; i++){SDA_OUTPUT();I2C_SDA_1(); delay_us(20);I2C_SCL_1(); delay_us(50);SDA_INPUT();value <<= 1;if (I2C_SDA_READ())value++;I2C_SCL_0(); delay_us(10);}return (value);
}
//i2c.h
#ifndef _iic_h
#define _iic_h
#include "struct.h"//i2c.h#include "gpio.h"
#include "stm32f4xx_hal.h"
#include "stdint.h"//#define I2C_PORT GPIOA
//#define I2C_SCL_Pin GPIO_PIN_13
//#define I2C_SDA_Pin GPIO_PIN_14#define I2C_PORT GPIOA //硬件接口定义
#define I2C_SCL_Pin GPIO_PIN_9
#define I2C_SDA_Pin GPIO_PIN_10#define I2C_SCL_1() I2C_PORT->BSRR = I2C_SCL_Pin // SCL = 1
#define I2C_SCL_0() I2C_PORT->BSRR = (uint32_t)I2C_SCL_Pin << 16U // SCL = 0
#define I2C_SDA_1() I2C_PORT->BSRR = I2C_SDA_Pin // SDA = 1
#define I2C_SDA_0() I2C_PORT->BSRR = (uint32_t)I2C_SDA_Pin << 16U // SDA = 0
#define I2C_SDA_READ() (I2C_PORT->IDR & I2C_SDA_Pin) //读取SDAvoid i2c_init(void);
void delay_us(uint16_t time);
void delay_ms(uint8_t time);
void i2c_Start(void);
void i2c_Stop(void);
void i2c_Ack(void);
void i2c_NoAck(void);
bool i2c_WaitAck(void);
void i2c_SendByte(uint8_t _ucByte);
uint8_t i2c_ReadByte(void);#endif
// hmc5883l.c
#include "hmc5883l.h"void HMC5883L_Init(void)
{i2c_Start();i2c_SendByte(0x3c); i2c_WaitAck();i2c_SendByte(0x00);i2c_WaitAck();i2c_SendByte(0x58); //输出速率75hzi2c_Stop();i2c_Start();i2c_SendByte(0x3c); //写指令i2c_WaitAck();i2c_SendByte(0x01);i2c_WaitAck();i2c_SendByte(0x60); //测量范围i2c_WaitAck();i2c_Stop();i2c_Start();i2c_SendByte(0x3c); //写指令i2c_WaitAck();i2c_SendByte(0x02);i2c_WaitAck();i2c_SendByte(0x00); //连续测量模式i2c_WaitAck();i2c_Stop();}void HMC5883L_READ(int16_t *x,int16_t *y)
{ uint8_t XYZ_Data[6]={0};i2c_Start();i2c_SendByte(0x3c); i2c_WaitAck(); i2c_SendByte(0x03); //X轴数据地址i2c_WaitAck(); i2c_Stop();i2c_Start(); i2c_SendByte(0x3d); i2c_WaitAck();for(uint8_t i=0;i<5;i++) {XYZ_Data[i]=i2c_ReadByte();i2c_Ack();}XYZ_Data[5] =i2c_ReadByte(); i2c_NoAck();i2c_Stop();*x = (int16_t)(XYZ_Data[0]<<8)|XYZ_Data[1];*y = (int16_t)(XYZ_Data[4]<<8)|XYZ_Data[5];}
#ifndef _hmc5883l_h_
#define _hmc5883l_h_#include "iic.h"
void HMC5883L_Init(void);
void HMC5883L_READ(int16_t *x,int16_t *y);
#endif
测试图
void main(){int16_t X_HM,Y_HM;i2c_init();HMC5883L_Init(); //磁力计while(1){osDelay(30);HMC5883L_READ(&X_HM,&Y_HM);printf("%d,%d\r\n",X_HM,Y_HM);}
}
可以利用公式计算角度:
Angle = (atan2(Y,X) * (180 / 3.14159265) + 180);