微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 有关HMC5883的问题请教

有关HMC5883的问题请教

时间:10-02 整理:3721RD 点击:
调试hmc5883时,旋转360度时读出的数据是正确的,但是如果旋转90或者180度时得到的数据就是错误的了。有大牛知道是什么原因吗?在线等解答!

/*********************hmc5883***************************/
#define        CONFIG_REG_A                0x00
#define        CONFIG_REG_B                0x01  
#define        MOD_REG              0x02                                 
#define        DATA_X_MSB                0x03                                                  
#define        DATA_X_LSB                0x04                                                  
#define        DATA_Z_MSB                0x05                                                  
#define        DATA_Z_LSB                0x06                                                  
#define        DATA_Y_MSB                0x07                                 
#define        DATA_Y_LSB                0x08                                                 
#define        STATE_REG                  0x09                                                  
#define        IDENTIFY_REG_A        0x0A                                                 
#define        IDENTIFY_REG_B        0x0B                                                  
#define        IDENTIFY_REG_C        0x0C                                          
void Mag_Init(void)          //hmc5883初始化
{
          delay_ms(100);
        WriteData(MagAddr,CONFIG_REG_A,0x70);
          WriteData(MagAddr,CONFIG_REG_B,0xA0 );
          WriteData(MagAddr,MOD_REG,0x00);
}
void MagDataPross(u8 *Pbuf,struct MagDatDef *MagDat)//将xyz轴数据存入结构体
{
        s16 sx,sy,sz;
        sx = (Pbuf[0] << 8) | Pbuf[1];        //x
        sy = (Pbuf[4] << 8) | Pbuf[5];        //y
        sz = (Pbuf[2] << 8) | Pbuf[3];        //z
        MagDat->x = (float)sx;
        MagDat->y = (float)sy;
        MagDat->z = (float)sz;
}
/*****************************************************************/

/*************************IIC时序**********************************/
void IIC_Init(void)
{                                             
        RCC->APB2ENR |= 1 << 3;//先使能外设IO PORTB时钟                                                          
        GPIOB->CRL &= 0X00FFFFFF;//PB6-SCL PB7-SDA 推挽输出
        GPIOB->CRL |= 0X33000000;          
        GPIOB->ODR |= 0X03 << 6;     // 拉高
}
//产生IIC起始信号
void IIC_Start(void)
{
        SDA_OUT();     //sda线输出
        IIC_SDA=1;                    
        IIC_SCL=1;
        delay_us(4);
        IIC_SDA=0;//START:when CLK is high,DATA change form high to low
        delay_us(4);
        IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}          
//产生IIC停止信号
void IIC_Stop(void)
{
        SDA_OUT();//sda线输出
        IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
        IIC_SCL=1;
        delay_us(4);
        IIC_SDA=1;//发送I2C总线结束信号
        delay_us(4);                                                                  
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)
{
        u8 ucErrTime=0;
        SDA_IN();      //SDA设置为输入  
        IIC_SDA=1;delay_us(10);          
        IIC_SCL=1;delay_us(10);         
        while(READ_SDA)
        {
                ucErrTime++;
                if(ucErrTime>250)
                {
                        IIC_Stop();
                        return 1;
                }
        }
        IIC_SCL=0;//时钟输出0           
        return 0;  
}
//产生ACK应答
void IIC_Ack(void)
{
        IIC_SCL=0;
        SDA_OUT();
        IIC_SDA=0;
        delay_us(2);
        IIC_SCL=1;
        delay_us(2);
        IIC_SCL=0;
}
//不产生ACK应答                    
void IIC_NAck(void)
{
        IIC_SCL=0;
        SDA_OUT();
        IIC_SDA=1;
        delay_us(2);
        IIC_SCL=1;
        delay_us(2);
        IIC_SCL=0;
}                                                                              
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答                          
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
        SDA_OUT();             
    IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1;           
                delay_us(2);   //对TEA5767这三个延时都是必须的
                IIC_SCL=1;
                delay_us(2);
                IIC_SCL=0;       
                delay_us(2);
    }         
}             
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
u8 IIC_Read_Byte(unsigned char ack)
{
        unsigned char i,receive=0;
        SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
        {
        IIC_SCL=0;
        delay_us(2);
                IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;   
                delay_us(1);
    }                                         
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}
void WriteData(u8 DevID,u8 Addr,u8 Dat)
{
        IIC_Start();
        IIC_Send_Byte(DevID << 1| 0);        //发送设备地址和写信号
        IIC_Wait_Ack();
        IIC_Send_Byte(Addr);
        IIC_Wait_Ack();
        IIC_Send_Byte(Dat);
        IIC_Wait_Ack();
        IIC_Stop();
        delay_ms(10);
}
void ReadData(u8 DevID,u8 Addr,u8 *Pbuf,u8 Num)
{
        u8 i;
        IIC_Start();
        IIC_Send_Byte(DevID << 1 | 0);        //发送设备地址和写信号
        IIC_Wait_Ack();
        IIC_Send_Byte(Addr);
        IIC_Wait_Ack();
        IIC_Start();
        IIC_Send_Byte(DevID << 1 | 1);        //发送设备地址和读信号
        IIC_Wait_Ack();
        for(i = 0;i < (Num - 1);i ++)
        {
                Pbuf = IIC_Read_Byte(1);
        }
        Pbuf = IIC_Read_Byte(0);
        IIC_Stop();
        delay_ms(5);
}
/**************************************************************/
/**********************主函数*********************************/
int angle;
int main(void)
{
        u8 Mag_Buf[6];
        struct MagDatDef MagDat;
         
        SystemInit();
        delay_init(72);             //延时初始化
        uart_init(9600);      //串口初始化
        IIC_Init();    //iic初始化
      Mag_Init();    //5883初始化
                 
        ReadData(MagAddr,IDENTIFY_REG_A,&temp,1);//读出3个识别寄存器
        printf("The MAG IDENTIFY_REG_A is 0x%02x\r\n",temp);
        ReadData(MagAddr,IDENTIFY_REG_B,&temp,1);
        printf("The MAG IDENTIFY_REG_B is 0x%02x\r\n",temp);
        ReadData(MagAddr,IDENTIFY_REG_C,&temp,1);
        printf("The MAG IDENTIFY_REG_C is 0x%02x\r\n",temp);
        ReadData(MagAddr,IDENTIFY_REG_A,&temp,1);
        while(1)
        {          
        ReadData(MagAddr,DATA_X_MSB,Mag_Buf,6);//把xyz轴数据存入mag_buf中
        MagDataPross(Mag_Buf,&MagDat);//
angle= atan2((double)MagDat.y,(double)MagDat.x) * (180 / 3.14159265)+180
         printf("angle  :%d\r\n",(int)angle);
                       
        }
}
帮忙看下有什么问题吧!

大牛都进来看下是什么问题吧!

通过测得的xyz的数据算航行角,难道不是这么算的?

我也有这种问题,转动一圈是360度,正确,但是转90度或是180读,读出的却不是相应的角度,测出的角度不准确。这是怎么回事?

请问知道问题在什么地方吗?

请问知道问题在什么地方吗?

没有人知道吗?

有没有校正?         

有校准,和楼上说的一样,实物转动90或者180但是输出的角度却与实际的转动角度有差别,有种跟不上的感觉,求解答,是不是的需要啥滤波程序

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top