6217|2

13

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

stm32 国产QMC5883L 进口HMC5883 三轴电子指南针加速度传感器 [复制链接]

 

QMC5883L源于Honeywell的HMC5883L,是一款表面贴装的集成了信号处理电路的三轴磁性传感器,应用场景主要包括罗盘、导航、无人机、机器人和手持设备等一些高精度的场合。

QMC5883L上电后默认为待命模式。此状态下,寄存器值将会通过一个超低功耗的LDO保持,对任意寄存器的读写操作都将会唤醒I2C总线接口。内部时钟被停止,同时也不会进行磁场测量。

以下是QMC5883L的寄存器列表:

00H~05H是数据寄存器,分别存放的是三轴传感器的X、Y和Z轴的值,每两个寄存器构成一个轴的高低字节,表示范围:-32768~32768。

06H是状态寄存器,当传感器数据已测量完毕并准备好DRDY位被置“1”,数据寄存器一旦被读取,DRDY位将被置“0”。OVL是溢出位,当有任意一个轴的测量值超过范围,OVL将被置“1”,当下一次测量不超测量范围时,OVL将会被置“0”。当处于连续模式下测量数据被跳过时DOR被置“1”,而当数据寄存器被读写后置“0”。

07H~08H存放的是QMC5883L内置的温度传感器的输出数据。这里需要注意的是温度传感器的增益出厂前校正过,但偏移没有得到补偿,所以,温度传感器测得的相对值是准确的。温度系数100 LSB/℃。

09H~0AH是QMC5883L的控制寄存器。09H设置工作模式(MODE)、数据输出更新频率(ODR)、传感器测量范围(RNG)以及过采样率(OSR)。0AH设置中断使能(INT_ENB)、点翻转使能(POL_PNT)以及软复位(SOFT_RST)。09H寄存器的设置如下图所示:

Figure 8 09H寄存器设置

INT_ENB被置“0”时,中断引脚(即DRDY)将被使能,置“1”时中断被禁止。

ROL_PNT被置“0”时,I2C总线接口将不会自动在00H~06H间翻转,置“1”时自动翻转。

SOFT_RST被置“1”时对QMC5883L进行软复位,软复位可以发生于任何模式下的任何时段,软复位发生后所有寄存器将会被置默认值。

0BH控制QMC5883L的设置/复位时间,推荐值是设定为0x01。

0DH是器件标识寄存器,其值为0xFF。
 

STM32程序如下,已调试通过

void IIC_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;	
	
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
 
	I2C_SCL_H;
	I2C_SDA_H;
}
 
void I2C_SDA_OUT(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;	
	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
}
 
void I2C_SDA_IN(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;	
	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
}
 
//产生起始信号
void I2C_Start(void)
{
	u16 i;
	I2C_SDA_OUT();
	
	I2C_SDA_H;
	I2C_SCL_H;
	for(i=0;i<5000;i++);
	I2C_SDA_L;
	for(i=0;i<6000;i++);
	I2C_SCL_L;
}
 
//产生停止信号
void I2C_Stop(void)
{
   u16 i;
   I2C_SDA_OUT();
 
//   I2C_SCL_L;
   I2C_SDA_L;
   I2C_SCL_H;
   for(i=0;i<6000;i++);
   I2C_SDA_H;
   for(i=0;i<6000;i++);
}
 
//主机产生应答信号ACK
void I2C_Ack(void)
{
   u16 i;
   I2C_SCL_L;
   I2C_SDA_OUT();
   I2C_SDA_L;
   for(i=0;i<2000;i++);
   I2C_SCL_H;
   for(i=0;i<5000;i++);
   I2C_SCL_L;
}
 
//主机不产生应答信号NACK
void I2C_NAck(void)
{
   u16 i;
   I2C_SCL_L;
   I2C_SDA_OUT();
   I2C_SDA_H;
   for(i=0;i<2000;i++);
   I2C_SCL_H;
   for(i=0;i<5000;i++);
   I2C_SCL_L;
}
//等待从机应答信号
//返回值:1 接收应答失败
//		  0 接收应答成功
u8 I2C_Wait_Ack(void)
{
	u8 tempTime=0;
	u16 i;
	I2C_SDA_H;
	for(i=0;i<1000;i++);
	I2C_SDA_IN();
 
	//I2C_SDA_H;
	//for(i=0;i<1000;i++);
	I2C_SCL_H;
	for(i=0;i<1000;i++);
 
	while(GPIO_ReadInputDataBit(GPIO_I2C,I2C_SDA))
	{
		tempTime++;
		if(tempTime>250)
		{
			//I2C_Stop();
			return 1;
		}	 
	}
 
	I2C_SCL_L;
	return 0;
}
 
//I2C 发送一个字节
void I2C_Send_Byte(u8 txd)
{
	u8 i=0;
	u16 j;
	I2C_SDA_OUT();
	I2C_SCL_L;//拉低时钟开始数据传输
 
	for(i=0;i<8;i++)
	{
		if((txd&0x80)>0) //0x80  1000 0000
			I2C_SDA_H;
		else
			I2C_SDA_L;
 
		txd<<=1;
		I2C_SCL_H;
		for(j=0;j<2000;j++);
		I2C_SCL_L;
		for(j=0;j<2000;j++);
	}
}
 
//I2C 读取一个字节
 
u8 IIC_Read_Byte(void )
{
	unsigned char i,receive=0;
	u16 j;
	I2C_SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
	{
        I2C_SCL_L; 
        for(j=0;j<5000;j++);
		I2C_SCL_H;
        receive<<=1;
        if(GPIO_ReadInputDataBit(GPIO_I2C,I2C_SDA))receive++;   
		for(j=0;j<5000;j++); 
    }
	return receive;
}
u8 I2C_Read_Byte(u8 ack)
{
   u8 i=0,receive=0;
   u16 j;
   I2C_SDA_IN();
   for(i=0;i<8;i++)
   {
   		I2C_SCL_L;
		for(j=0;j<2000;j++);
		I2C_SCL_H;
		receive<<=1;
		if(GPIO_ReadInputDataBit(GPIO_I2C,I2C_SDA))
		   receive++;
		for(j=0;j<1000;j++);
   }
 
   	if(ack==0)
	   	I2C_NAck();
	else
		I2C_Ack();
 
	 
	return receive;
}
//********??????????*************************
//unsigned char Single_Read_HMC5883(unsigned char REG_Address)
unsigned char Single_Read(unsigned char SlaveAddress,unsigned char REG_Address)
{  unsigned char REG_data;
    I2C_Start();                         //????
    I2C_Send_Byte(SlaveAddress);           //??????+???
    I2C_Send_Byte(REG_Address);                   //????????,?0??	
    I2C_Start();                          //????
    I2C_Send_Byte(SlaveAddress+1);         //??????+???
    REG_data=I2C_Read_Byte(1);              //???????
	I2C_Ack();	
	I2C_Stop();                          //????
    return REG_data; 
}
void IIC_Read(u8 IcAddr,u8 DtAddr,u8 len)
{
	u8 i=0;
 
	I2C_Start();
 
	I2C_Send_Byte(IcAddr);//器件地址+数据地址
	I2C_Wait_Ack();
	
	I2C_Send_Byte(DtAddr);//双字节是数据地址低位		
	I2C_Wait_Ack();
	I2C_Start();
	I2C_Send_Byte(IcAddr+0x01);
	I2C_Wait_Ack();
 
	for(i=0;i<len-1;i++)
	{
		IIC_buf[i]=I2C_Read_Byte(1); //  1   代表 ACK
	}
 
	IIC_buf[len-1]=I2C_Read_Byte(0); //  0  代表 NACK
	I2C_Stop();		
}
 
 
void IIC_Write(u8 IcAddr,u8 DtAddr,u8 dt)
{
	I2C_Start();
 
    I2C_Send_Byte(IcAddr);//器件地址+数据地址
	I2C_Wait_Ack();
 
	I2C_Send_Byte(DtAddr);//双字节是数据地址低位		
	I2C_Wait_Ack();
 
	I2C_Send_Byte(dt);
	I2C_Wait_Ack();
 
	I2C_Stop();
}
 
 
 void  Init_HMC5883L(void)
{
   IIC_Write(HMC5883L_Addr,0x09,0x1d);   //
   IIC_Write(HMC5883L_Addr,0x0A,0x41);
	IIC_Write(HMC5883L_Addr,0x0b,0x01);   //
}
 
//******************************************************
 
void hmc_write_reg(u8 reg,u8 data)
{
	I2C_Start();
	I2C_Send_Byte(WRITE_ADDRESS);
	I2C_Wait_Ack();
	I2C_Send_Byte(reg);
	I2C_Wait_Ack();
	I2C_Send_Byte(data);
	I2C_Wait_Ack();
	I2C_Stop();
	//delay_ms(5);
}
 
u8 hmc_read_reg(u8 reg)
{
	u8 data;
	I2C_Start();
	I2C_Send_Byte(WRITE_ADDRESS);
	I2C_Wait_Ack();
	I2C_Send_Byte(reg);
	I2C_Wait_Ack();
	I2C_Stop();
	I2C_Start();
	I2C_Send_Byte(READ_ADDRESS);
	I2C_Wait_Ack();
	data=IIC_Read_Byte();
	I2C_NAck();
	I2C_Stop();
	return data;
}
void hmc_read_XYZ(short int *data)
{
 
	
	x=((int16_t)hmc_read_reg(DATAX_M)<<8) | (hmc_read_reg(DATAX_L)); //Combine MSB and LSB of X Data output register
	y=((int16_t)hmc_read_reg(DATAY_M)<<8) | (hmc_read_reg(DATAY_L)); //Combine MSB and LSB of Y Data output register	
	z=((int16_t)hmc_read_reg(DATAZ_M)<<8) | (hmc_read_reg(DATAZ_L)); //Combine MSB and LSB of Z Data output register
	
	if(x>0x7fff) x=0x1ffff-x;		
	else x=0xffff+x;
	
	if(y>0x7fff) y=0x1ffff-y;		
	else y=0xffff+y;
	
	if(z>0x7fff) z=0x1ffff-z;		
	else z=0xffff+z;
	
	x_temp[xyz_count]=x;
	y_temp[xyz_count]=y;
	z_temp[xyz_count]=z;
	
	
	angledot[0]= atan2((double)y,(double)x) * (180 / 3.14159265) + 180; // angle in degrees
	angledot[1]= atan2((double)z,(double)x) * (180 / 3.14159265) + 180; // angle in degrees
	angledot[2]= atan2((double)y,(double)z) * (180 / 3.14159265) + 180; // angle in degrees
	chip_ID=hmc_read_reg(0x0d);
}

芯片比较难手焊,我把PCB焊盘和芯片底部焊盘都镀锡,然后用风枪吹,一次焊接成功。

最新回复

很好的知识,有种豁然开朗的感觉,感谢楼主分享。   详情 回复 发表于 2021-12-22 09:50
点赞 关注
 
 

回复
举报

661

帖子

0

TA的资源

纯净的硅(初级)

沙发
 

谢谢分享

 
 
 

回复

51

帖子

0

TA的资源

一粒金砂(中级)

板凳
 

很好的知识,有种豁然开朗的感觉,感谢楼主分享。

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表