最近买了个数字罗盘模块,调通后发现很不错,非常灵敏,测试的时候精度在1°以内。连续测量模式下,最快测量、输出速率可达75hz,模块每次测量完毕并将数据更新至寄存器后,其DRDY引脚便产生一个低电平脉冲(可以配置一个外部中断捕获DRDY引脚的下降沿,并在中断服务程序中读取数据),在STM32中可以设置一个下降沿触发的外部中断,并在中断服务程序中调用角度数据读取函数。以下为操作该模块的主要步骤。

一、IIC协议相关操作(单片机作为主机控制时钟线)

宏定义:

//这里用到了STM32的位带区操作,方便实现对一个位的操作
//PB13配置为OD输出,同时外部给上拉电阻,这样既可输出信号给从机,也能
//在PB13为漏极开路状态时接收从机的信号(STM32的IO配置为输出模式时,
//IO口的电平也会不断地被捕获到输入寄存器中)
//PB14配置为推挽输出,PB15配置为浮空输入
#define R_SDA IPB13 // PB13输入寄存器
#define W_SDA OPB13 // PB13输出寄存器
#define W_SCL OPB14 // PB14输出寄存器
#define R_DRDY IPB15 // PB15输入寄存器
#define Xmsb 0     //X轴数字量的高8位
#define Xlsb 1 //X轴数字量的低8位
#define Zmsb 2 //Z轴数字量的高8位
#define Zlsb 3 //Z轴数字量的低8位
#define Ymsb 4 //Y轴数字量的高8位
#define Ylsb 5 //Y轴数字量的低8位

附位带宏定义:

#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C
#define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08 #define BITBAND_Addr(Addr,num) ((volatile unsigned long *)(0x42000000+32*(Addr-0x40000000)+4*num)) #define IPB13 *BITBAND_Addr(GPIOB_IDR_Addr,13)
#define OPB13 *BITBAND_Addr(GPIOB_ODR_Addr,13)
#define OPB14 *BITBAND_Addr(GPIOB_ODR_Addr,14)
#define IPB15 *BITBAND_Addr(GPIOB_IDR_Addr,15)

启动IIC传输:

void _iic_Start()
{
W_SCL=;
W_SDA=;
_delay();
W_SDA=; //SCL高时,拉低SDA,表示开始IIC传输,占用总线
_delay();
W_SCL=; //控制SCL
_delay();
}

停止IIC传输:

void _iic_Stop()
{
W_SCL=; //释放SCL(由于没有其他主器件,SCL无需开漏)
W_SDA=;
_delay();
W_SDA=; //SCL为高时,拉高SDA表示结束ICC传输,释放总线
}

发送一个字节:

uint8_t _iic_SendByte(uint8_t dat)
{
uint8_t i;
for(i=;i<;i++)
{
_delay();
W_SDA=dat>>; //SCL拉高之前写SDA
dat=dat<<;
_delay();
W_SCL=; //拉高SCL,从器件开始读取SDA
_delay();
W_SCL=; //重新拉低SCL
}
W_SDA=; //释放SDA
W_SCL=; //拉高SCL,读取从器件应答信号
// 等待应答
i=;
while(i&&R_SDA) {i--;_delay();}
if(i==) //无应答
{
W_SCL=; //重新拉低SCL
return ;
}
else { //有应答
_delay();
W_SCL=; //重新拉低SCL
return ;
}
}

接收一个字节:

uint8_t _iic_ReadByte(uint8_t Ack)
{
uint8_t temp,i;
W_SDA=; //释放SDA
_delay();
for(i=;i<;i++)
{
_delay();
W_SCL=; //拉高SCL开始读取SDA
temp=temp<<;
temp|=R_SDA; //SCL拉高之后读取SDA
W_SCL=; //拉低SCL,从器件开始放置数据
}
//发送应答信号
if(Ack)W_SDA=; //拉低SDA表示应答
W_SCL=; //拉高SCL,从器件接收应答信号
_delay();
W_SCL=; //重新拉低SCL
W_SDA=; //释放SDA
return temp;
}

二、配置HMC5883L模块

 void HMC5883L_Init()
{
_iic_Start();
_iic_SendByte(0x3c); //写操作
_iic_SendByte(0x00); //指针指向00,配置寄存器A
_iic_SendByte(0x78); //数据测量、输出速率75hz
_iic_Start(); //指针定位到02,模式寄存器
_iic_SendByte(0x3c);
_iic_SendByte(0x02);
_iic_SendByte(0x00); //连续测量模式
_iic_Stop();
}

三、读取角度数据

接收三轴数据,处理X,Y轴的数据并计算角度:

int16_t HMC5883L_ReadAngle()
{
static uint8_t i;
static uint8_t XYZ_Data[]; //用来存储三个轴输出的数字量 _iic_Start();
_iic_SendByte(0x3c); // 发送HMC5883L的器件地址0x3c,写操作
_iic_SendByte(0x03); //指针指向03,X msb寄存器
_iic_Start();
_iic_SendByte(0x3d); //改为读操作 //依次读取三个轴的数字量
for(i=;i<;i++) //前5次读取发送应答信号
{
XYZ_Data[i]=_iic_ReadByte();
}
XYZ_Data[] =_iic_ReadByte(); //不应答
_iic_Stop();
return atan2( (double)((int16_t)((XYZ_Data[Ymsb]<<)+XYZ_Data[Ylsb]) ),(double)((int16_t)((XYZ_Data[Xmsb]<<)+XYZ_Data[Xlsb])))*(/3.14159265)+; //计算角度,需要包含math.h头文件
}

配置好IO口,调用HMC5883L_Init()后,便可调用HMC5883L_ReadAngle()读取角度值,0~360°。

以下为测试时的截图:

测试时,模块比较灵敏且精确,稍微旋转模块便有精确的变化。由于该模块是基于对地磁场的测量,此模块容易受到其他磁场的干扰,比如将该模块靠近直流电机时,

便会因为电机内的磁场而降低精度甚至失灵(之前做智能小车时就遇到这个问题,要将电机内的磁场屏蔽起来才行)。

(完)

基于STM32的三轴数字罗盘HMC5883L模块的测试的更多相关文章

  1. 张高兴的 Windows 10 IoT 开发笔记:三轴数字罗盘 HMC5883L

    注意,数据不包含校验,准确的来说我不知道怎么校验,但方向看起来差不多是对的... GitHub:https://github.com/ZhangGaoxing/windows-iot-demo/tre ...

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

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

  3. Arduino I2C + 三轴加速度计ADXL345

    ADXL345是ADI公司生产的三轴数字加速度计芯片,与ST的LIS3DH功能接近.主要特性有: 工作电压:2.0 ~ 3.6V 功耗:待机功耗0.1μA:工作时与数据输出频率(ODR)有关,如ODR ...

  4. 【传感器】BMA253 数字,三轴加速度传感器

    参考文档:BMA253E DataSheet 参考文档链接 密码:9new BMA253 数字,三轴加速度传感器 关键特性: 关键特性   封装方式 LGA封装(12pins),长*宽(2mm*2mm ...

  5. 基于STM32的学习型通用红外遥控设备的设计实现(三)

    CPU: STM32 调试平台: STM32F103ZET和STM32F103VBT 软件平台: Keil uVision4 电路设计: Altium Designer v6.9 http://blo ...

  6. Keil MDK STM32系列(三) 基于标准外设库SPL的STM32F407开发

    Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...

  7. 我的嵌入式Qt开发第一课——基于BBB和hmc5843三轴电子罗盘

    几次想照着课本系统地学习Qt,但我发现还是有详细问题驱动时学习比較快. 于是我给自己设定了这个任务: 读取HMC5843的三轴磁场强度值,计算出角度,并把角度用直观形式显示在图形界面上. 这里面涉及到 ...

  8. 基于STM32的uCGUI移植和优化

    基于STM32的uCGUI移植和优化 首先在开始这个说明之前,要简要说明下具体的环境: 编译工具:MDK4.20 开发板:安富莱v2版开发板 调试器:JLink  v8盗版 移植篇 相信大家有移植经验 ...

  9. 【雕爷学编程】Arduino动手做(48)---三轴ADXL345模块

    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践(动手试试)出真知的理念,以学习和交流为目的,这里准备 ...

随机推荐

  1. statu 设置

    DATA: itab TYPE TABLE OF sy-ucomm. APPEND 'DELE' TO itab. APPEND 'PICK' TO itab. SET PF-STATUS 'STA3 ...

  2. 快照COW

    What is Copy-on-write? Copy-on-write      Copy-on-write (sometimes referred to as "COW") i ...

  3. 3django url name详解

    打开urls.py from django.conf.urls import url from django.contrib import admin from calc import views a ...

  4. Python 列表解析list comprehension和生成表达式generator expression

    如果想通过操作和处理一个序列(或其他的可迭代对象)来创建一个新的列表时可以使用列表解析(List comprehensions)和生成表达式(generator expression) (1)list ...

  5. [原创]java WEB学习笔记29:Cookie Demo 之自动登录

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  6. ll指令输出解析

    从左到右: 文件属性 共有10-11位,分别表示: 1.表示目标属性,d目录,l连结文件,-文件 2-4,owner权限,顺序为: r可读.w可写.x可执行,例如: rwx可读写执行,rw-可读写不能 ...

  7. Java -- 表达式类型的自动提升

    1. 提升规则: a. 所有byte型,short型和char型将被提升到int型. b. 整个算数表达式的数据类型自动提升到与表达式中最高等级操作数同样的类型. 例1: short val = 5; ...

  8. JAVA发送手机短信

    <p><span>JAVA发送手机短信,流传有几种方法:(1)使用webservice接口发送手机短信,这个可以使用sina提供的webservice进行发送,但是需要进行注册 ...

  9. PHP中include路径的解决方法汇总

    这几天整理一份很乱的代码,这才意识到php对include处理不是一般的贱:别的编程语言在处理include中的相对目录时,都是以当前处理的文件作为基准.也就是说,如果A包含B,B包含C时,C再包含一 ...

  10. node.js+express+jade系列五:ajax登录

    本文通过jquery实现简单的无刷新登录 1:首先要在router中配置登录请求,因为登录需要传user和pwd考虑到安全需用post请求 {        path:'/',        meth ...