HMC5883l磁力计数据读取

1.数据手册地址
2.芯片介绍

  1. 设备的7位地址为0x1e,读地址为0x3d,写地址为0x3c。如图
    图1
    2.寄存器A
    2.主要需要配置的寄存器有3个。分别是配置寄存器A(0x00),配置寄存器B(0x01)和模式寄存器(0x03)

    1. 配置寄存器A(0x00)是用来配置该装置设置的数据输出速率和测量配置. 要注意的是:
      CR7 要设为0。
      CRA6到CRA5用来设置采样平均数。
      CRA4到CRA2用来设置输出速率。
      CRA1到CRA0用来设置测量模式。
      具体配置参数如图
      在这里插入图片描述
      2.配置寄存器B(0x01)
      CRB7到CRB5用来配置测量范围的。
      CRB4到CRB0要设为0。

在这里插入图片描述
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

生成海报
点赞 0

qq_43553197

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

串口不定长接收

一、保留接收区和开启接收的语句    uint8_t buffer[5];HAL_UART_Transmit_IT(&huart1,buffer,3); 二、写入开启空闲中断的语句    __HAL_UART_ENABLE_IT(&huart

基于STM32单片机的电子密码锁设计

一.硬件方案 本设计采用STM32F103C8T6单片机作为主控芯片,结合外围的矩阵按键输入、LCD1602液晶显示、报警、开锁等电路模块实现开锁、上锁、报警、密码更改等功能,设计了一款可以多次修改密码并且具有报警