QMC5883L磁场传感器驱动

本文介绍Honeywell的HMC5883L三轴磁性传感器的驱动程序实现,包括初始化过程、寄存器配置及数据读取等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Honeywell的HMC5883L三轴磁性传感器驱动,操作比较简单,就是要注意设置好模式寄存器后,还要将0x0B设置为1,否则测量的值不对,并且温度一直是0

//QMC5883L.c

/*************************************************************************************************************
 * 文件名:		QMC5883L.c
 * 功能:		QMC5883L驱动
 * 作者:		cp1300@139.com
 * 邮箱:		cp1300@139.com
 * 创建时间:	2020-11-03
 * 最后修改时间:2020-11-03
 * 详细:		Honeywell的HMC5883L三轴磁性传感器
*************************************************************************************************************/
#include "SYSTEM.h"
#include "QMC5883L.h"


//QMC5883L寄存器列表
#define QMC5883L_DATA_X_LSB			0x00		//X LSB			只读
#define QMC5883L_DATA_X_MSB			0x01		//X MSB			只读
#define QMC5883L_DATA_Y_LSB			0x02		//Y LSB			只读
#define QMC5883L_DATA_Y_MSB			0x03		//Y MSB			只读
#define QMC5883L_DATA_Z_LSB			0x04		//Z LSB			只读
#define QMC5883L_DATA_Z_MSB			0x05		//Z MSB			只读
#define QMC5883L_STATUS_REG			0x06		//状态寄存器	只读
#define QMC5883L_TEMP_LSB			0x07		//温度 LSB		只读-温度只是相对值,没有实际用途
#define QMC5883L_TEMP_MSB			0x08		//温度 MSB		只读-温度只是相对值,没有实际用途
#define QMC5883L_CONTROL1_REG		0x09		//控制寄存器1	读写
#define QMC5883L_CONTROL2_REG		0x0A		//控制寄存器2	读写-BIT7为复位
#define QMC5883L_SET_RESET_PERIOD	0x0B		//时间寄存器,设置为0x01
#define QMC5883L_ID_REG				0x0D		//芯片ID		只读


bool QMC5883L_ReadOneReg(QMC5883L_HANDLE *pHandle,u8 RegAddr, u8 *pData);						//QMC5883L读取一个寄存器
bool QMC5883L_ReadMultReg(QMC5883L_HANDLE *pHandle,u8 RegAddr, u8 RegNum, u8 DataBuff[]);		//QMC5883L读取多个寄存器
bool QMC5883L_WriteOneReg(QMC5883L_HANDLE *pHandle,u8 RegAddr,u8 data);							//QMC5883L写一个寄存器

#define QMC5883L_ID			0xFF				//QMC5883L 芯片ID

/*************************************************************************************************************************
*函数        	:	bool QMC5883L_Init(QMC5883L_HANDLE *pHandle, u8 SlaveAddr, 
						bool (*IIC_ReadReg)(u8 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum), 
						bool (*IIC_WriteReg)(u16 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum))
*功能        	:	QMC5883L初始化
*参数        	:	pHandle:句柄;SlaveAddr:芯片IIC读地址;IIC_ReadReg:IIC读取接口;IIC_WriteReg:IIC写入接口;
*返回        	:	TRUE:初始化成功;FALSE:初始化失败
*依赖			: 	底层宏定义
*作者       	:	cp1300@139.com
*时间     		:	2020-11-03
*最后修改时间	:	2020-11-03
*说明        	:	
*************************************************************************************************************************/
bool QMC5883L_Init(QMC5883L_HANDLE *pHandle, u8 SlaveAddr, 
	bool (*IIC_ReadReg)(u8 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum), 
	bool (*IIC_WriteReg)(u16 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum))
{
	u8 tempreg;
	
	if(pHandle == NULL) 
	{
		DEBUG("无效的句柄\r\n");
		SYS_DelayMS(5000);
		return FALSE;
	}
	pHandle->SlaveAddr = SlaveAddr;										//记录地址
	pHandle->IIC_ReadReg = IIC_ReadReg;									//IIC接口
	pHandle->IIC_WriteReg = IIC_WriteReg;								//IIC接口
	
	QMC5883L_WriteOneReg(pHandle, QMC5883L_CONTROL2_REG, 0X80);			//复位,要延时一定时间
    SYS_DelayMS(100);
	QMC5883L_WriteOneReg(pHandle, QMC5883L_SET_RESET_PERIOD, 0X01);		//复位后必须写入0x01,否则温度为0,磁场数据也不对
	QMC5883L_SetMode(pHandle, QMC5883L_MODE_CONTINUOUS, QMC5883L_ODR_50HZ, QMC5883L_RNG_2G, QMC5883L_OSR_64);//设置工作模式
	
	if(QMC5883L_ReadOneReg(pHandle, QMC5883L_ID_REG, &tempreg) == FALSE)
	{
		DEBUG("QMC5883L初始化失败,读取芯片ID失败\r\n");
		return FALSE;
	}
	if(tempreg == QMC5883L_ID)//器件ID正确
	{
		uart_printf("QMC5883L初始化成功,ID:0x%X\r\n", tempreg);
		return TRUE;
 	}
	else 
	{
		DEBUG("QMC5883L初始化失败,无效的ID:0x%X\r\n", tempreg);
		return FALSE;
	}
	
	//读取配置,看看是否与写入的一致,由于芯片id是0xFF,并不能用于判断芯片是否初始化正常
	if(QMC5883L_ReadOneReg(pHandle, QMC5883L_CONTROL1_REG, &tempreg) == FALSE)
	{
		DEBUG("QMC5883L初始化失败,读取配置失败\r\n");
		return FALSE;
	}
	if(tempreg == pHandle->ModeConfigData)//器件配置正确
	{
		uart_printf("QMC5883L初始化成功,配置:0x%X\r\n", tempreg);
		return TRUE;
 	}
	else 
	{
		DEBUG("QMC5883L初始化失败,无效的配置:0x%X!=0x%02X\r\n", tempreg, pHandle->ModeConfigData);
		return FALSE;
	}
}


/*************************************************************************************************************************
*函数        	:	bool QMC5883L_SetMode(QMC5883L_HANDLE *pHandle, QMC5883L_MODE mode, QMC5883L_ODR odr, QMC5883L_RNG rng, QMC5883L_OSR osr)
*功能        	:	设置工作模式
*参数        	:	pHandle:句柄;mode:工作模式,见QMC5883L_MODE;odr:输出速率,见QMC5883L_ODR;rng:测量范围,
						见QMC5883L_RNG;osr:过采样率,见QMC5883L_OSR
*返回        	:	TRUE:成功;FALSE:失败
*依赖			: 	底层宏定义
*作者       	:	cp1300@139.com
*时间     		:	2020-10-19
*最后修改时间	:	2020-10-19
*说明        	:	
*************************************************************************************************************************/
bool QMC5883L_SetMode(QMC5883L_HANDLE *pHandle, QMC5883L_MODE mode, QMC5883L_ODR odr, QMC5883L_RNG rng, QMC5883L_OSR osr)
{
	u8 tempreg = 0;
	
	tempreg = ((mode&0x03)<<0) | ((odr&0x03)<<2) | ((rng&0x03)<<4) | ((osr&0x03)<<6);
	pHandle->ModeConfigData = tempreg;
	
	return QMC5883L_WriteOneReg(pHandle, QMC5883L_CONTROL1_REG, tempreg);
}

/*************************************************************************************************************************
*函数        	:	bool QMC5883L_ReadOneReg(QMC5883L_HANDLE *pHandle,u8 RegAddr, u8 *pData)
*功能        	:	QMC5883L读取一个寄存器
*参数        	:	pHandle:句柄;RegAddr:寄存器地址;pData:寄存器值
*返回        	:	TRUE:读取成功;FALSE:读取失败
*依赖			: 	底层宏定义
*作者       	:	cp1300@139.com
*时间     		:	2020-10-19
*最后修改时间	:	2020-10-19
*说明        	:	
*************************************************************************************************************************/
bool QMC5883L_ReadOneReg(QMC5883L_HANDLE *pHandle,u8 RegAddr, u8 *pData)
{
	return pHandle->IIC_ReadReg(pHandle->SlaveAddr, RegAddr, pData, 1);
}


/*************************************************************************************************************************
*函数        	:	bool QMC5883L_ReadMultReg(QMC5883L_HANDLE *pHandle,u8 RegAddr, u8 RegNum, u8 DataBuff[])
*功能        	:	QMC5883L读取多个寄存器
*参数        	:	pHandle:句柄;RegAddr:寄存器地址;RegNum:寄存器数量;DataBuff:返回结果缓冲区
*返回        	:	TRUE:读取成功;FALSE:读取失败
*依赖			: 	底层宏定义
*作者       	:	cp1300@139.com
*时间     		:	2020-10-19
*最后修改时间	:	2020-10-19
*说明        	:	
*************************************************************************************************************************/
bool QMC5883L_ReadMultReg(QMC5883L_HANDLE *pHandle,u8 RegAddr, u8 RegNum, u8 DataBuff[])
{
	return pHandle->IIC_ReadReg(pHandle->SlaveAddr, RegAddr, DataBuff, RegNum);
}


/*************************************************************************************************************************
*函数        	:	void QMC5883L_WriteOneReg(QMC5883L_HANDLE *pHandle,u8 RegAddr,u8 data)
*功能        	:	QMC5883L写一个寄存器
*参数        	:	pHandle:句柄;RegAddr:寄存器地址;data:要写入的值
*返回        	:	TRUE:成功;FALSE:失败
*依赖			: 	底层宏定义
*作者       	:	cp1300@139.com
*时间     		:	2020-10-19
*最后修改时间	:	2020-10-19
*说明        	:	
*************************************************************************************************************************/
bool QMC5883L_WriteOneReg(QMC5883L_HANDLE *pHandle,u8 RegAddr,u8 data)
{
	return pHandle->IIC_WriteReg(pHandle->SlaveAddr, RegAddr, &data, 1);
}



/*************************************************************************************************************************
*函数        	:	bool QMC5883L_GetTemper(QMC5883L_HANDLE *pHandle, s16 *pTemp)
*功能        	:	QMC5883L读取温度(相对温度)
*参数        	:	pHandle:句柄;pTemp:读取的温度值,扩大100倍
*返回        	:	TRUE:成功;FALSE:失败
*依赖			: 	底层宏定义
*作者       	:	cp1300@139.com
*时间     		:	2020-11-03
*最后修改时间	:	2020-11-03
*说明        	:	注意:读取的温度是相对温度,只能用于测量温度变化量,初值没有进行校准
*************************************************************************************************************************/
bool QMC5883L_GetTemper(QMC5883L_HANDLE *pHandle, s16 *pTemp)
{
	u8 buff[2];
	s16 temp;
	
	if(QMC5883L_ReadMultReg(pHandle, QMC5883L_TEMP_LSB, 2, buff) == FALSE) return FALSE;
	temp = ((u16)buff[1]<<8)|buff[0];
	*pTemp = temp;
	
	return TRUE;
}


/*************************************************************************************************************************
*函数        	:	bool QMC5883L_GetMagneticData(QMC5883L_HANDLE *pHandle, s16 *mx, s16 *my ,s16 *mz)
*功能        	:	QMC5883L读取磁力计原始数据
*参数        	:	pHandle:句柄;mx,my,mz:三个轴原始数据
*返回        	:	TRUE:成功;FALSE:失败
*依赖			: 	底层宏定义
*作者       	:	cp1300@139.com
*时间     		:	2020-11-03
*最后修改时间	:	2020-11-03
*说明        	:	
*************************************************************************************************************************/
bool QMC5883L_GetMagneticData(QMC5883L_HANDLE *pHandle, s16 *mx, s16 *my ,s16 *mz)
{
	u8 buff[6];

	if(QMC5883L_ReadMultReg(pHandle, QMC5883L_DATA_X_LSB, 6, buff) == FALSE) return FALSE;
	*mx=((u16)buff[1]<<8)|buff[0];  
	*my=((u16)buff[3]<<8)|buff[2];  
	*mz=((u16)buff[5]<<8)|buff[4];
	
	return TRUE;	
}

//QMC5883L.h

/*************************************************************************************************************
 * 文件名:		QMC5883L.h
 * 功能:		QMC5883L驱动
 * 作者:		cp1300@139.com
 * 邮箱:		cp1300@139.com
 * 创建时间:	2020-11-03
 * 最后修改时间:2020-11-03
 * 详细:		Honeywell的HMC5883L三轴磁性传感器
*************************************************************************************************************/
#ifndef __QMC5883L_H_
#define __QMC5883L_H_
#include "system.h"

//QMC5883L 句柄
typedef struct
{
	bool (*IIC_ReadReg)(u8 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum);		//IIC读取寄存器接口
	bool (*IIC_WriteReg)(u16 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum);	//IIC写入寄存器接口
	u8 SlaveAddr;
	u8 ModeConfigData;						//记录模式配置值
}QMC5883L_HANDLE;

//QMC5883L工作模式
typedef enum
{
	QMC5883L_MODE_STANDBY		=	0x00,	//待机模式
	QMC5883L_MODE_CONTINUOUS	=	0x01,	//连续工作模式
}QMC5883L_MODE;


//QMC5883L更新速率
typedef enum
{
	QMC5883L_ODR_10HZ			=	0x00,	//10Hz
	QMC5883L_ODR_50HZ			=	0x01,	//50Hz
	QMC5883L_ODR_100HZ			=	0x02,	//100Hz	
	QMC5883L_ODR_200HZ			=	0x03,	//200Hz	
}QMC5883L_ODR;

//QMC5883L测量范围
typedef enum
{
	QMC5883L_RNG_2G				=	0x00,	//2G
	QMC5883L_RNG_8G				=	0x01,	//8G
}QMC5883L_RNG;

//QMC5883L过采样
typedef enum
{
	QMC5883L_OSR_512			=	0x00,	//512
	QMC5883L_OSR_256			=	0x01,	//256
	QMC5883L_OSR_128			=	0x02,	//128
	QMC5883L_OSR_64				=	0x03,	//64
}QMC5883L_OSR;

bool QMC5883L_Init(QMC5883L_HANDLE *pHandle, u8 SlaveAddr, 
	bool (*IIC_ReadReg)(u8 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum), 
	bool (*IIC_WriteReg)(u16 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum));											//QMC5883L初始化
bool QMC5883L_SetMode(QMC5883L_HANDLE *pHandle, QMC5883L_MODE mode, QMC5883L_ODR odr, QMC5883L_RNG rng, QMC5883L_OSR osr);	//设置工作模式
bool QMC5883L_GetTemper(QMC5883L_HANDLE *pHandle, s16 *pTemp);																//QMC5883L读取温度(相对温度)
bool QMC5883L_GetMagneticData(QMC5883L_HANDLE *pHandle, s16 *mx, s16 *my ,s16 *mz);											//QMC5883L读取磁力计原始数据

#endif //__QMC5883L_H_

//测试

#include "typedef.h"
#include "nuc970_system.h"
#include "stdlib.h"
#include "main.h"
#include "test.h"
#include "QMC5883L.h"
#include "SoftwareIIC.h"



SIIC_HANDLE g_IIC_Handle;
QMC5883L_HANDLE g_QMC5883L_Handle;

//IIC读取寄存器接口
bool QMC5883L_IIC_ReadReg(u8 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum)		
{
	return SIIC_ReadReg(&g_IIC_Handle, SlaveAddr, RegAddr, TRUE, pDataBuff, ByteNum);	//软件IIC读取寄存器(可以读取1个或者多个寄存器)
}

//IIC写入寄存器接口
bool QMC5883L_IIC_WriteReg(u16 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum)
{
	return SIIC_WriteReg(&g_IIC_Handle, SlaveAddr, RegAddr, TRUE, pDataBuff, ByteNum);	//软件IIC写寄存器(可以写1个或者多个寄存器)
}


//QMC5883L0测试
void qmc5883l_test(void)
{
	s16 Temp;
	s16 MagneticData[3];
	
	
	SIIC_Init(&g_IIC_Handle, GPIOG, GPIOG, 0, 1, 10);														//软件IIC初始化
	while(QMC5883L_Init(&g_QMC5883L_Handle, 0x1A, QMC5883L_IIC_ReadReg, QMC5883L_IIC_WriteReg) == FALSE)	//QMC5883L初始化
	{
		Sleep(1000);
	}

	while(1)
	{
		if(QMC5883L_GetTemper(&g_QMC5883L_Handle, &Temp) == TRUE)			//MPU6050读取温度
		{
			uart_printf("[QMC5883L]温度:%s%d.%02d℃\r\n",(Temp<0)?"-":"", abs(Temp)/100, abs(Temp)%100);
		}
		else
		{
			uart_printf("[QMC5883L]温度:ERROR\r\n");
		}
		
		if(QMC5883L_GetMagneticData(&g_QMC5883L_Handle,  &MagneticData[0], &MagneticData[1] , &MagneticData[2]) == TRUE)	//QMC5883L读取磁力计原始数据
		{
			uart_printf("[QMC5883L]磁力计:%d %d %d\r\n", MagneticData[0],MagneticData[1],MagneticData[2]);
		}
		else
		{
			uart_printf("[QMC5883L]磁力计:ERROR\r\n");
		}
	
		Sleep(500);
	}
	
}

//*************************************************** 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); // }
### 解决 IntelliJ IDEA 中 `@Autowired` 注解导致的红色波浪线错误 在使用 Spring 框架时,如果遇到 `@Autowired` 注解下的依赖注入对象显示为红色波浪线错误或者黄色警告的情况,通常是由以下几个原因引起的: #### 1. **Spring 插件未启用** 如果 Spring 支持插件未被激活,则可能导致 IDE 无法识别 `@Autowired` 或其他 Spring 特定的功能。可以通过以下方式解决问题: - 打开设置菜单:`File -> Settings -> Plugins`。 - 确认已安装并启用了名为 “Spring Framework Support” 的官方插件[^1]。 #### 2. **项目配置文件缺失或不正确** Spring 需要通过 XML 文件、Java Config 类或其他形式来定义 Bean 定义。如果没有正确加载这些配置文件,可能会导致 `@Autowired` 报错。 - 确保项目的 `applicationContext.xml` 或者基于 Java 的配置类(带有 `@Configuration` 和 `@Bean` 注解)已被正确定义和引入。 - 对于 Spring Boot 项目,确认是否存在 `spring.factories` 文件以及是否包含了必要的组件扫描路径[^3]。 #### 3. **模块依赖关系问题** 当前模块可能缺少对 Spring Core 或 Context 组件库的有效引用。这可能是由于 Maven/Gradle 构建工具中的依赖项声明不足造成的。 - 检查 `pom.xml` (Maven) 或 `build.gradle` (Gradle),确保包含如下核心依赖之一: ```xml <!-- For Maven --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> ``` ```gradle // For Gradle implementation 'org.springframework:spring-context:${springVersion}' ``` - 更新项目依赖树以应用更改:右键点击项目根目录 -> `Maven -> Reload Project` 或运行命令 `./gradlew build --refresh-dependencies`。 #### 4. **IDE 缓存损坏** Intellij IDEA 的缓存机制有时会因各种因素而失效,从而引发误报错误。清除缓存可以有效缓解此类情况。 - 使用快捷组合键 `Ctrl + Alt + Shift + S` 进入项目结构对话框;也可以尝试执行操作序列:`File -> Invalidate Caches / Restart... -> Invalidate and Restart`. #### 5. **启动异常影响正常解析** 若之前存在类似 `com.intellij.diagnostic.PluginException` 的严重初始化失败日志记录,则表明某些关键服务未能成功加载,进而干扰到后续功能表现[^2]。建议重新下载最新稳定版本的 IDEA 并按照标准流程完成初次部署工作。 ```java // 示例代码片段展示如何正确运用 @Autowired 注解实现自动装配 @Service public class StudentService { private final Repository repository; public StudentService(@Qualifier("specificRepository") Repository repo){ this.repository = repo; } } @Component class SpecificComponent{ @Autowired private transient StudentService studentService; // 此处应无任何编译期告警现象发生 } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cp1300

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值