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 ...
随机推荐
- vue 下载jquery 下载layui-layer 下载vue-router
1.下载jquery cmd:语句 npm install jquery 然后在main.js文件里面写 import $ from 'jquery' 2.下载layui-layer 在vue里面的l ...
- c 判断端口是否已被使用
isPortOpen.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include & ...
- C#与sql进行图片存取
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Da ...
- 在Linux命令行内的大小写转换
在编辑文本时大小写常常是需要注意的地方,大小写的转换是很枯燥而繁琐的工作,所幸,Linux 提供了很多能让这份工作变得容易的命令.接下来让我们看看都有哪些完成大小写转换的命令. tr 命令 tr (t ...
- 【小白学PyTorch】21 Keras的API详解(下)池化、Normalization层
文章来自微信公众号:[机器学习炼丹术].作者WX:cyx645016617. 参考目录: 目录 1 池化层 1.1 最大池化层 1.2 平均池化层 1.3 全局最大池化层 1.4 全局平均池化层 2 ...
- 会用Docker的人都别装了,这多简单呐
学术又官方的说法 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器或Windows 机器上,也可以实现虚拟化,容器是 ...
- cookie和session可以参考的文章
cookie和session可以参考的文章 cookie:http://www.lemfix.com/topics/5session:https://www.cnblogs.com/nickjiang ...
- for循环结构中的3个表达式缺一不可?
do-while循环结构结束条件是while后的判断语句不成立for循环结构中的3个表达式都可以为空的.
- c#用于时间日期的类型:DateTime
https://blog.csdn.net/qq_42675313/article/details/82155446 写的简洁易懂了
- deconv的弊端
https://chuansongme.com/n/2630693453218 学习到deconvlution会带来棋盘鬼影,比较重要的解决方法就是resize-deconvlution