基本信息:测量范围-8~8G、16位ADC采样、-40~85℃、最大200HZ的数据输出率。
重点来了:淘宝上面现在买的三轴磁传感器模块GY-273,其实用的都是QMC5883,但是却标的是HMC5883,最重要的是两个芯片的IIC地址、寄存器也都不一样,这实在是太坑了啊。
寄存器以及IIC地址:
寄存器从00H-0DH,14个寄存器。
7位IIC地址0x0D ,如果需要其他地址,联系厂家订做。
======================================================================================
1、通过读取ID,查看是否能检测到芯片:
bool CheckQMC5883Chip()
{
uint8_t ChipID=0;
I2cReadByte( 0, QMC5883_ADDRESS, QMC5883_REG_PRODUCTID, &ChipID );
if(ChipID==0xFF)
{
return true;
}
else
{
return false;
}
}
读取寄存器0DH,读数固定为0xFF,也可以用于测试iic驱动是否正常,当然也可以用于判断传感器是否存在。
2、设置芯片的工作模式:
主要设置控制寄存器1和控制寄存器2
其中,控制寄存器1主要设置采样模式:待机模式和连续测量模式,上电之后处于待机模式;
数据输出速率(ODR):四个特定速率,10hz、50hz、100hz、200hz(单片机读数速率不能超过相应的数据输出速率);
满量程范围:2G、8G(量程越大,精度也就越低;反之);
过采样率:64、128、256、512。
void InitQMC5883()
{
I2cWriteByte( 0, QMC5883_ADDRESS, QMC5883_REG_CTRL2, QMC5883_CMD_SOFT_RST_ENABLE );
//使能软件复位
I2cWriteByte( 0, QMC5883_ADDRESS, QMC5883_REG_CTRL1, QMC5883_CMD_MODE_CON|QMC5883_CMD_ODR_10HZ|QMC5883_CMD_RNG_8G|QMC5883_CMD_OSR_512 );
//连续模式、满量程为8G、过采样率
I2cWriteByte( 0, QMC5883_ADDRESS, QMC5883_REG_CTRL2, QMC5883_CMD_INT_DISABLE|QMC5883_CMD_ROL_PNT_ENABLE );
//不使用中断,数据指针自动移动到下一个地址(在寄存器00H~05H之间)
}
3、读数
主要是寄存器00H~05H,连续测量模式下,根据设置的速率数据周期更新,是有符号数据,范围在-32768~32768之间。
void GetQMC5883Data()
{
int16_t mxyz[10][3] = {0};
int32_t avermxyz[3]={0};
uint8_t buffer[6]={0};
static float magGaussData[3] = {0.0};
static uint8_t cnt=0;
I2cReadData( 0, QMC5883_ADDRESS, QMC5883_REG_DATA, buffer, 6 );
printf("Xl=%d,Xh=%d,Yl=%d,Yh=%d,Zl=%d,Zh=%d\r\n",buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5]);
mxyz[cnt][0] = (int16_t)(buffer[1] << 8 | buffer[0]);
mxyz[cnt][1] = (int16_t)(buffer[3] << 8 | buffer[2]);
mxyz[cnt][2] = (int16_t)(buffer[5] << 8 | buffer[4]);
cnt++;
if(cnt>=10)
{
cnt=0;
for(uint8_t i=0,j=0;i<3;i++)
{
for(j=0;j<10;j++)
{
avermxyz[i]+=mxyz[j][i];
}
avermxyz[i]=avermxyz[i]/10;
}
printf("average original data :x=%d,y=%d,z=%d\r\n",avermxyz[0],avermxyz[1],avermxyz[2]);
for(uint8_t k=0;k<3;k++)
{
magGaussData[k]=magGaussData[k]-32768; //32768:Null Field Output
magGaussData[k]=avermxyz[k]/3000; //3000:sensitivity, 3000 counts/G
}
printf("convert the raw data :x=%f,y=%f,z=%f\r\n",magGaussData[0],magGaussData[1],magGaussData[2]);
printf("\r\n");
}
DelayMs(3000);
}
读数减去32768是因为,是有磁场是有符号数,除以3000是满量程在8G的时候对应的灵敏度。
4、其他
(1)SET/RESET寄存器
我查阅了其他的磁传感器,set/reset功能主要用于防止芯片被磁化,设置这个寄存器之后,需要重新初始化芯片。
(2)状态寄存器
中断产生的时候需要读取这个寄存器,查询中断的类型,其中DRDY位,在数据转化完成之后置1、读取数据寄存器之后自动清0。
如要使能中断,需要配置INT引脚连接到mcu,mcu对应的引脚设置为输入中断,会产生上升沿中断,同时控制寄存器2的INT_ENB字段也要设置为0。
(3)温度寄存器
精度100LSB/℃,说直白点,读数需要除以100,才是真是温度。
将寄存器以及需要设置的参数定义如下:
#define QMC5883_REG_DATA 0x00
#define QMC5883_REG_OUT_X_L 0x00
#define QMC5883_REG_OUT_X_M 0x01
#define QMC5883_REG_OUT_Y_L 0x02
#define QMC5883_REG_OUT_Y_M 0x03
#define QMC5883_REG_OUT_Z_L 0x04
#define QMC5883_REG_OUT_Z_M 0x05
#define QMC5883_REG_STATUS 0x06
#define QMC5883_DRDY_BIT0 //0: no new data, 1: new data is ready
#define QMC5883_OVL_BIT1 //0: normal, 1: data overflow
#define QMC5883_DOR_BIT2 //0: normal, 1: data skipped for reading
#define QMC5883_REG_TEMP_OUT_L 0x07
#define QMC5883_REG_TEMP_OUT_H 0x08
#define QMC5883_REG_CTRL1 0x09
#define QMC5883_CMD_MODE_STANDBY 0x00 //mode
#define QMC5883_CMD_MODE_CON 0x01
#define QMC5883_CMD_ODR_10HZ 0x00 //Output Data Rate
#define QMC5883_CMD_ODR_50HZ 0x04
#define QMC5883_CMD_ODR_100HZ 0x08
#define QMC5883_CMD_ODR_200HZ 0x0C
#define QMC5883_CMD_RNG_2G 0x00 //Full Scale
#define QMC5883_CMD_RNG_8G 0x10
#define QMC5883_CMD_OSR_512 0x00 //Over Sample Ratio
#define QMC5883_CMD_OSR_256 0x40
#define QMC5883_CMD_OSR_128 0x80
#define QMC5883_CMD_OSR_64 0xC0
#define QMC5883_REG_CTRL2 0x0A
#define QMC5883_CMD_INT_ENABLE 0x00
#define QMC5883_CMD_INT_DISABLE 0x01
#define QMC5883_CMD_ROL_PNT_ENABLE 0x40 //pointer roll-over function,only 0x00-0x06 address
#define QMC5883_CMD_ROL_PNT_DISABLE 0x00
#define QMC5883_CMD_SOFT_RST_ENABLE 0x80
#define QMC5883_CMD_SOFT_RST_DISABLE 0x00
#define QMC5883_REG_SET_RESET 0x0B
#define QMC5883_CMD_SET_RESET 0x01
#define QMC5883_REG_PRODUCTID 0x0D //chip id :0xFF