stm32与地磁传感器HMC5883L
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

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

模式寄存器


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

数据输出 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的更多相关文章
- Android指南针之加速度传感器地磁传感器-android学习之旅(67)
由于andorid不推荐用传统的方向传感器,推荐用加速度传感器和地磁传感器来构造得到方向传感器的数据,其实主要是z轴的旋转角度 具体代码示例 代码如下 public class MainActivit ...
- 博世传感器调试笔记(三)加速度及地磁传感器BMC156
一. 器件简介:1. BMC 156是一款整合三轴地磁传感器与三轴(12bit)加速度传感器于一体的传感器,以BMC 150 电子罗盘模块为基础, 并与Bosch Sensortec 2x ...
- STM32读取温湿度传感器DHT11和DHT21(AM2301)系列问题
1.DHT11和DHT21传感器 这两种传感器都是奥松公司的产品,具体的传感器说明书在其官网上有(www.aosong.com). DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合 ...
- STM32之光敏电阻传感器模块的使用
本实验配合2.2寸TFT液晶屏显示,当光弱的时候显示“昏暗”,光强时显示“明亮”. 实验使用的是下图所示的3线光敏电阻传感器模块,用途:光线亮度检测,光线亮度传感器,智能小车寻光模块.模块特色:比较器 ...
- 玩转X-CTR100 l STM32F4 l HMC5983/HMC5883L三轴磁力计传感器
我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] 本文介绍X-CTR100控制器 扩展HMC ...
- MTK6589下传感器框架结构和代码分析以及传感器的参数指标
MTK6589下传感器框架结构和代码分析以及传感器的参数指标 作者:韩炜彬 中国当代著名嵌入式研究专家 一. 模块框架 1)配置 路径:Alps/mediatek/config/$(pro ...
- Android实现传感器应用及位置服务
Android实现传感器应用及位置服务 开发工具:Andorid Studio 1.3 运行环境:Android 4.4 KitKat 代码实现 这里需用获取加速度传感器和地磁传感器,手机获取旋转的方 ...
- Android开发者指南-方位传感器-Position Sensor
Android开发者指南-方位传感器-Position Sensor 转载自:http://blog.sina.com.cn/s/blog_48d4913001010zsu.html Position ...
- 传感器 Sensor 加速度【示例】
简介 坐标系 x轴:从左到右 y轴:从下到上 z轴:从内到外 这个坐标系与Android 2D API中的不同,传感器中的返回值都以此坐标系为准. SENSOR_TYPE_ACCELEROMETER ...
随机推荐
- postgreSQL与Kingbase 字符串裁剪区别
--postgreSQL postgres=# select substring('abcdefg',0,4); substring abc (1 行记录) postgres=# select sub ...
- Python+Appium自动化测试(10)-TouchAction类与MultiAction类(控件元素的滑动、拖动,九宫格解锁,手势操作等)
滑动屏幕方法swipe一般用于对页面进行上下左右滑动操作,但自动化过程中还会遇到其他情况,如对控件元素进行滑动.拖拽操作,九宫格解锁,手势操作,地图的放大与缩小等.这些需要针对控件元素的滑动操作,或者 ...
- 强大的table组件-antd pro table
概述 antd pro table antd pro table 的主要部分 表格显示的配置(绿色框内) 检索的配置(红色框内) 是否显示检索部分 检索的内容是如何生效的 工具栏的配置(黄色框内) 表 ...
- golang API 请求队列
概要 实现思路 使用方法 启动队列服务 使用队列服务 概要 在调用第三方 API 的时候, 基本都有访问限速的限制条件. 第三方的 API 有多个的时候, 就不太好控制访问速度, 常常会导致 HTTP ...
- Vue 学习 二 路由详解
1 roter-link 和roter-view组件 2路由配置 a.动态路由 b.嵌套路由 c.别名路由 d.命名路由 3 Js操作路由 4 重定向和别名 1为路由默认绑定 2 使用组件 根据 路由 ...
- 多测师讲解 _接口自动化框架设计_高级讲师肖sir
背景:因为把传入接口参数.组建测试用例.执行测试用例和发送报告,都放入一个.py文件对于接口的使用非常不灵活就需要数据和接口业务进行分离让代码之间的 耦合性降低.和实现接口的分层管理,所以需要对代码进 ...
- Android开发还不会这些?如何面试拿高薪!
我所接触的Android开发者,百分之九十五以上 都遇到了以下几点致命弱点! 如果这些问题也是阻止你升职加薪,跳槽大厂的阻碍. 那么我确信可以帮你突破瓶颈! 群内有许多来自一线的技术大牛,也有在小厂或 ...
- 分布式锁结合SpringCache
1.高并发缓存失效问题: 缓存穿透: 指查询一个一定不存在的数据,由于缓存不命中导致去查询数据库,但数据库也无此记录,我们没有将此次查询的null写入缓存,导致这个不存在的数据每次请求都要到存储层进行 ...
- Linux+Nginx/Apache下的PHP exec函数执行Linux命令
1.php.ini配置文件 打开PHP的配置文件,里面有一行 disable_function 的值,此处记录了禁止运行的函数,在里面将exec和shell_exec.system等函数删除. 2.权 ...
- 微信小程序的账号找回。
之前注册过微信小程序,好久没用了,马上要开发微信小程序了,我今天登陆了一下突然发现 然后点击账号找回,按照流程同意点击下一步,到第二部时要输入搜索框里的提示. 这时的我早已忘了,百度搜了一下如何找回原 ...