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 ...
随机推荐
- js 正则表达式 判断val是不是整数
function isIntNum(val){ var regPos = / ^\d+$/; // 非负整数 // var regNeg = /^\-[1-9][0-9]*$/; // 负整数 if( ...
- Linux批量查找与替换
Linux批量查找并替换文件夹下所有文件的内容 经常要使用到 Linux的批量查找与替换,这里为大家介绍使用 sed 命令和 grep 命令的结合来实现查找文件中的内容并替换. 语法格式: sed - ...
- 实验二 HTML中图片和超链接的应用
实验二 HTML中图片和超链接的应用 [实验目的] 1.通过本例要求掌握常见的图像格式及图像的插入方法. 2.能够修改图像属性,利用外部图像处理软件编辑图像. 3.掌握设置各类超级连接的方法. 4.灵 ...
- linux内存优化之手工释放linux内存
先介绍下free命令 Linux free命令用于显示内存状态. free指令会显示内存的使用情况,包括实体内存,虚拟的交换文件内存,共享内存区段,以及系统核心使用的缓冲区等. 语法: free [- ...
- shell脚本算术运算
自增自减操作 用let命令可以实现自增自减的命令,不需要$符号: #!/bin/bash set -e n=100 let n++ echo $n 还可以实现自增自减指定的值: #!/bin/bash ...
- selenium常用操作学习笔记
一,弹窗处理(推荐文章:https://blog.csdn.net/huilan_same/article/details/52298460) selenium提供switch_to方法定位弹窗的对话 ...
- 很多人都搞不清楚C语言和C++的关系!今天我们来一探究竟为大家解惑~
最近,身边有许多小伙伴已经开始学习编程了,但是呢,学习又会碰到许多的问题,其中作为新手小白提到最多的问题就是编程语言的选择. 每次遇到这种问题,看起来很简单,但是又有很多小伙伴搞不清编程语言之间的关系 ...
- NLP任务梳理总结
NLP任务 前处理任务 前处理任务的结果可作为下游任务输入的额外特征. POSTa(词性标注) 往模型中输入句子,对每一个token进行词性的识别. 识别出的词性可以用于下游任务. Word Segm ...
- java应用启动报错Unable to access jarfile xxxxx.jar
当使用命令:javar -jar xxxx.jar 启动应用时,报错Unable to access jarfile xxxxx.jar,这种主要是 jar 的名称或者路径有问题:
- 对于72种常用css3的使用经验
对于72种常用css3的使用经验 保存网站源码 目的 保证有足够的css和js文件源码 拿到当前网页的整体布局 本地化 创建web项目 将web项目创建出来 在项目中创建一个文件夹 将所有的js和cs ...