CDWJ 发表于 2012-12-26 12:12:03

HMC5883L三轴数字罗盘————资料及例程

/**************************************************
================== HMC5883L测试程序===============
** 3-轴数字罗盘
** 协议:IIC    详细读写协议,请参考相关资料
** 时间:2012.2.2
** Author:Keliwen
**************************************************/
#include <reg52.h>
#include <math.h>
#include <stdio.h>
#include <intrins.h>

typedef unsigned char uchar;
typedef unsigned int uint;

/*12232液晶引脚定义*/      
sbit CS=P0^2;
sbit SID=P0^1;
sbit SCLK=P0^0;

sbit SCL=P1^0;      //IIC时钟引脚定义
sbit SDA=P1^1;      //IIC数据引脚定义

#define SlaveAddress 0x3c   //定义器件在IIC总线中的从地址
uchar Rec_Data;


/*延时函数*/
void Delay(uint t)
{
    while(t--)
    {}
}
/********************************************
**LCD显示函数
********************************************/
/*写入一个数据或指令*/
void Send_DATA(uchar Data,uchar A)
{
    uchar i,Dat;
    CS=0;
    switch(A)
    {
      case 0 : Dat=0xf8; break;//写指令
      case 1 : Dat=0xfa; break;//写数据
      default : break;
    }
    SCLK=0;
    CS=1;
    for(i=0;i<8;i++)
    {
      SID=Dat&0x80;
      SCLK=0;
      SCLK=1;
      Dat<<=1;
    }   
    Dat=Data&0xf0;
    for(i=0;i<8;i++)
    {
      SID=Dat&0x80;
      SCLK=0;
      SCLK=1;
      Dat<<=1;
    }
    Dat=(Data<<4);
    for(i=0;i<8;i++)
    {
      SID=Dat&0x80;
      SCLK=0;
      SCLK=1;
      Dat<<=1;
    }   
    CS=0;
    Delay(20);
}
/*12232液晶初始化*/
void LCD_Init(void)
{
    Delay(60000);
    Send_DATA(0x02,0);
    Send_DATA(0x0c,0);
    Send_DATA(0x30,0);
    Send_DATA(0x06,0);
    Send_DATA(0x01,0);
    Delay(3000);
}
/*显示字符串*/
void Dis_str(uchar Addr,uchar *str)
{
    Send_DATA(Addr,0);
    Delay(10);
    while(*str!='\0')
    {
      Send_DATA(*str,1);
      str++;
      Delay(10);
    }
}
/*起始信号*/
void IIC_Start(void)
{
    SDA=1;
    SCL=1;
    Delay(5);
    SDA=0;
    Delay(5);
    SCL=0;
}
/*停止信号*/
void IIC_Stop(void)
{
    SDA=0;
    SCL=1;
    Delay(5);
    SDA=1;
    Delay(5);
}
/*发送应答信号*/
void IIC_SendAck(bit Ack)
{
    SDA=Ack;//ack (0:ACK 1:NACK)
    SCL=1;
    Delay(5);
    SCL=0;
    Delay(5);
}
/*接收应答信号*/
bit IIC_RecAck(void)
{
    SCL=1;
    Delay(5);
    CY=SDA;
    SCL=0;
    Delay(5);
    return CY;
}
/*向IIC总线发送一个字节数据*/
void HMC5883_Send_Byte(uchar Dat)
{
    uchar i;
    for(i=0;i<8;i++)
    {
      Dat<<=1;
      SDA=CY;
      SCL=1;
      Delay(5);
      SCL=0;
      Delay(5);
    }
    IIC_RecAck();
}
/*从IIC总线接收一个字节数据*/
uchar HMC5883_Rec_Byte(void)
{
    uchar i,Dat=0;
    SDA=1;
    for(i=0;i<8;i++)
    {
      Dat<<=1;
      SCL=1;
      Delay(5);
      Dat |=SDA;
      SCL=0;
      Delay(5);
    }
    return Dat;
}
/*单字节写HMC5833*/
void Single_Write_HMC5883(uchar Address,uchar Dat)
{
    IIC_Start();
    HMC5883_Send_Byte(SlaveAddress);
    HMC5883_Send_Byte(Address);
    HMC5883_Send_Byte(Dat);
    IIC_Stop();
}
/*单字节读HMC5833*/
/*uchar Single_Read_HMC5883(uchar Addr)
{
    uchar Value;
    IIC_Start();
    HMC5883_Send_Byte(SlaveAddress);
    HMC5883_Send_Byte(Addr);
    IIC_Start();
    HMC5883_Send_Byte(SlaveAddress+1);
    Value=HMC5883_Rec_Byte();
    IIC_SendAck(1);
    IIC_Stop();
    return Value;
}*/
/*多字节读HMC5833*/
void Multiple_Read_HMC5883(void)
{
    uchar i;//连续读出HMC5883内部角度数据,地址范围0x3~0x5
    IIC_Start();
    HMC5883_Send_Byte(SlaveAddress);
    HMC5883_Send_Byte(0x03);//发送存储单元地址,从0x03开始
    IIC_Start();
    HMC5883_Send_Byte(SlaveAddress+1);
    for(i=0;i<6;i++) //连续读取6个地址数据,存储在Rec_Data
    {
      Rec_Data=HMC5883_Rec_Byte();
      if(i==5)
            IIC_SendAck(1); //最后一个数据需要回NOACK
      else
            IIC_SendAck(0); //回应ACK
    }
    IIC_Stop();
    Delay(100);
}
//初始化HMC5883,根据需要请参考pdf进行修改****
void HMC5883_Init(void)
{
   Single_Write_HMC5883(0x02,0x00);
}
/*主函数*/
void main(void)
{
    int X,Y,Z;
    double Angle;
    uint Acr;

    LCD_Init();//LCD12232液晶初始化
    Dis_str(0x80,"3 轴数字罗盘");
    HMC5883_Init();//HMC5883初始化

    do
    {
      Multiple_Read_HMC5883();//连续读出数据,存储在Rec_Data[]中
      X=Rec_Data<<8 | Rec_Data;//Combine MSB and LSB of X Data output register
      Z=Rec_Data<<8 | Rec_Data;//Combine MSB and LSB of Z Data output register
      Y=Rec_Data<<8 | Rec_Data;//Combine MSB and LSB of Y Data output register
      Angle= atan2((double)Y,(double)X)*(180/3.14159265)+180;//单位:角度 (0~360)
      Angle*=10;
      Acr=(uint)Angle;

      Send_DATA(0x92,0);
      Send_DATA(Acr%10000/1000+0x30,1);
      Send_DATA(Acr%1000/100+0x30,1);
      Send_DATA(Acr%100/10+0x30,1);
      Send_DATA('.',1);
      Send_DATA(Acr%10+0x30,1);

      Delay(50000);
    }
    while(1);
}

gdoujiajia 发表于 2012-12-26 12:51:10

想做个指南针,用这个正好!

brb2010 发表于 2012-12-26 17:26:23

这个程序很多网站上都有啊……

redwolf310 发表于 2012-12-27 10:48:35

mark         

princeward 发表于 2012-12-29 22:51:31

这个芯片真心不好焊。。。。

long578553882 发表于 2013-3-3 16:11:59

mark......

hnstray 发表于 2013-3-6 08:59:57

这个程序百度上满天飞

yun20 发表于 2013-3-27 16:51:41

满天飞就满天飞吧,学习了{:smile:}

woshisangao 发表于 2013-4-7 09:09:01

能贡献出来就是要鼓励下的

COMPASSNAVHK 发表于 2013-4-25 10:29:09

精度应该挺不错吧

jlian168 发表于 2013-4-25 11:41:10

mark,thanks.

落叶随风 发表于 2013-4-25 12:28:12

谢谢,顶一下!

guoyinwhu 发表于 2013-8-10 14:58:28

Angle= atan2((double)Y,(double)X)*(180/3.14159265)+180
+180是什么意思

yujunwei 发表于 2013-8-11 15:25:42

正好要用,mark

lijianchen2013 发表于 2013-9-9 21:45:21

guoyinwhu 发表于 2013-8-10 14:58 static/image/common/back.gif
Angle= atan2((double)Y,(double)X)*(180/3.14159265)+180
+180是什么意思

atan2获得的是-180到180而加上180 就转换成0 - 360°{:tongue:} 了

滨海田园 发表于 2013-9-24 17:47:36

lijianchen2013 发表于 2013-9-9 21:45 static/image/common/back.gif
atan2获得的是-180到180而加上180 就转换成0 - 360° 了

数字罗盘的y轴没有利用上,求利用y轴数据对横倾进行校正的方法{:smile:}

techh 发表于 2013-9-24 20:09:24

正准备学习

senkan2013 发表于 2013-11-25 14:44:18

HMC5883L初始化函数是不是有问题?手册上说CRA的最高位CR7必须清零以确保正确运行,这里初始化函数并没有操作CRA,而且CRA7的默认值是1

索达客 发表于 2014-2-4 12:44:17

先测试下再说,

茶亦爽 发表于 2014-2-8 14:05:21

多谢分享,好东西

yuyu7226974 发表于 2014-2-20 20:18:47

不知道有人有没有这个芯片和STM32 成功的程序啊。。。我搞了两天 一点进展都没有

ac0309 发表于 2014-2-21 09:52:49

东西很好,mark~~

hyf88 发表于 2014-4-16 09:08:50

楼主,请问一下,这个液晶是什么接口的?怎么才用到3个引脚?

hyf88 发表于 2014-4-16 09:10:11

不知道用stc15f104单片机来做这个行不行?

lujianfeng2001 发表于 2014-5-20 02:03:02

111111111111111

y1z2f4 发表于 2014-5-27 15:56:37

谢谢楼主分享,实际使用效果怎么样,分享一下吧。{:victory:}

zszc 发表于 2014-11-3 22:49:13

谢谢收藏了

bonito 发表于 2014-11-5 08:02:28

请问能接到6050上面的xda、xcl用i2c读取么

roc. 发表于 2014-11-5 08:45:09

多谢分享,好东西

mcufan5524 发表于 2015-1-9 00:18:24

我正需要这个资料呢,多谢分享

你贼漂亮 发表于 2015-1-11 21:39:35

能不能贴出代码的整个工程

空白L 发表于 2015-4-11 11:19:01

我得到结果不是0-360度,就在200-300度之间。知道这是怎么回事吗

woshiychvscyz 发表于 2015-4-20 20:35:59

有人知道怎么焊这个贴片吗??烙铁还是热风,多少度啊亲?

机械电子协会 发表于 2015-5-6 14:46:07

学习了                           

zhangxwnoah 发表于 2015-5-10 10:42:41

数字罗盘

videofun 发表于 2015-5-16 09:03:34


谢谢楼主分享,实际使用效果怎么样,谢谢分享。

陶新成 发表于 2015-12-17 11:57:33

请教楼主一个问题,在计算罗盘方位角的时候用俯仰和横滚角进行补偿但是补偿之后的数据乱飘,Xr=Xcosα+Ysinαsinβ+ Zcosβsin,Yr=Ycosβ- Zsin,就是当罗盘水平时即俯仰和横滚都为零时方位角才准确,不知道什么原因请您帮我看一下谢谢了!
http://www.amobbs.com/thread-5639795-1-1.html

陶新成 发表于 2015-12-24 14:56:23

程序时完整的吗,磁数据读出来不需要映射计算吗就是Heading = arctan(Yh / Xh ),Yh= X sinRollsinPitch +Y cosRoll+ Z sinRollcosPitch,Xh =X cosPitch+ Z sinPitch
页: [1]
查看完整版本: HMC5883L三轴数字罗盘————资料及例程