关于磁力计HMC5883L型号探索

一.序言

在众多磁力计中,HMC5883L因为其廉价实用而受到大多数嵌入式开发小白的追捧。然而某宝上不仅仅有HMC5883L这一款,还有QMC5883和HMC5983,常有商家搞不清芯片就出售,导致提供的数据手册不对应。同时,不同单片机对IIC的操作也略有差异,对小白而言也是件头疼的事情。

HMC5883L与QMC5883L区别对比

可以看到,QMC5883L的各寄存器地址与HMC5883L区别还是不小。这样,移植时候程序整体结构不用大改,把寄存器改掉即可。

(1)      修改I2C address

0x3C -> 0x1A

0x3D -> 0x1B

(2)      X/Y/Z Register

起始:0x03 -> 0x00

顺序:X-Z-Y -> X-Y-Z

(3)      Mode Register

0x02 -> 0x09

0x00 -> 0x01

二.HMC5983

HMC5983是HMC5883L的“加强版”,寄存器与5883基本一致,但同时支持I2C和SPI两种通信模式,更加快捷。因此,使用方法与5883几乎没有差别。这里,本人将官方提供的测试程序修改为STC15系列单片机,主要移植I2C通信中时序函数。

本人增加了一个定任意方向为0度的功能,主要为了解决各类机器人竞赛中场地不一定何种角度朝向的问题。不过由于时间仓促没有来的及写滤波。思路就是将坐标系进行转换。贴出程序,仅供参考。

1.电路图

2.所需元件

STC15W408AS    x1

HMC5983        x1

1k电阻          x1

独立按键        x1

排针           若干

洞洞板          x1

3.程序结构

4.源码

(1)user_config.h

/*-----------------------------------------用户配置文件-------------------------------------------*/
#ifndef _CONFIG_H_
#define _CONFIG_H_/*  宏定义  */
#define   uchar unsigned char
#define   uint  unsigned int    typedef unsigned char BYTE;
typedef unsigned short WORD;/*  包含头文件  */
#include <STC15F2K60S2.H>
#include  <math.h>    //Keil library
#include  <stdio.h>   //Keil library
#include  <INTRINS.H>
//USER Library
#include "HMC5983_Driver.h"
#include "HMC5983_Software.h"
#include "uart.h"
#include "delay.h"
#include "interrupt.h"//#include "LQ12864.h"//使用的端口,请按照以下接线
sbit    SCL=P3^2;      //IIC时钟引脚定义
sbit    SDA=P3^3;      //IIC数据引脚定义
sbit  KEY=P3^6;      //按键
//sfr INT_CLKO = 0x8f; //外部中断与时钟输出控制寄存器//全局变量引入
extern BYTE BUF[8];
extern uchar ge,shi,bai,qian,wan;           //显示变量
extern int  dis_data;                       //变量
extern double angle_ch;
#endif

(2)HMC5983_Driver.h

/*------------------------------------HMC5983驱动文件-------------------------------------*/
#ifndef _HMC5983_DRIVER_H_
#define _HMC5983_DRIVER_H_#define   SlaveAddress   0x3C       //定义器件5883在IIC总线中的从地址//************
//函数
//************void Init_HMC5883(void);            //初始化5883void  Single_Write_HMC5883(uchar REG_Address,uchar REG_data);   //单个写入数据
//uchar Single_Read_HMC5883(uchar REG_Address);                   //单个读取内部寄存器数据
void  Multiple_Read_HMC5883(void);                                  //连续的读取内部寄存器数据
//以下是模拟iic使用函数-------------
void HMC5883_Start(void);
void HMC5883_Stop(void);
void HMC5883_SendACK(bit ack);
bit  HMC5883_RecvACK(void);
void HMC5883_SendByte(BYTE dat);
BYTE HMC5883_RecvByte(void);
void HMC5883_ReadPage(void);
void HMC5883_WritePage(void);#endif

(3)interrupt.h

/*--------------------------中断服务头文件---------------------------*/
#ifndef _IT_H_
#define _IT_H_#define Init_INT2() INT_CLKO |= 0x10#endif

(4)uart.c

/*-----------------------------------串口配置STC15F408AS内置晶振波特率 9600 bps------------------------------------*/#include "user_config.h"BYTE BUF[8];                         //接收数据缓存区   //*********************************************
//串口初始化
//9600 bps @ 11.059 MHz
void init_uart(void)
{SCON  = 0x50;AUXR |= 0x04;T2L   = 0xa0;T2H   = 0xfc;AUXR |= 0x10;TI    = 1;EA    = 1;
}//*********串口数据发送******************
void SeriPushSend(uchar send_data)
{SBUF = send_data;  while(!TI);TI=0;
}

(5)interrupt.c

/*-----------------------------中断服务-----------------------------*/
#include "user_config.h"double angle_ch = 0;void KEY_DOWN(void) interrupt 10
{Delay5ms();if(KEY == 0){while(!KEY);angle_ch = Angle_Update();}
}

(6)HMC5983_Driver.c

//***************************************
// HMC5883 51串口测试程序
// 使用单片机STC89C51
// 晶振:11.0592M
// 显示:PC串口
// 编译环境 Keil uVision2
// 参考宏晶网站24c04通信程序
// 时间:2011年3月1日
//****************************************#include "user_config.h"
#include "HMC5983_Driver.h"int  dis_data;                       //变量//-----------------------------------/**************************************
起始信号
**************************************/
void HMC5883_Start(void)
{SDA = 1;                    //拉高数据线SCL = 1;                    //拉高时钟线Delay5us();                 //延时SDA = 0;                    //产生下降沿Delay5us();                 //延时SCL = 0;                    //拉低时钟线
}/**************************************
停止信号
**************************************/
void HMC5883_Stop(void)
{SDA = 0;                    //拉低数据线SCL = 1;                    //拉高时钟线Delay5us();                 //延时SDA = 1;                    //产生上升沿Delay5us();                 //延时
}/**************************************
发送应答信号
入口参数:ack (0:ACK 1:NAK)
**************************************/
void HMC5883_SendACK(bit ack)
{SDA = ack;                  //写应答信号SCL = 1;                    //拉高时钟线Delay5us();                 //延时SCL = 0;                    //拉低时钟线Delay5us();                 //延时
}/**************************************
接收应答信号
**************************************/
bit HMC5883_RecvACK(void)
{SCL = 1;                    //拉高时钟线Delay5us();                 //延时CY = SDA;                   //读应答信号SCL = 0;                    //拉低时钟线Delay5us();                 //延时return CY;
}/**************************************
向IIC总线发送一个字节数据
**************************************/
void HMC5883_SendByte(BYTE dat)
{BYTE i;for (i=0; i<8; i++)         //8位计数器{dat <<= 1;              //移出数据的最高位SDA = CY;               //送数据口SCL = 1;                //拉高时钟线Delay5us();             //延时SCL = 0;                //拉低时钟线Delay5us();             //延时}HMC5883_RecvACK();
}/**************************************
从IIC总线接收一个字节数据
**************************************/
BYTE HMC5883_RecvByte(void)
{BYTE i;BYTE dat = 0;SDA = 1;                    //使能内部上拉,准备读取数据,for (i=0; i<8; i++)         //8位计数器{dat <<= 1;SCL = 1;                //拉高时钟线Delay5us();             //延时dat |= SDA;             //读数据               SCL = 0;                //拉低时钟线Delay5us();             //延时}return dat;
}//***************************************************void Single_Write_HMC5883(uchar REG_Address,uchar REG_data)
{HMC5883_Start();                  //起始信号HMC5883_SendByte(SlaveAddress);   //发送设备地址+写信号HMC5883_SendByte(REG_Address);    //内部寄存器地址,请参考中文pdf HMC5883_SendByte(REG_data);       //内部寄存器数据,请参考中文pdfHMC5883_Stop();                   //发送停止信号
}/*
//********单字节读取内部寄存器*************************
uchar Single_Read_HMC5883(uchar REG_Address)
{uchar REG_data;HMC5883_Start();                          //起始信号HMC5883_SendByte(SlaveAddress);           //发送设备地址+写信号HMC5883_SendByte(REG_Address);                   //发送存储单元地址,从0开始  HMC5883_Start();                          //起始信号HMC5883_SendByte(SlaveAddress+1);         //发送设备地址+读信号REG_data=HMC5883_RecvByte();              //读出寄存器数据HMC5883_SendACK(1);   HMC5883_Stop();                           //停止信号return REG_data;
}
*/
//******************************************************
//
//连续读出HMC5883内部角度数据,地址范围0x3~0x5
//
//******************************************************
void Multiple_read_HMC5883(void)
{   uchar i;HMC5883_Start();                          //起始信号HMC5883_SendByte(SlaveAddress);           //发送设备地址+写信号HMC5883_SendByte(0x03);                   //发送存储单元地址,从0x3开始   HMC5883_Start();                          //起始信号HMC5883_SendByte(SlaveAddress+1);         //发送设备地址+读信号for (i=0; i<7; i++)                      //连续读取6个地址数据,存储中BUF{BUF[i] = HMC5883_RecvByte();          //BUF[0]存储0x32地址中的数据if (i == 6){HMC5883_SendACK(1);                //最后一个数据需要回NOACK}else{HMC5883_SendACK(0);                //回应ACK}}HMC5883_Stop();                          //停止信号Delay5ms();
}//初始化HMC5883,根据需要请参考pdf进行修改****
void Init_HMC5883(void)
{Single_Write_HMC5883(0x02,0x00);  //Single_Write_HMC5883(0x01,0xE0);  //
}

(7)HMC5983_Software.c

/*---------------------------------HMC5983  角度变换将任意角度变为0度-----------------------------------*/
#include "user_config.h"uchar ge,shi,bai,qian,wan;           //显示变量double Angle_Update(void)
{int x,y,z,t;Multiple_Read_HMC5883();      //连续读出数据,存储在BUF中x = BUF[0] << 8 | BUF[1]; z = BUF[2] << 8 | BUF[3]; y = BUF[4] << 8 | BUF[5]; t = atan2((double)y,(double)x) * (180 / 3.14159265) + 180; // angle in degreeswhile(abs(t-45) <= 0.001){Multiple_Read_HMC5883();      //连续读出数据,存储在BUF中x = BUF[0] << 8 | BUF[1]; z = BUF[2] << 8 | BUF[3]; y = BUF[4] << 8 | BUF[5]; t = atan2((double)y,(double)x) * (180 / 3.14159265) + 180; // angle in degrees}return t;
}void conversion(uint temp_data)
{  wan=temp_data/10000+0x30 ;temp_data=temp_data%10000;   //取余运算qian=temp_data/1000+0x30 ;temp_data=temp_data%1000;    //取余运算bai=temp_data/100+0x30   ;temp_data=temp_data%100;     //取余运算shi=temp_data/10+0x30    ;temp_data=temp_data%10;      //取余运算ge=temp_data+0x30;
}double Change_Target(void)
{double angle_now = Angle_Update();if(angle_now >= angle_ch) return angle_now-angle_ch;else return 360-angle_ch+angle_now;
}

(8)main.c

/*----------------------------------------------------------基于HMC5983智能电子罗盘2017/10/24        Listen C@ 型号:STC15F408AS@ 晶振:内置33.1776MHz@ 通信:IIC@ 显示:0.96 OLED@ 串口:9600 bps------------------------------------------------------------*/#include <STC15F2K60S2.H>
#include "user_config.h"//*********************************************************
//                  主程序
//*********************************************************void main(void)
{ // bit sign_bit;unsigned int i;double angle;delay(100);Init_INT2();init_uart();Init_HMC5883();while(1)            //循环{ angle = Change_Target();conversion(angle);       //计算数据和显示Delay5ms(); SeriPushSend(0x0d);SeriPushSend(0x0a);SeriPushSend(bai);SeriPushSend(shi);SeriPushSend(ge);}
} 

三.QMC5883L在Arduino上使用

在arduino中,I2C address用的是7位地址而不是8位,所以需要对应将address改掉。

比如QMC5883为0x1a,则二进制为0001_1010。而换算为7位,右移一位二进制为0000_1101。

则十六进制为0x0d。

源码如下:

#include <Wire.h>#define address 0x0d void setup() {//put your setup code here, to run once:Serial.begin(9600);delay(500);Wire.begin();Wire.beginTransmission(address);Wire.write(0x09);Wire.write(0x01);Wire.endTransmission();}void loop() {//put your main code here, to run repeatedly:intx,y,z;Wire.beginTransmission(address);Wire.write(0x00);Wire.endTransmission();Wire.requestFrom(address,6);if(Wire.available() >= 6){x= Wire.read() << 8;x |= Wire.read();y = Wire.read() << 8;y |= Wire.read();z= Wire.read() << 8;z |= Wire.read();}Serial.print("x: ");Serial.print(x);Serial.print("   y: ");Serial.print(y);Serial.print("   z: ");Serial.println(z);delay(250);}

网盘链接:http://pan.baidu.com/s/1gfEje8r 密码:dbvr

【模块学习】关于磁力计HMC5883L型号探索相关推荐

  1. <转载>光模块学习总结

    作者写的非常详细全面,转载到这儿大家一起学习学习. 如有侵权请联删. 作者: 曹世宏 链接: https://cshihong.github.io/2020/08/16/光模块学习总结/ 光模块简介 ...

  2. ESP8266 WIFI模块学习之路(2)——模块与单片机连接进行远程操作

    上一个博客:ESP8266 WIFI模块学习之路(1)是关于对串口连接的,简单验证ESP8266是怎么样连接及其功能验证,下面将通过单片机连接,和手机进行远程操作. ESP8266和单片机的连接,我这 ...

  3. 蓝桥杯模块学习17——AT24C02存储器(深夜学习——单片机)

    一.硬件电路: 1.引脚功能: (1)A0-A2:决定不同设备的地址码: (2)WP:写保护 二.通讯方式(IIC协议) 通讯方式与PCF8591相同,可参考以下文章: 蓝桥杯模块学习16--PCF8 ...

  4. python 的日志logging模块学习

    2019独角兽企业重金招聘Python工程师标准>>> python 的日志logging模块学习 分类: python 2011-08-02 23:51 8338人阅读 评论(0) ...

  5. 【深度学习】计算机视觉相关技术探索(一)

    [深度学习]计算机视觉相关技术探索(一) 文章目录 1 计算机视觉概述 2 使用机器学习解决图像分类问题 3 Keras和神经网络简介 4 卷积神经网络(CNN),迁移学习 5 对象检测问题 6 yo ...

  6. python中configparser_python中confIgparser模块学习

    python中configparser模块学习 ConfigParser模块在python中用来读取配置文件,配置文件的格式跟windows下的ini配置文件相似,可以包含一个或多个节(section ...

  7. python textwrap_python2.7.3编译python模块学习- textwrap 文本包装和填充

    python模块学习- textwrap 文本包装和填充 代码实例: sample_text = ''' The textwrap module can beused to format text f ...

  8. android fm模块学习,AndroidFM模块学习之5关闭FM流程

    AndroidFM模块学习之五关闭FM流程 前一阵子简单描述了一些关于FM开启.录音和搜索的流程,浅析了一下各个类的源码,接下来就是关闭FM了,FM模块的学习就告一段落了,希望这阵子的整理能对大家在F ...

  9. python中的glob 模块学习文件路径查找

    glob glob.glob(pathname), 返回所有匹配的文件路径列表.它只有一个参数pathname,定义了文件路径匹配规则,这里可以是绝对路径,也可以是相对路径. import glob ...

  10. pythontemp_python 临时文件夹 的 tempfile模块学习

    python的临时文件夹的tempfile模块学习 应用程序经常要保存一些临时的信息,这些信息不是特别重要,没有必要写在配置文件 里,但又不能没有,这时候就可以把这些信息写到临时文件里.其实很 多程序 ...

最新文章

  1. 在JavaScript中重复字符串的三种方法
  2. 如何利用Gephi可视化浏览的网站关系
  3. video视频播放以及主流浏览器兼容
  4. jQuery在页面加载的时候自动调用某个函数的方法(转载)
  5. 《mongodb权威指南》学习
  6. SpringBoot中整合Thymeleaf
  7. chinaunix-索引资料
  8. 05-Java通过Executors提供四种线程池
  9. java从入门到精通_Java---开发从入门到精通,分享视频学习教程
  10. Servlet工作原理解析2(以Tomcat为例)
  11. kml文件怎么用arcgis打开_ArcGIS学习记录—KMZ KML与SHP文件互相转换
  12. miou 代码 VOC2012
  13. 【大数据】一图了解大数据发展历程
  14. 成为数据分析师要具备什么能力——招式篇
  15. C++根据三个点坐标计算夹角
  16. 设置默认打印机出现错误。提示无法完成,错误是0x00000709
  17. JavaScript在数组尾部添加元素
  18. mkdir创建目录失败的原因
  19. CTA 策略分享之三 -- 策略优化
  20. 典型可编程接口芯片及应用

热门文章

  1. WinZip 15注册码
  2. SpringBoot代理设置
  3. Paper reading:A simple baseline for one-shot multi-object tracking(二)
  4. 我为什么选择Hexo建站
  5. IDEA自动生成serialVersionUID的设置
  6. SWOT分析流程图模板分享
  7. ubuntu18.04 Nvidia 显卡的风扇调速及startx的后果 --转载
  8. mysql根据经纬度计算距离并排序
  9. 计算机还原默认的配置,每次开电脑bios会恢复默认设置怎么办实测解决
  10. 速达3000 数据库备份文件分析