QMC5883L磁场传感器驱动

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);
	}
	
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

cp1300

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

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

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

打赏作者

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

抵扣说明:

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

余额充值