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 high
delay_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();
else
I2C_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) //读取SDA
void 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); //输出速率75hz
i2c_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);
版权声明:本文为CSDN博主「qq_43553197」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_43553197/article/details/122928098
暂无评论