1.简介

  霍尼韦尔 HMC5883L 是一种表面贴装的高集成模块,并带有数字接口的弱磁传感器芯片,应用于低成本罗盘和磁场检测领域。HMC5883L 包括最先进的高分辨率 HMC118X 系列磁阻传感器,并附带霍尼韦尔专利的集成电路包括放大器、自动消磁驱动器、偏差校准、能使罗盘精度控制在 1°~2°的 12 位模数转换器.简易的 I2 C 系列总线接口。HMC5883L 是采用无铅表面封装技术,带有 16 引脚,尺寸为 3.0X3.0X0.9mm。HMC5883L 的所应用领域有手机、笔记本电脑、消费类电子、汽车导航系统和个人导航系统。

  HMC5883L 采用霍尼韦尔各向异性磁阻(AMR)技术,该技术的优点是其他磁传感器技术所无法企及。这些各向异性传感器具有在轴向高灵敏度和线性高精度的特点.传感器带有的对于正交轴低敏感行的固相结构能用于测量地球磁场的方向和大小,其测量范围从毫高斯到 8高斯(gauss)。 霍尼韦尔的磁传感器在低磁场传感器行业中是灵敏度最高和可靠性最好的传感器。

2.硬件连接

  下图为HMC5883L与STM32的连接图,可以看出它是用的IIC通讯方式,注意这边上拉电阻用的是10K的(官方推荐),我个人还是用4.7K进行测试读写。

              

3.寄存器介绍

             

提到寄存器就必须说一下,大家买HMC5883L的时候一定要注意!!!别错买QMC5883L,两者的寄存器地址是不一样的哦。下面简单介绍一下各个寄存器:

配置寄存器 A:

  配置寄存器是用来配置该装置设置的数据输出速率和测量配置。 CRA0 通过 CRA7 表明位的位置,用 CAR 指示在配置寄存器中的位。 CRA7 指示数据流的第一位。括号中的数目显示是该位的默认值(不太可靠,仅供参考)。

            

                                  上表为:配置寄存器A,下表尾配置寄存器A的位分配情况

            

下表的数据显示在连续测量模式下的所有可选的输出速率。所有这三个通道应在某一特定数据速率下测量。其他输出速率可以通过控制单测量模式下的 DRDY 中断引脚来获得,最大速率为 160Hz。

            

                                上表为:数据输出速率,下表为测量模式选择

            

配置寄存器 B

  配置寄存器 B 设置装置的增益。 CRB0 通过 CRB7 识别位的位置,用 CRB 指示在配置寄存器里的位。CRB7 表示数据流中的第一位。括号中的数目显示的是位的默认值。下表为:配置寄存器B及位分配
            

            

下表描述增益设置。使用以下“增益”一栏将counts转换成Guass。在总共磁场强度引起所有数据输出存储器中一个溢位(饱和)时选择较低的增益值(高GN#值)。

            

模式寄存器

该寄存器是一个8位可读可写的寄存器。该寄存器是用来设定装置的操作模式。 MR0通过MR7识别位的位置,MR表明模式寄存器里的位。MR7指示数据流中的第一位。括号中的数字显示的是位的默认值。下表为:模式寄存器

            

            

                                  上表为:模式寄存器位分配,下表为:操作模式

            

数据输出 X 寄存器 A 和B

数据输出 X 寄存器是两个 8 位寄存器,数据输出寄存器 A 和 B。这些寄存器储存从通道 X 所测量结果。数据输出 X 寄存器 A 储存一个来自测量结果中的 MSB(高位数据),数据输出 X 寄存器 B 储存一个来自测量结果中的 LSB(低位数据)。存储在这两个寄存器的值是一个 16 位值以二进制的补码形式存在,其范围是 0xF800到 0x07FF。DXRA0 至 DXRA7、DXRB0 至 DXRB7 标识出位置, DXRA 和 DXRB 标识出在数据输出寄存器 X 中的位。DXRA7 和 DXRB7 标识出数据流的第一位,括号中的数目显示该位的默认值。
在事件的ADC上溢或下溢阅读给定的通道,或者如果有一个数学溢出的过程,这种数据寄存器将包含-4096的值。在下一次有效测量完成进行之后,该寄存器上的值将被清除。下表为:数据输出X寄存器 A和B
            

下面的Y和Z和X类似就不介绍了。

4.软件设计

  用到IIC通讯必须要注意一下HMC5883L的控制时序,各位注意修改,我这边直接用的HAL库自带的延时,下面看一下IIC的程序:

//--------------------------------------------i2c-------------------------------------------
// 设置SDA为输出方向,对于双向I/O需切换为输出
void SDA_D_OUT()
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
} // 设置SDA为输入方向,对于双向I/O需切换为输入
void SDA_D_IN()
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
} /**************************************
起始信号
**************************************/
void HMC5883_Start()
{
SDA_D_OUT();
SDA_H; //拉高数据线
SCL_H; //拉高时钟线
HAL_Delay(1); //延时
SDA_L; //产生下降沿
HAL_Delay(1); //延时
SCL_L; //拉低时钟线
} /**************************************
停止信号
**************************************/
void HMC5883_Stop()
{
//SDA_D_OUT();
SCL_H; //拉高时钟线
SDA_L; //拉低数据线
HAL_Delay(1); //延时
SDA_H; //产生上升沿
HAL_Delay(1); //延时
} /**************************************
发送应答信号
入口参数:ack (0:ACK 1:NAK)
**************************************/
void HMC5883_SendACK(uint8_t ack)
{
SDA_D_OUT();
if(ack==1)
{
SDA_H;
}else
{
SDA_L;
}
SCL_H; //拉高时钟线
HAL_Delay(1); //延时
SCL_L; //拉低时钟线
HAL_Delay(1); //延时
} /**************************************
接收应答信号
**************************************/
uint8_t HMC5883_RecvACK()
{
SDA_D_IN();
SCL_H; //拉高时钟线
HAL_Delay(10); //延时
CY = READ_SDA_IN; //进位标志 读应答信号
SCL_L; //拉低时钟线
HAL_Delay(1); //延时
return CY;
}
//等待从机应答信号
//返回值:1 接收应答失败
// 0 接收应答成功
uint8_t HMC5883L_I2C_Wait_Ack(void)
{
uint8_t tempTime=0; SDA_D_IN(); SDA_H;
HAL_Delay(1);
SCL_H;
HAL_Delay(1); while(READ_SDA_IN)
{
tempTime++;
if(tempTime>250)
{
HMC5883_Stop();
return 1;
}
} SCL_L;
return 0;
}
/**************************************
向IIC总线发送一个字节数据
**************************************/
void HMC5883_SendByte(uint8_t dat)
{
uint8_t i;
SDA_D_OUT();
SCL_L; //拉低时钟开始数据传输
for (i=0; i<8; i++) //8位计数器
{
//dat <<= 1; //移出数据的最高位
if( dat & 0x80 )
{
SDA_SET;
}
else
{
SDA_CLR;
}
HAL_Delay(1); //延时
dat <<= 1; //移出数据的最高位
SCL_H; //拉高时钟线
HAL_Delay(1); //延时
SCL_L; //拉低时钟线
} HMC5883_RecvACK();
}
/**************************************
从IIC总线接收一个字节数据
**************************************/
uint8_t HMC5883_RecvByte()
{
uint8_t i;
uint8_t dat = 0;
SDA_D_IN();
SDA_H; //使能内部上拉,准备读取数据,
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1;
SCL_H; //拉高时钟线
HAL_Delay(1); //延时
if(READ_SDA_IN)dat++;
//dat <<= 1;
//dat |= SDA; //读数据
SCL_L; //拉低时钟线
HAL_Delay(1); //延时
}
return dat;
} //************************写入单字节数据*************************** //void Single_Write_QMC5883(uint8_t REG_Address,uint8_t REG_data)
//{
// QMC5883_Start(); //起始信号
// QMC5883_SendByte(Slave_Address); //发送设备地址+写信号
// //if(QMC5883L_I2C_Wait_Ack())
// //{
// // QMC5883_Stop();
// // printf("error\r\n");
// //}
// QMC5883_SendByte(REG_Address); //内部寄存器地址,请参考中文pdf
// QMC5883_SendByte(REG_data); //内部寄存器数据,请参考中文pdf
// QMC5883_Stop(); //发送停止信号
//} //************************读取单字节数据*************************
uint8_t Single_Read_HMC5883(uint8_t REG_Address)
{
uint8_t REG_data;
HMC5883_Start(); //起始信号
HMC5883_SendByte(Slave_Address); //发送设备地址+写信号
HMC5883_SendByte(REG_Address); //发送存储单元地址,从0开始
HMC5883_Start(); //起始信号
HMC5883_SendByte(Slave_Address+1); //发送设备地址+读信号
REG_data=HMC5883_RecvByte(); //读出寄存器数据
HMC5883_SendACK(1);
HMC5883_Stop(); //停止信号
return REG_data;
} //******************************************************
//连续读出QMC5883内部角度数据,地址范围0x00~0x05
//******************************************************
void Multiple_Read_HMC5883(void)
{
uint8_t i=0;
HMC5883_Start(); //起始信号
HMC5883_SendByte(Slave_Address); //发送设备地址+写信号
HMC5883_SendByte(0x03); //发送存储单元地址,从0x00开始
HMC5883_Start(); //起始信号
HMC5883_SendByte(Slave_Address+1); //发送设备地址+读信号
for (i=0; i<6; i++) //连续读取6个地址数据,存储中BUF
{
BUF[i] = HMC5883_RecvByte(); //BUF[0]存储数据
if (i == 5)
{
HMC5883_SendACK(1); //最后一个数据需要回非应答NOACK
}
else
{
HMC5883_SendACK(0); //应答ACK
}
}
x=(BUF[0]<<8)|(BUF[1]);
if(x>32767) x=0xffff-x+1;
z=(BUF[2]<<8)|(BUF[3]);
if(z>32767) z=0xffff-z+1;
y=(BUF[4]<<8)|(BUF[5]);
if(y>32767) y=0xffff-y+1;
HMC5883_Stop(); //停止信号
HAL_Delay(10);
} //2初始化HMC5883,根据需要请参考pdf进行修改****
void HMC5883L_Init()
{
HMC5883_Start();
HMC5883_SendByte(0x3c); //发送设备地址+写信号
HMC5883_SendByte(0x00); //内部寄存器地址,请参考中文pdf
HMC5883_SendByte(0x78); //内部寄存器数据,请参考中文pdf
HMC5883_Start();
HMC5883_SendByte(0x3c); //发送设备地址+写信号
HMC5883_SendByte(0x01); //内部寄存器地址,请参考中文pdf
HMC5883_SendByte(0x00); //内部寄存器数据,请参考中文pdf
HMC5883_Start();
HMC5883_SendByte(0x3c); //发送设备地址+写信号
HMC5883_SendByte(0x02); //内部寄存器地址,请参考中文pdf
HMC5883_SendByte(0x00); //内部寄存器数据,请参考中文pdf
HMC5883_Stop();
}

IIC通讯

预定义和主程序如下:

// 设置系统参数命令
#define SCL_SET HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET)
#define SCL_H HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET) #define SCL_CLR HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET)
#define SCL_L HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET) #define SCL_D_OUT {} // 设置SCL为输出方向,对于双向I/O需切换为输出 #define SDA_SET HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET)
#define SDA_H HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET) #define SDA_CLR HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET)
#define SDA_L HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET) #define CH455_SDA_IN HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_9) // 读取SDA输入电平
#define READ_SDA_IN HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_9) // 读取SDA输入电平 #define Slave_Address 0x3C //定义器件在IIC总线中的从地址 write

预定义

int main(void)
{
HAL_Init(); SystemClock_Config(); MX_GPIO_Init();
MX_USART1_UART_Init(); printf("===========\r\n");
HMC5883L_Init();
for(int i=0;i<13;i++)
{
printf("%d:%d\r\n",i,Single_Read_HMC5883(i));
}
while (1)
{
Multiple_Read_HMC5883(); //连续读取三轴角度数据,存储在BUF中
printf("x:%d\r\ny:%d\r\nz:%d\r\n",x,y,z);
printf("=================================\r\n");
HAL_Delay(1000);
}
}

主程序

下面看一下串口输出结果:

上面输出的0~12是相对应的寄存器值,10~12应该是固定值,xyz是读出的三轴场强值。

stm32与地磁传感器HMC5883L的更多相关文章

  1. Android指南针之加速度传感器地磁传感器-android学习之旅(67)

    由于andorid不推荐用传统的方向传感器,推荐用加速度传感器和地磁传感器来构造得到方向传感器的数据,其实主要是z轴的旋转角度 具体代码示例 代码如下 public class MainActivit ...

  2. 博世传感器调试笔记(三)加速度及地磁传感器BMC156

    一.    器件简介:1.    BMC 156是一款整合三轴地磁传感器与三轴(12bit)加速度传感器于一体的传感器,以BMC 150 电子罗盘模块为基础, 并与Bosch Sensortec 2x ...

  3. STM32读取温湿度传感器DHT11和DHT21(AM2301)系列问题

    1.DHT11和DHT21传感器 这两种传感器都是奥松公司的产品,具体的传感器说明书在其官网上有(www.aosong.com). DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合 ...

  4. STM32之光敏电阻传感器模块的使用

    本实验配合2.2寸TFT液晶屏显示,当光弱的时候显示“昏暗”,光强时显示“明亮”. 实验使用的是下图所示的3线光敏电阻传感器模块,用途:光线亮度检测,光线亮度传感器,智能小车寻光模块.模块特色:比较器 ...

  5. 玩转X-CTR100 l STM32F4 l HMC5983/HMC5883L三轴磁力计传感器

    我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ]      本文介绍X-CTR100控制器 扩展HMC ...

  6. MTK6589下传感器框架结构和代码分析以及传感器的参数指标

    MTK6589下传感器框架结构和代码分析以及传感器的参数指标 作者:韩炜彬  中国当代著名嵌入式研究专家 一.      模块框架 1)配置 路径:Alps/mediatek/config/$(pro ...

  7. Android实现传感器应用及位置服务

    Android实现传感器应用及位置服务 开发工具:Andorid Studio 1.3 运行环境:Android 4.4 KitKat 代码实现 这里需用获取加速度传感器和地磁传感器,手机获取旋转的方 ...

  8. Android开发者指南-方位传感器-Position Sensor

    Android开发者指南-方位传感器-Position Sensor 转载自:http://blog.sina.com.cn/s/blog_48d4913001010zsu.html Position ...

  9. 传感器 Sensor 加速度【示例】

    简介 坐标系 x轴:从左到右 y轴:从下到上 z轴:从内到外 这个坐标系与Android 2D API中的不同,传感器中的返回值都以此坐标系为准. SENSOR_TYPE_ACCELEROMETER  ...

随机推荐

  1. minikube dashboard报503的错误

    minikube start之后,minikube dashboard启动web界面报503错误 解决方案,删除掉c盘用户目录下的.kube和.minikube目录,重新启动,具体什么原因导致的呢,也 ...

  2. 你还在手撕微服务?快试试 go-zero 的微服务自动生成

    0. 为什么说做好微服务很难? 要想做好微服务,我们需要理解和掌握的知识点非常多,从几个维度上来说: 基本功能层面 并发控制&限流,避免服务被突发流量击垮 服务注册与服务发现,确保能够动态侦测 ...

  3. 阿里百秀后台管理项目笔记 ---- Day01

    摘要 在此记录一下阿里百秀项目的教学视频的学习笔记,部分页面被我修改了,某些页面效果会不一样,基本操作是一致的,好记性不如烂笔头,加油叭!!! step 1 : 整合全部静态页面 将静态页面全部拷贝到 ...

  4. MeteoInfo 新网站

    MeteoInfo特别是MeteoInfoLab的推广需要写大量详细的帮助文档和示例程序,MeteoInfo原先的网站使用最原始的编写.html文件的方式来更新,效率实在太低,最近学习了一下Sphin ...

  5. 习题3-4 周期串(Periodic Strings, UVa455)

    #include<stdio.h> #include<string.h> char s[100]; int main() { int T; scanf("%d&quo ...

  6. ansible通过yum/dnf模块给受控机安装软件(ansible2.9.5)

    一,使用yum/dnf模块要注意的地方: 使用dnf软件安装/卸载时,需要有root权限, 所以要使用become参数 说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnb ...

  7. 通过命令行上传ipa到appstore

    搞持续集成自动化打包上传到appstore遇到这个问题,记录一下. 其实主要就一条到命令: xcrun altool --upload-app -f xxxx.ipa -u "yanqizh ...

  8. Java9系列第8篇-Module模块化编程

    我计划在后续的一段时间内,写一系列关于java 9的文章,虽然java 9 不像Java 8或者Java 11那样的核心java版本,但是还是有很多的特性值得关注.期待您能关注我,我将把java 9 ...

  9. 浏览器缓存引起的bug总结

    缓存原理 浏览器缓存分为强缓存和协商缓存 先检查是否过期,没有过期直接使用本地缓存.如果过期,查看是否使用协商缓存 协商缓存流程: 后端返回headers: ETag: W/"1e3-175 ...

  10. liunx 免密登录远程主机

    #!/bin/bash #Program: # no password login in hosts #History: # hbl 2017/12/9 1.0.0v function auto-lo ...