stm32读取数据hmc58663l问题

用stm32读取hmc58663l获取的3轴都是“-1”,不知道怎么回事

main.c


#include "stm32f10x.h"
#include "delay.h"
#include "Lcd_Driver.h"
#include "hmc5883l.h"
#include "usart.h"
#include "sys.h"
#include "stdlib.h"
#include "math.h"

int x, y, z, X, Y, Z;


float Get_Current_Angle() {
  u8 i;
  u8 a[6];
  float Curent_Angle;
  i2c_Start(); //iic开始
  i2c_SendByte(HMC5883L_Write_Address); //发送写地址 0x3c
  i2c_WaitAck(); //等待应答
  i2c_SendByte(0x03);//发送写的那个寄存器
  i2c_WaitAck(); //等待应答

  i2c_Start(); //iic第二次开始
  i2c_SendByte(HMC5883L_Read_Address); //发送读地址 0x3d
  i2c_WaitAck(); //等待应答
  for (i = 0;i < 6;i++) //都6个字节
  {
    a[i] = i2c_ReadByte();
    if (i == 5)
    {
      i2c_NAck(); //最后一字节应答
    }
    else
    {
      i2c_Ack();
    }
  }
  i2c_Stop(); //停止iic
  x = a[0];
  x = x << 8;
  x = x | a[1];
  y = a[2];
  y = y << 8;
  y = y | a[3];
  z = a[4];
  z = z << 8;
  z = z | a[5];
  if (x > 32768)
  {
    x = -(0xFFFF - x + 1);
  }

  if (y > 32768)
  {
    y = -(0xFFFF - y + 1);
  }
  if (z > 32768)
  {
    z = -(0xFFFF - z + 1);
  }
  X = (s16)x;    //x分量  
  Y = (s16)y;    //y分量  
  Z = (s16)z;    //z分量  

  printf("X:%d Y:%d Z:%d\r\n", X, Y, Z);
  Curent_Angle = (atan2(Y, X) * (180 / 3.14159265) + 180);  //实际水平角度  
  return Curent_Angle;
}


int main(void)
{
  float ang;

  SystemInit();    //System init.
  delay_init(72);//Delay init.
  Lcd_Init();
  uart_init(115200);
  HMC5883L_Init();


  GPIO_ResetBits(GPIOA, GPIO_Pin_8);
  GPIO_ResetBits(GPIOD, GPIO_Pin_2);

  while (1)
  {
    delay_ms(4000);
    ang = Get_Current_Angle();
    printf("%f\r\n", ang);
  }
}


hmc58663l.h头文件

#include "stm32f10x_i2c.h"
#include "misc.h"
#include "sys.h"
#include "stm32f10x_gpio.h"
#include "delay.h"



/**
 * i2c
*/

#define HMC5883L_Write_Address  0x3C
#define HMC5883L_Read_Address   0x3D

#define SDA_IN()  {GPIOB->CRH&=0XFFFFFF0F;GPIOB->CRH|=(u32)8<<4;}
#define SDA_OUT() {GPIOB->CRH&=0XFFFFFF0F;GPIOB->CRH|=(u32)3<<4;}
#define IIC_SCL    PBout(8) //SCL
#define IIC_SDA    PBout(9) //SDA     
#define GPIO_SCL    GPIO_Pin_8
#define GPIO_SDA    GPIO_Pin_9
#define IIC_PERIPH  GPIOB
#define READ_SDA    PBin(9) 

void i2c_Start(void);
void i2c_Stop(void);
void i2c_SendByte(u8 _ucByte);
u8 i2c_ReadByte(void);
u8 i2c_WaitAck(void);
void i2c_Ack(void);
void i2c_NAck(void);
void HMC5883L_Init(void);


hmc58663l.c

#include "hmc5883l.h"

void IIC_IO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);    //ê1?üGPIOBê±?ó

  GPIO_InitStructure.GPIO_Pin = GPIO_SCL | GPIO_SDA;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //í?íìê?3?
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(IIC_PERIPH, &GPIO_InitStructure);
  GPIO_SetBits(IIC_PERIPH, GPIO_Pin_8 | GPIO_Pin_9);     //PB6,PB7 ê?3???
}

void i2c_Start(void)
{
  /*SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */
  SDA_OUT();
  IIC_SDA = 1;
  delay_us(10);
  IIC_SCL = 1;
  delay_us(10);
  IIC_SDA = 0;
  delay_us(10);
  IIC_SCL = 0;
  delay_us(10);
}
void i2c_Stop(void)
{
  /*SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */
  SDA_OUT();
  IIC_SDA = 0;
  delay_us(10);
  IIC_SCL = 1;
  delay_us(10);
  IIC_SDA = 1;
}
void i2c_SendByte(u8 _ucByte)
{
  u8 i;
  SDA_OUT();
  /* 先发送字节的高位bit7 */
  for (i = 0; i < 8; i++)
  {
    if (_ucByte & 0x80)
    {
      IIC_SDA = 1;
    }
    else
    {
      IIC_SDA = 0;
    }
    delay_us(10);
    IIC_SCL = 1;
    delay_us(10);
    IIC_SCL = 0;
    if (i == 7)
    {
      IIC_SDA = 1; // 释放总线  
    }
    _ucByte <<= 1;    /* 左移一个bit */
    delay_us(10);
  }
}
u8 i2c_ReadByte(void)
{
  u8 i;
  u8 value;
  IIC_SDA = 1;
  SDA_IN();
  /* 读到第1个bit为数据的bit7 */
  value = 0;
  for (i = 0; i < 8; i++)
  {
    value <<= 1;
    IIC_SCL = 1;
    delay_us(10);
    if (READ_SDA)
    {
      value++;
    }
    IIC_SCL = 0;
    delay_us(10);
  }
  return value;
}
u8 i2c_WaitAck(void)
{
  u8 re;
  SDA_IN();
  IIC_SDA = 1;  /* CPU释放SDA总线 */
  delay_us(10);
  IIC_SCL = 1;  /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */
  delay_us(10);
  if (READ_SDA)   /* CPU读取SDA口线状态 */
  {
    re = 1;
  }
  else
  {
    re = 0;
  }
  IIC_SCL = 0;
  delay_us(10);
  return re;
}
void i2c_Ack(void)
{
  SDA_OUT();
  IIC_SDA = 0;  /* CPU驱动SDA = 0 */
  delay_us(10);
  IIC_SCL = 1;  /* CPU产生1个时钟 */
  delay_us(10);
  IIC_SCL = 0;
  delay_us(10);
  IIC_SDA = 1;  /* CPU释放SDA总线 */
}
void i2c_NAck(void)
{
  SDA_OUT();
  IIC_SDA = 1;  /* CPU驱动SDA = 1 */
  delay_us(10);
  IIC_SCL = 1;  /* CPU产生1个时钟 */
  delay_us(10);
  IIC_SCL = 0;
  delay_us(10);
}
void HMC5883L_Init(void)
{
  IIC_IO_Init();
  //i2c_CheckDevice(HMC5883L_Write_Address);  
  i2c_Start();
  i2c_SendByte(HMC5883L_Write_Address);
  i2c_WaitAck();
  i2c_SendByte(0x00);
  i2c_WaitAck();
  i2c_SendByte(0x70);
  i2c_WaitAck();
  i2c_SendByte(0x01);
  i2c_WaitAck();
  i2c_SendByte(0xe0);
  i2c_WaitAck();
  i2c_SendByte(0x02);
  i2c_WaitAck();
  i2c_SendByte(0x01);
  i2c_Stop();
}




这个最好先使用读取下传感器的ID值是否正确,以此判断I2C通讯是否正常,再查看手册看下传感器寄存器功能配置是否配置到位。 一步步解决问题,应该很快就可以迎刃而解了