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 ...
随机推荐
- mac常用指令
mkdir demo //创建一个文件夹 touch index.html // 创建一个html文件 rm rouch index.html //删除找个index.html文件 rmdir dem ...
- Python 中 pip 工具的安装与使用
pip 是 Python 包管理工具,该工具提供了对Python 包的查找.下载.安装.卸载的功能. 目前如果你在 python.org 下载最新版本的安装包,则是已经自带了该工具. Python 2 ...
- RHSA-2017:2299-中危: NetworkManager 和 libnl3 安全和BUG修复更新(本地提权、代码执行)
[root@localhost ~]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) 修复命令: 使用root账号登陆She ...
- python进程开启的两种方式
一.进程 1.1.方式一 from multiprocessing import Process import time #方式一 def task(name): print(f"my na ...
- 多路复用select和epoll的区别(转)
先说下本文框架,先是问题引出,然后概括两个机制的区别和联系,最后介绍每个接口的用法 一.问题引出 联系区别 问题的引出,当需要读两个以上的I/O的时候,如果使用阻塞式的I/O,那么可能长时间的阻塞在一 ...
- 关于ptype_all和pypte_base中的pt_prev的说明[转]
不知道原帖,我是从这里看到了,解决了迷惑我很久的疑问,抄过来. 看见noble_shi兄弟"关于net_rx_action函数的若干问题"贴中关于pt_prev的问题, 本来想在论 ...
- 利用Turtle绘制各种图形
首先引入函数库: 第一种: import turtle import turtle as t 第二种: from turtle import * 1:使用 turtle 库的 turtle.fd() ...
- java字符流与字节流的区别是什么
java中字符流与字节流的区别: 1.字节流操作的基本单元为字节:字符流操作的基本单元为Unicode码元. 2.字节流默认不使用缓冲区:字符流使用缓冲区. 3.字节流通常用于处理二进制数据,实际上它 ...
- Hash算法简介
Hash算法性质 Hash算法用于计算消息摘要(Message Digest),可以将任意长的输入信息快速地转换为固定长度的输出.在区块链中主要利用了Hash算法的三种性质: 抗冲突性(Collisi ...
- 扫描仪扫描文件处理-ABBYY对扫描版PDF文字加黑加粗、去除背景漂白
1. 设置ABBYY自动歪斜矫正: 2. 设置导出PDF参数: 3. PDF文字加黑加粗.去除背景漂白步骤:3.1 ABBYY - 打开扫描版PDF文档3.2 ABBYY - 编辑图像3.3 等级 - ...