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