基于STM32的三轴数字罗盘HMC5883L模块的测试

最近买了个数字罗盘模块,调通后发现很不错,非常灵敏,测试的时候精度在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=1;
     W_SDA=1;
     _delay();
     W_SDA=0;     //SCL高时,拉低SDA,表示开始IIC传输,占用总线
     _delay();
     W_SCL=0;     //控制SCL
     _delay();
}

停止IIC传输:

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

发送一个字节:

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

接收一个字节:

uint8_t _iic_ReadByte(uint8_t Ack)
{
     uint8_t temp,i;
     W_SDA=1;              //释放SDA
     _delay();
    for(i=0;i<8;i++)
    {
        _delay();
        W_SCL=1;          //拉高SCL开始读取SDA
        temp=temp<<1;
        temp|=R_SDA;      //SCL拉高之后读取SDA
        W_SCL=0;              //拉低SCL,从器件开始放置数据
     }
     //发送应答信号
    if(Ack)W_SDA=0;             //拉低SDA表示应答
    W_SCL=1;             //拉高SCL,从器件接收应答信号
    _delay();
    W_SCL=0;             //重新拉低SCL
    W_SDA=1;             //释放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[6]; //用来存储三个轴输出的数字量

_iic_Start();
_iic_SendByte(0x3c); // 发送HMC5883L的器件地址0x3c,写操作
_iic_SendByte(0x03); //指针指向03,X msb寄存器
_iic_Start();
_iic_SendByte(0x3d); //改为读操作

//依次读取三个轴的数字量
for(i=0;i<5;i++)        //前5次读取发送应答信号
{
XYZ_Data[i]=_iic_ReadByte(1);
}
XYZ_Data[5] =_iic_ReadByte(0);  //不应答
_iic_Stop();
return atan2( (double)((int16_t)((XYZ_Data[Ymsb]<<8)+XYZ_Data[Ylsb]) ),(double)((int16_t)((XYZ_Data[Xmsb]<<8)+XYZ_Data[Xlsb])))*(180/3.14159265)+180;       //计算角度,需要包含math.h头文件
}

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

以下为测试时的截图:

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

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

(完)

时间: 05-26

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

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

原文:张高兴的 Windows 10 IoT 开发笔记:三轴数字罗盘 HMC5883L 注意,数据不包含校验,准确的来说我不知道怎么校验,但方向看起来差不多是对的... GitHub:https://github.com/ZhangGaoxing/windows-iot-demo/tree/master/HMC5883L

Arduino I2C + 三轴加速度计ADXL345

ADXL345是ADI公司生产的三轴数字加速度计芯片,与ST的LIS3DH功能接近.主要特性有: 工作电压:2.0 ~ 3.6V 功耗:待机功耗0.1μA:工作时与数据输出频率(ODR)有关,如ODR<10 Hz时30μA 接口:I2C:三线/四线制SPI 分辨率:可选择,最大13-bit 内置FIFO single tap/double tap检测 自由落体检测 两个可编程中断输出脚 封装:3 x 5 x 1 mm LGA 管脚定义 与Arduino的连接 用工作于3.3V/8MHz版本的Ar

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

几次想照着课本系统地学习Qt,但我发现还是有详细问题驱动时学习比較快. 于是我给自己设定了这个任务: 读取HMC5843的三轴磁场强度值,计算出角度,并把角度用直观形式显示在图形界面上. 这里面涉及到一些问题,接下来就用问答的形式记录一下. Q1: 搭建Ubuntu-BBB的Qt交叉编译环境.配置触摸屏: A1: http://blog.csdn.net/wyt2013/article/details/18549415 Q2: 去掉Qt界面的标题栏 A2: 在mainwindow.cpp中Mai

基于STM32的四旋翼飞行器的设计与实现

针对四旋翼飞行控制器姿态数据测量易受干扰.算法实现及设计较为困难等问题,设计并实现了以高性价比的STM32F103VET6微处理器作为主控板的四 旋翼飞行器.选用六轴运动组件MPU6050.电子罗盘HMC5883L及气压计MS5611等传感器对飞行器姿态数据进行了实时采集,并结合卡尔曼滤波 方法对姿态数据进行了数据融合.在控制算法上采用了非线性双闭环PID来实现两组四个电机的转速控制,并通过遥控器对四旋翼飞行器的飞行姿态进行实时调 节.飞行试验表明:基于STM32F103VET6微处理器的四旋翼

三轴加速度传感器原理及应用

三轴加速度传感器原理 目前的加速度传感器有多种实现方式,主要可分为压电式.电容式及热感应式三种,这三种技术各有其优缺点.以电容式3轴加速度计的技术原理为例.电容式加速度计能够感测不同方向的加速度或振动等运动状况.其主要为利用硅的机械性质设计出的可移动机构:由于加速度使得机械悬臂与两个电极之间的距离发生变化,从而改变了两个电容的参数.通过集成的开关电容放大电路量测电容参数的变化,形成了与加速度成正比的电压输出.因此3轴加速度传感器必然包含一个单纯的机械性MEMS传感器和一枚ASIC接口芯片两部分,

基于STM32的RFID射频识别技术 韦根协议C语言驱动解码程序

RFID工作原理 RFID技术的基本工作原理并不复杂:标签进入磁场后,接收解读器发出的射频信号,凭借感应电流所获得的能量发送出存储在芯片中的产品信息(无源标签或被动标签),或者由标签主动发送某一频率的信号(Active Tag,有源标签或主动标签),解读器读取信息并解码后,送至中央信息系统进行有关数据处理. 一套完整的RFID系统, 是由阅读器与电子标签也就是所谓的应答器及应用软件系统三个部份所组成,其工作原理是Reader发射一特定频率的无线电波能量,用以驱动电路将内部的数据送出,此时Read

【翻译】利用加速度求解位置的算法——三轴传感器

摘要 此文档描述并使用MMA7260QT三轴加速计和低功耗的9S08QG8八位单片机实现求解位置的算法 . 在今天先进的电子市场,有不少增加了许多特性和智能的多功能的产品.定位和游戏只是得益于获取到的位置信息的一部分市场.一个获取这种信息的可选方案是通过使用惯性传感器.从这些传感器中取得的信号需要进行一些处理,因为在加速度和位置之间没有一种直接转换. 为了获得位置,需要对加速度进行二次积分.本文介绍一种简单的算法实现加速度的二重积分.为了获取加速度的二重积分,一个简单的积分要进行两次,因为这样也

基于STM32的USB枚举过程学习笔记

源:基于STM32的USB枚举过程学习笔记 基于STM32的USB枚举过程学习笔记(一) 基于STM32的USB枚举过程学习笔记(二) 基于STM32的USB枚举过程学习笔记(三) 基于STM32的USB枚举过程学习笔记(四) 基于STM32的USB枚举过程学习笔记(五)

[转]四旋翼飞行器 - 基于stm32

原文地址:http://www.cnblogs.com/moranBlogs/p/3684275.html 期待我也可以做出一个飞行器来!! 尝试制作这个四旋翼飞控的过程,感触颇多,整理了思绪之后,把重要的点一一记下来: 这个飞控是基于STM32,整合了MPU6050,即陀螺仪和重力加速计,但没有融合电子罗盘: 另外,四旋翼飞行器的运动方式请百度百科,不太复杂,具体不再赘述: 这是飞控程序的控制流程(一个执行周期): 比较重要的地方: 1.i2c通信方式: 因为我不是学电类专业,最开始对i2c这