综合技术
直播中

张璨

7年用户 204经验值
私信 关注
[问答]

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%02xrn",temp);
        ReadData(MagAddr,IDENTIFY_REG_B,&temp,1);
        printf("The MAG IDENTIFY_REG_B is 0x%02xrn",temp);
        ReadData(MagAddr,IDENTIFY_REG_C,&temp,1);
        printf("The MAG IDENTIFY_REG_C is 0x%02xrn",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:%drn",(int)angle);
                        
        }
}
帮忙看下有什么问题吧!

回帖(3)

任娇

2019-5-5 10:26:17
帮顶....
举报

李铃华

2019-5-5 10:43:31
遇到相同的问题。。。同求!
举报

农一航

2022-6-30 17:19:02
同样的问题,有解决方法吗
举报

更多回帖

发帖
×
20
完善资料,
赚取积分