[讨论] 关于hmc5883L的问题,数据读写一直有问题,请大家来看一下

aaronjedi   2014-4-2 14:48 楼主
关于 HMC5883L 我是用MSP 实现,但是数据是医一直错误 的 变化范围一直是 180~250左右。不知道问题是什么

回复评论 (16)

#include
#include "cry12864.h"
#include "cry12864.c"
#include
#include


#define HMC5883L_DIR   P1DIR
#define HMC5883L_IN    P1IN
#define HMC5883L_OUT   P1OUT
#define SCL  BIT2     //IIC时钟引脚定义
#define SDA  BIT3     //IIC数据引脚定义   
                      //DRDY 不接
#define SCL_H  (HMC5883L_DIR|=SCL,HMC5883L_OUT|=SCL)
#define SCL_L  (HMC5883L_DIR|=SCL,HMC5883L_OUT&=~SCL)
#define SDA_H  (HMC5883L_DIR|=SDA,HMC5883L_OUT|=SDA)
#define SDA_L  (HMC5883L_DIR|=SDA,HMC5883L_OUT&=~SDA)

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

//uchar ge,shi,bai,qian,wan;
unsigned char Rec_Data[6],b[5];
unsigned char  x,y,z;
double Angle;
uchar Acr;
   
/*延时函数*/
void Delay(uint t)
{
while(t--);
}

/*起始信号*/
void IIC_Start(void)
{
    SDA_H;
    SCL_H;
    Delay(50);
    SDA_L;
    Delay(50);
    SCL_L;
}

/*停止信号*/
void IIC_Stop(void)
{
    SDA_L;
    SCL_H;
    Delay(50);
    SDA_H;
    Delay(50);
}

/*发送应答信号*/
void IIC_SendAck(char Ack)
{   
    if(Ack)      //ack (0:ACK 1:NACK)
    SDA_H;
    else SDA_L;
    SCL_H;
    Delay(50);
    SCL_L;
    Delay(50);
}

/*接收应答信号*/
char IIC_RecAck(void)
{   
    char CY;
    HMC5883L_DIR&=~SDA;
    SCL_H;
    Delay(50);
    if(HMC5883L_DIR&SDA)
      CY=1;
    else CY=0;
    SCL_L;
    Delay(50);
    return CY;
}

/*向IIC总线发送一个字节数据*/
void HMC5883_Send_Byte(unsigned char Dat)
{
    unsigned char i;
    for(i=0;i<8;i++)
    {
        if(Dat&BIT7)
        SDA_H;
        else SDA_L;
        SCL_H;
        Delay(50);
        SCL_L;
        Delay(50);
        Dat<<=1;
    }
    IIC_RecAck();
}

/*从IIC总线接收一个字节数据*/
unsigned char HMC5883_Rec_Byte(void)
{
    unsigned char i,Dat=0;
    SDA_H;
    HMC5883L_DIR&=~SDA;
    for(i=0;i<8;i++)
    {
        Dat<<=1;
        SCL_H;
        Delay(50);
        
        if((HMC5883L_IN&SDA)==SDA)
        Dat|=BIT0;
        
        SCL_L;
        Delay(50);
    }
    return Dat;
}

/*单字节写HMC5883*/
void Single_Write_HMC5883(unsigned char Address,unsigned char Dat)
{
    IIC_Start();
    HMC5883_Send_Byte(SlaveAddress);
    HMC5883_Send_Byte(Address);
    HMC5883_Send_Byte(Dat);
    IIC_Stop();
}

/*单字节读HMC5883*/
unsigned char Single_Read_HMC5883(unsigned char Addr)
{
    unsigned char 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;
}

/*多字节读HMC5883*/
void Multiple_Read_HMC5883(void)
{
    unsigned char 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(0x00,0x60);
     Single_Write_HMC5883(0x02,0x00);
     //HMC5883_Send_Byte(0x00);
}




void conversion(uint temp_data)  
{  //uchar k;
    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;         
   

}

/*********************测试程序**********************/
unsigned char temp[16];

void main(void)
{
  //unsigned char m,n,p,q;
  char s[10];
  WDTCTL = WDTPW + WDTHOLD;             // Stop WDT
  P6DIR=0XFF;P6OUT=0XFF;
P3DIR=0XFF;P3OUT=0XFF;
P4DIR=0XFF;P4OUT=0XFF;
  Ini_Lcd();
   
  //display_word();
  HMC5883_Init();
  do
  {
   Multiple_Read_HMC5883();
   x=Rec_Data[0]<<8 | Rec_Data[1];//Combine MSB and LSB of X Data output register
   Draw_Line(0,0,"X轴:");
   sprintf(s,"%d",(int)x);
   Draw_Line(0,4,s);
   
   y=Rec_Data[4]<<8 | Rec_Data[5];//Combine MSB and LSB of Y Data output register
   Draw_Line(1,0,"Y轴:");
   sprintf(s,"%d",(int)y);
   Draw_Line(1,4,s);
   
   z=Rec_Data[2]<<8 | Rec_Data[3];//Combine MSB and LSB of Z Data output register
   Draw_Line(2,0,"Z轴:");
   sprintf(s,"%d",(int)z);
   Draw_Line(2,4,s);
   
   Angle= atan2((double)y,(double)x)*(180/3.14159265)+180;

   //conversion(Angle);
  
  
  
  
   Draw_Line(3,0,"角度:");
   sprintf(s,"%f",Angle);
   Draw_Line(3,4,s);
   
   
  Delay(50000);

   }
   while(1);

}
点赞  2014-4-2 14:49
问题已解决 是定义 接收XYZ 数据的数组定义问题,谢谢大家
点赞  2014-4-4 21:31
引用: aaronjedi 发表于 2014-4-4 21:31
问题已解决 是定义 接收XYZ 数据的数组定义问题,谢谢大家

你好。我也是一个电子爱好者。在 HMC5883L 的编程中和你遇见了相同的问题,就是只能变化范围一直是 180~250左右。
看到你说“问题已解决 是定义 接收XYZ 数据的数组定义问题”  可以更详细的告诉我问题的所在和解决方法吗??不胜感谢!!!  我的邮箱是:xm19771112@sina.com
点赞  2014-8-5 00:04
没什么比解决了纠结好久的问题让人更爽了,有需要芯片联系我哦QQ:453105832 本帖最后由 强哥精湛 于 2014-11-24 11:48 编辑
点赞  2014-11-24 11:15
引用: XM19771112 发表于 2014-8-5 00:04
你好。我也是一个电子爱好者。在 HMC5883L 的编程中和你遇见了相同的问题,就是只能变化范围一直是 180~2 ...
楼主 求教
点赞  2014-11-26 19:57
我读出的全是oxff,这是怎么回事?
点赞  2015-11-27 20:34
引用: dadangjia 发表于 2015-11-27 20:34
我读出的全是oxff,这是怎么回事?

我的读出来也是 0XFF  请问一下问题解决了吗
点赞  2015-11-29 12:52
还没有解决呀,不知道该怎么办?
点赞  2015-12-2 13:23
引用: dadangjia 发表于 2015-12-2 13:23
还没有解决呀,不知道该怎么办?

关于180-270的问题我今天刚解决,只要把x,y,z改为short类型的就可以了。我用的是stm32,32位单片机。
点赞  2015-12-16 14:21
引用: 秋水水天 发表于 2015-12-16 14:21
关于180-270的问题我今天刚解决,只要把x,y,z改为short类型的就可以了。我用的是stm32,32位单片机。

如果后面有同样问题的,确实将x,y,z改为short int 型即可, 我之前使用的类型是int,出现同样的问题。我使用的也是STM32.
点赞  2016-1-6 20:20
IIC通信地址问题也是值得注意的啊
点赞  2016-1-25 17:15
楼主这段程序是读角度还是读磁场
点赞  2016-3-27 16:24

这里有读HMC5883的代码,分享你们参照一下,其实同24C02有一点像

//***************************************************

void Single_Write_HMC5883(uchar REG_Address,uchar REG_data)
{
    HMC5883_Start();                  //起始信号
    HMC5883_SendByte(SlaveAddress);   //发送设备地址+写信号
    HMC5883_SendByte(REG_Address);    //内部寄存器地址,请参考中文pdf
    HMC5883_SendByte(REG_data);       //内部寄存器数据,请参考中文pdf
    HMC5883_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<6; i++)                      //连续读取6个地址数据,存储中BUF
    {
        BUF[i] = HMC5883_RecvByte();          //BUF[0]存储数据
        if (i == 5)
        {
           HMC5883_SendACK(1);                //最后一个数据需要回NOACK
        }
        else
        {
          HMC5883_SendACK(0);                //回应ACK
       }
   }
    HMC5883_Stop();                          //停止信号
    Delay5ms();
}
点赞  2018-12-3 15:53
数据类型是编程中一定要注意的,
点赞  2018-12-9 13:13
谢谢分享 赞一个
点赞  2018-12-9 18:27
引用: dadangjia 发表于 2015-11-27 20:34
我读出的全是oxff,这是怎么回事?

我的也是这个问题,请问怎么解决,还有HMC5883读取角度的程序吗?
点赞  2018-12-31 14:01
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复