QMC5883L磁力计介绍(硬件+软件)(附STM32程序~~~)

QMC5883L磁力计介绍

话不多说,先上代码链接
GitHub - Tuya-Community/tuya-iotos-embeded-mcu-demo-wifi-ble-electronic-compass: electronic compass of mcu sdk
QMC5883L是一款国产磁力计,与HMC5993 pin to pin 兼容,软件上只要少许改动,便可达到相同效果。鉴于网络上qmc5883l资料较少,今天小编就教大家如何使用这款传感器。


硬件介绍

首先是硬件,qmc5883硬件引脚如下

1 SCL :Serial Clock – I2C Master/Slave Clock
2 VDD :Power Supply (2.16V to 3.6V)
3 NC: Not to be Connected
4 S1 :Tie to VDDIO
5 NC: Not to be Connected
6 NC: Not to be Connected
7 NC :Not to be Connected
8 SETP: Set/Reset Strap Positive – S/R Capacitor (C2) Connection
9 GND :Supply Ground
10 C1: Reservoir Capacitor (C1) Connection
11 GND: Supply Ground
12 SETC :S/R Capacitor (C2) Connection – Driver Side
13 VDDIO: IO Power Supply (1.71V to VDD)
14 NC: Not to be Connected
15 DRDY :Data Ready, Interrupt Pin. Default low. Data ready high until data
register is read.
16 SDA: Serial Data – I2C Master/Slave Data

根据手册说明,电路可以如下设计:

这边要提以下几点:
首先是供电电压,qmc5883l的供电范围是2.16~3.6V,大家千万不要超出这个范围,否则会影响正常工作,甚至永久损坏。
还有一个是设备地址,qmc5883默认的7-bit IIC地址为0X0D:0001101
qmc5883l有一个S1引脚,
如果我们将S1接VDD,那么写地址为0X1A,读地址为0X1B(通常接VDD);
如果我们将S1接GND,那么写地址为0X18,读地址为0X19;

初始化


驱动程序方面,初始化函数可以如下
IIC_Write_Byte(QMC5883L_ADDRESS,0x0B, 0x01);
//IIC_Write_Byte(QMC5883L_ADDRESS,0x20, 0x40);
//IIC_Write_Byte(QMC5883L_ADDRESS,0x21, 0x01);

Config = OVER_SAMPLE_RATIO_512
|FULL_SCALE_2G
|OUTPUT_DATA_RATE_10HZ
|MODE_CONTROL_CONTINUOUS;
/OSR=512,RNG=+/-2G,ODR=200Hz,MODE= continuous***/
IIC_Write_Byte(QMC5883L_ADDRESS,0x09, Config);

接下来给大家讲解每个寄存器的意思

其中0x0B寄存器写01,这个设置周期,01是手册建议的写入值;


后面0x20和0x21这两个寄存器参数的写入,基本来自于网络上别的文档,但是正式的数据手册上面,并没有这两个寄存器的信息,小编试了一下,没有这两句,传感器也可以正常工作,所以大家还是以正式数据手册为主吧。

0x09寄存器,这个是重点。

主要用于设置工作模式,输出频率,量程范围和采样速率,大家可以根据自己的需求,看表格设置。
小编是设置成512采样速率,2G范围,10HZ输出,连续采样模式。其中低输出速率,可以提高一些精度。

数据读取

接下来是数据读取,数据寄存器有6个

程序如下,注意第一个数据是低八位,后面的是高八位。
IIC_ReadMulByte(QMC5883L_ADDRESS,0x00,Mag,6);
Mag_data.x= (int16_t)(Mag[1] <<8 | Mag[0]);// First byte is LSB, second byte is MSB
Mag_data.y= (int16_t)(Mag[3] << 8 | Mag[2]);
Mag_data.z= (int16_t)(Mag[5] << 8 | Mag[4]);

当然,如果出于产品化考虑,可以在获取数据前,先判断一下传感器状态。
IIC_ReadMulByte(QMC5883L_ADDRESS,0x06,&temp,1);

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

角度计算

获取地磁原始数据后,就可以通过三角函数,计算出方位角度。
data->x=atan2((double)Mag_data.y,(double)Mag_data.x)*57.3+180;

完成例程,可以通过下面链接查看

本文例程

  • 19
    点赞
  • 130
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
//*************************************************** 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(); } //初始化HMC5883,根据需要请参考pdf进行修改**** void Init_HMC5883() { Single_Write_HMC5883(0x02,0x00); // }
抱歉,我是一名AI语言模型,无法编写程序。但是,我可以提供一个简单的STM32检测QMC5883L的示例程序,供您参考: ``` #include "stm32f4xx.h" #include "stdio.h" #define QMC5883L_ADDRESS 0x0D #define QMC5883L_REG_X_LSB 0x00 #define QMC5883L_REG_STATUS 0x06 I2C_HandleTypeDef hi2c1; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_I2C1_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_I2C1_Init(); uint8_t data[1]; uint8_t status; while (1) { HAL_I2C_Mem_Read(&hi2c1, QMC5883L_ADDRESS, QMC5883L_REG_STATUS, 1, data, 1, 1000); status = data[0]; if ((status & 0x01) == 0x01) { printf("Magnetic field data is ready!\r\n"); } else { printf("Magnetic field data is not ready yet.\r\n"); } HAL_Delay(1000); } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = 16; RCC_OscInitStruct.PLL.PLLN = 336; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4; RCC_OscInitStruct.PLL.PLLQ = 7; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } } static void MX_I2C1_Init(void) { hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } void Error_Handler(void) { __disable_irq(); while (1) { } } ``` 这个程序使用了HAL库来初始化STM32的I2C1接口,并通过I2C接口读取QMC5883L的状态寄存器来检测磁场数据是否准备就绪。如果准备就绪,程序将会输出"Magnetic field data is ready!",否则输出"Magnetic field data is not ready yet."。程序中使用了延时函数HAL_Delay(1000),每隔1秒钟检测一次磁场数据是否准备就绪。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值