使用MK60FX512芯片的硬件I2C读取MPU6050成功,但是再用它读取HMC5883L时,XYZ轴都是0,表示很郁闷,使用的是GY-86模块,HMC5883L接到MPU6050辅助I2C管脚上。程序如下,麻烦看一下是否正确?
[mw_shl_code=c,true]原理图请看这个连接:http://www.openedv.com/posts/list/38503.htm [/mw_shl_code]
谢谢!
[mw_shl_code=c,true]//程序里已经在MPU6050初始化程序里写了,下面的语句
i2c_write_bit(MPU6050_I2C_Moudle, MPU6050_ADDRESS, MPU6050_USER_CTRL, 5, 0);//不让MPU6050控制辅助I2C(AUX I2C),成为外部传感器的主机
i2c_write_bit(MPU6050_I2C_Moudle, MPU6050_ADDRESS, MPU6050_INT_PIN_CFG, 1, 1);//K60与MPU6050的辅助I2C(AUX I2C)直通,K60可以直接访问HMC5883L
// i2c_write_bit函数内容
void i2c_write_bit(I2Cn_e i2cn, uint8 SlaveID, uint8 reg, uint8 bitNum, uint8 data)
{
uint8 a,b;
a = i2c_read_reg(i2cn, SlaveID, reg);
b = (data != 0) ? (a | (1 << bitNum)) : (a & ~(1 << bitNum));
i2c_write_reg(i2cn, SlaveID, reg, b);
}
//HMC5883L也是用硬件I2C,读取一个字节、写一个字节的函数都是一样
//I2C的启动信号,停止信号,应答信号也一样
/**************************下面是HMC5883L程序************/
//.C文件
#include "hmc5883.h"
#include "MK60_i2c.h"
#include "common.h"
float x_scale,y_scale,z_scale;//温度变化比例因子
float HMC5883_lastx,HMC5883_lasty,HMC5883_lastz;
int16 HMC5883_FIFO[3][11]; //磁力计滤波
int16 HMC5883_maxx=0,HMC5883_maxy=0,HMC5883_maxz=0,HMC5883_minx=-0,HMC5883_miny=-0,HMC5883_minz=-0;//磁力计标定值
uint8 HMC5883_calib=0; //初始化完成标志
//每个增益系数对应的 LSb/Gauss
const int16 counts_per_milligauss[8]=
{
1370, //+-0.88Ga
1090, //+-1.3Ga
820, //+-1.9Ga
660, //+-2.5Ga
440, //+-4.0Ga
390, //+-4.7Ga
330, //+-5.6Ga
230 //+-8.1Ga
};
/*
int16 HMC5883_GetDoubleData(uint8 Addr)
{
uint16 data=0x0000;
data=i2c_read_reg(HMC5883_I2C_Moudle,HMC5883_ADDRESS, Addr);
data=(uint16)((data<<8)&0xff00);
data+=i2c_read_reg(HMC5883_I2C_Moudle,HMC5883_ADDRESS, Addr+1);
//int16 data;
//data= ((int16)i2c_read_reg(MPU6050_I2C_Moudle,MPU6050_ADDRESS, Addr)<<8)
// |(int16)i2c_read_reg(MPU6050_I2C_Moudle,MPU6050_ADDRESS, Addr+1);
return (int16)data;//合成数据,为有符号整形数
}
void HMC5883_init(void)
{
i2c_init(I2C0,400*1000); // 初始化I2C0,期待的波特率为400k
i2c_write_reg(HMC5883_I2C_Moudle,HMC5883_ADDRESS,HMC_CFG1, 0x78);
i2c_write_reg(HMC5883_I2C_Moudle,HMC5883_ADDRESS,HMC_CFG2, 0x00);
i2c_write_reg(HMC5883_I2C_Moudle,HMC5883_ADDRESS,HMC_MOD, 0x00);
}
*/
//滑动平均滤波
void HMC58X3_newValues(int16 x,int16 y,int16 z)
{
uint8 i,j;
int16 min[3],max[3];
int32 sum_data = 0;
for(j=1;j<10;j++)
{
HMC5883_FIFO[0][j-1]=HMC5883_FIFO[0][j];
HMC5883_FIFO[1][j-1]=HMC5883_FIFO[1][j];
HMC5883_FIFO[2][j-1]=HMC5883_FIFO[2][j];
}
//找极值
for(i=0;i<3;i++)
{
min = HMC5883_FIFO[0];
max = HMC5883_FIFO[0];
for(j=0;j<10;j++)
{
if(max<=HMC5883_FIFO[j])
max = HMC5883_FIFO[j];
if(min>=HMC5883_FIFO[j])
min = HMC5883_FIFO[j];
}
}
//去极值求平均
for(i=0;i<3;i++)
{
for(j=0;j<10;j++)
{
sum_data += HMC5883_FIFO[j];
HMC5883_FIFO[10] = (sum_data - min - max)/8;
}
sum_data = 0;
}
if(HMC5883_calib)//校正有效,采集标定值
{
if(HMC5883_minx>HMC5883_FIFO[0][10])HMC5883_minx=HMC5883_FIFO[0][10];
if(HMC5883_miny>HMC5883_FIFO[1][10])HMC5883_miny=HMC5883_FIFO[1][10];
if(HMC5883_minz>HMC5883_FIFO[2][10])HMC5883_minz=HMC5883_FIFO[2][10];
if(HMC5883_maxx<HMC5883_FIFO[0][10])HMC5883_maxx=HMC5883_FIFO[0][10];
if(HMC5883_maxy<HMC5883_FIFO[1][10])HMC5883_maxy=HMC5883_FIFO[1][10];
if(HMC5883_maxz<HMC5883_FIFO[2][10])HMC5883_maxz=HMC5883_FIFO[2][10];
//LED_Change();
}
}
//读取磁力计当前ADC值
void HMC58X3_getlastValues(int16 *x,int16 *y,int16 *z)
{
*x = HMC5883_FIFO[0][10];
*y = HMC5883_FIFO[1][10];
*z = HMC5883_FIFO[2][10];
}
//读取校正后的ADC值
void HMC58X3_mgetValues(float *arry)
{
int16 xr,yr,zr;
HMC58X3_getRaw(&xr, &yr, &zr);
arry[0]= HMC5883_lastx=(float)(xr-((HMC5883_maxx+HMC5883_minx)/2));
arry[1]= HMC5883_lasty=(float)(yr-((HMC5883_maxy+HMC5883_miny)/2));
arry[2]= HMC5883_lastz=(float)(zr-((HMC5883_maxz+HMC5883_minz)/2));
}
//比较大小
int16 min(int16 x,int16 y)
{
if(x<y)
return x;
else
return y;
}
//一次获取16位数据,2个字节(方法一)
int16 HMC5883L_Axes_data(uint8 reg_addr)
{
int16 xyz_data;
xyz_data = ((int16)i2c_read_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, reg_addr)<<8)
|(int16)i2c_read_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, reg_addr+1);
return xyz_data;
}
//获取HMC5883L ID
void HMC58X3_getID(int8 id[3])
{
id[0]=i2c_read_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, HMC58X3_R_IDA);
id[1]=i2c_read_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, HMC58X3_R_IDB);
id[2]=i2c_read_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, HMC58X3_R_IDC);
}
/**********************************************************************
输入参数: 速率值(DOR)
0 -> 0.75Hz | 1 -> 1.5Hz
2 -> 3Hz | 3 -> 7.5Hz
4 -> 15Hz | 5 -> 30Hz
6 -> 75Hz
**********************************************************************/
//设置HMC5883L的数据输出速率
void HMC58X3_setDOR(uint8 DOR)
{
if (DOR>6)
return;
i2c_write_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, HMC58X3_R_CONFA,DOR<<2);
}
//设置HMC5883L增益
void HMC58X3_setGain(uint8 gain)
{
if (gain > 7)
return;
i2c_write_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, HMC58X3_R_CONFB, gain << 5);
}
//设置HMC5883L有效的工作模式
void HMC58X3_setMode(uint8 mode)
{
if (mode > 2)//判断mode是否超出有效的模式范围
{
return;
}
i2c_write_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, HMC58X3_R_MODE, mode);
DELAY_US(100);
}
//获取X、Y、Z轴数据
void HMC58X3_getRaw(int16 *x,int16 *y,int16 *z)
{
uint8 vbuff[6];
vbuff[0] = i2c_read_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, HMC58X3_R_XM);
vbuff[1] = i2c_read_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, HMC58X3_R_XL);
vbuff[2] = i2c_read_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, HMC58X3_R_ZM);
vbuff[3] = i2c_read_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, HMC58X3_R_ZL);
vbuff[4] = i2c_read_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, HMC58X3_R_YM);
vbuff[5] = i2c_read_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, HMC58X3_R_YL);
HMC58X3_newValues(((int16)vbuff[0] << 8) | vbuff[1],((int16)vbuff[4] << 8) | vbuff[5],((int16)vbuff[2] << 8) | vbuff[3]);
*x = HMC5883_FIFO[0][10];
*y = HMC5883_FIFO[1][10];
*z = HMC5883_FIFO[2][10];
}
//填充HMC5883_FIFO数组
void HMC58X3_FIFO_init(void)
{
int16 temp[3];
uint8 i;
for(i=0;i<100;i++)
{
HMC58X3_getRaw(&temp[0],&temp[1],&temp[2]);
DELAY_US(200); //延时再次读取数据
//LED_Change();
}
}
//使用HMC5883L内部的磁场进行初步自检测标定
void HMC58X3_calibrate(uint8 gain,uint8 n_samples)//gain:增益0-7;n_samples采样次数
{
int16 xyz[3]; //2字节,存放X、Y、Z轴的磁场
int32 xyz_total[3]={0,0,0}; //4字节,数据不会溢出
uint8 bret=1; //函数返回值
int8 id[3]; //存放芯片ID
int32 low_limit, high_limit;
uint8 i;
//uint8 vbuff[6]; //读取HMC5883的字节数据缓冲
if ((8>gain) && (0<n_samples))
{
HMC58X3_getID(id); //读取芯片ID,检查是否是磁力计芯片
if (('H' == id[0]) && ('4' == id[1]) && ('3' == id[2]))
{
i2c_write_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS,HMC58X3_R_CONFA, 0x10 + HMC_POS_BIAS);//寄存器A配置为0x010 + HMC_POS_BIAS,数据输出速率15Hz;XYZ轴正偏压配置
HMC58X3_setGain(gain);
HMC58X3_setMode(1);//改变HMC5883L测量模式:单一测量模式
xyz[0] = HMC5883L_Axes_data(HMC58X3_R_XM);
xyz[0] = HMC5883L_Axes_data(HMC58X3_R_ZM);
xyz[0] = HMC5883L_Axes_data(HMC58X3_R_YM);
for ( i=0; i<n_samples; i++)
{
HMC58X3_setMode(1);//改变HMC5883L测量模式:单一测量模式
xyz[0] = HMC5883L_Axes_data(HMC58X3_R_XM);
xyz[0] = HMC5883L_Axes_data(HMC58X3_R_ZM);
xyz[0] = HMC5883L_Axes_data(HMC58X3_R_YM);
xyz_total[0]+=xyz[0];
xyz_total[1]+=xyz[1];
xyz_total[2]+=xyz[2];
if (-(1<<12) >= min(xyz[0],min(xyz[1],xyz[2])))
{
bret=0;//HMC58x3 Self test saturated. Increase range.
break;// Breaks out of the for loop. No sense in continuing if we saturated.
}
}
/*
Compare the values against the expected self test bias gauss.
Notice, the same limits are applied to all axis.
*/
low_limit =SELF_TEST_LOW_LIMIT *counts_per_milligauss[gain]*2*n_samples;
high_limit=SELF_TEST_HIGH_LIMIT*counts_per_milligauss[gain]*2*n_samples;
if ((bret) &&
(low_limit <= xyz_total[0]) && (high_limit >= xyz_total[0]) &&
(low_limit <= xyz_total[1]) && (high_limit >= xyz_total[1]) &&
(low_limit <= xyz_total[2]) && (high_limit >= xyz_total[2]) )
{
/*
Successful calibration.
Normalize the scale factors so all axis return the same range of values for the bias field.
Factor of 2 is from summation of total of n_samples from both positive and negative bias.
*/
x_scale=(counts_per_milligauss[gain]*(HMC58X3_X_SELF_TEST_GAUSS*2))/(xyz_total[0]/n_samples);
y_scale=(counts_per_milligauss[gain]*(HMC58X3_Y_SELF_TEST_GAUSS*2))/(xyz_total[1]/n_samples);
z_scale=(counts_per_milligauss[gain]*(HMC58X3_Z_SELF_TEST_GAUSS*2))/(xyz_total[2]/n_samples);
}
else
{
bret=0;//HMC58x3 Self test out of range.
}
i2c_write_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, HMC58X3_R_CONFA, 0x010); // set RegA/DOR back to default.
}
else
{
bret=0;//HMC5843 failed id check.
}
}
else
{
bret=0;//HMC58x3 Bad parameters.
}
i2c_write_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, HMC58X3_R_CONFA, 0x010); // set RegA/DOR back to default
}
//初始化HMC5883L
void HMC58X3_init(uint8 setmode)
{
if(setmode)//当setmode = 0时,跳过此设置,因为HMC5883L默认在0模式
{
HMC58X3_setMode(0);
}
x_scale=1.0;
y_scale=1.0;
z_scale=1.0;
i2c_write_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, HMC58X3_R_CONFA, 0x70);//采样平均数:8;数据输出速率:15Hz;测量配置(默认)
i2c_write_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, HMC58X3_R_CONFB, 0xA0);//增益配置:390Counts/高斯;推荐的传感器磁场范围:+-4.7Ga
i2c_write_reg(HMC5883_I2C_Moudle, HMC5883_ADDRESS, HMC58X3_R_MODE, 0x00);//连续测量模式
}
//启动HMC5883L
void HMC5883L_SetUp(void)
{
//HMC5883_calib=0;
HMC58X3_init(0);//初始化在0模式下工作
HMC58X3_calibrate(1, 32);//自检测标定
HMC58X3_setMode(0);
HMC58X3_setDOR(6); //75Hz更新率
HMC58X3_FIFO_init();
//读取标定值
}
//进入磁力计标定
void HMC5883L_Start_Calib(void)
{
HMC5883_calib = 1;//开始标定
HMC5883_maxx = 0; //将原来的标定值清除
HMC5883_maxy = 0;
HMC5883_maxz = 0;
HMC5883_minx = -0;
HMC5883_miny = -0;
HMC5883_minz = -0;
}
//保存磁力计标定值到Flash
void HMC5883L_Save_Calib(void)
{
}
//.H文件
#ifndef __HMC5883_H__
#define __HMC5883_H__
#include "common.h"
#define HMC_POS_BIAS 1
#define HMC_NEG_BIAS 2
#define HMC58X3_R_CONFA 0x00 //Register ConfigA
#define HMC58X3_R_CONFB 0x01 //Register ConfigB
#define HMC58X3_R_MODE 0x02 //Mode Register
#define HMC58X3_R_XM 0x03 //data output x MSB
#define HMC58X3_R_XL 0x04 //data output x LSB
#define HMC58X3_R_ZM 0x05 //data output y MSB
#define HMC58X3_R_ZL 0x06 //data output y LSB
#define HMC58X3_R_YM 0x07 //data output z MSB
#define HMC58X3_R_YL 0x08 //data output z LSB
#define HMC58X3_R_STATUS 0x09 //Statue Register
#define HMC58X3_R_IDA 0x10 //Identification Register A
#define HMC58X3_R_IDB 0x11 //Identification Register B
#define HMC58X3_R_IDC 0x12 //Identification Register C
#define HMC58X3_X_SELF_TEST_GAUSS (+1.16) //!< X axis level when bias current is applied.
#define HMC58X3_Y_SELF_TEST_GAUSS (HMC58X3_X_SELF_TEST_GAUSS) //!< Y axis level when bias current is applied.
#define HMC58X3_Z_SELF_TEST_GAUSS (+1.08) //!< Y axis level when bias current is applied.
#define SELF_TEST_LOW_LIMIT (243.0/390.0) //!< Low limit when gain is 5.
#define SELF_TEST_HIGH_LIMIT (575.0/390.0) //!< High limit when gain is 5.
#define HMC5883_I2C_Moudle I2C0
#define HMC5883_SLAVE_ADDRESS 0x3C
#define HMC5883_ADDRESS HMC5883_SLAVE_ADDRESS
// API函数接口
void HMC58X3_newValues(int16 x,int16 y,int16 z); //滑动平均滤波
void HMC58X3_getlastValues(int16 *x,int16 *y,int16 *z); //读取磁力计当前ADC值
void HMC58X3_mgetValues(float *arry); //读取校正后的ADC值
int16 min(int16 x,int16 y); //比较大小
int16 HMC5883L_Axes_data(uint8 reg_addr); //一次获取16位数据,2个字节(方法一)
void HMC58X3_getID(int8 id[3]); //获取HMC5883L ID
void HMC58X3_setDOR(uint8 DOR); //设置 5883L的 数据输出速率
void HMC58X3_setGain(uint8 gain); //设置HMC5883L增益
void HMC58X3_setMode(uint8 mode); //设置HMC5883L有效的工作模式
void HMC58X3_getRaw(int16 *x,int16 *y,int16 *z); //获取X、Y、Z轴数据
void HMC58X3_FIFO_init(void); //填充HMC5883_FIFO数组
void HMC58X3_calibrate(uint8 gain,uint8 n_samples); //使用HMC5883L内部的磁场自检测标定
void HMC58X3_init(uint8 setmode); //初始化HMC5883L
void HMC5883L_SetUp(void); //启动HMC5883L
void HMC5883L_Start_Calib(void); //进入磁力计标定
void HMC5883L_Save_Calib(void); //保存磁力计标定值到Flash
#endif
[/mw_shl_code]
一周热门 更多>