HMC5883l地磁场传感器,读取数据问题,麻烦看一下,谢谢!

2019-10-15 19:15发布

使用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]
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
11条回答
jubichang
1楼-- · 2019-10-16 16:05
看看地址是不是写错了 如果是硬件I2C的话 那么地址是7位的 而网上的程序中的HMC的地址是8位的 ox3C   7位是0X1E 
junhuadesizhou
2楼-- · 2019-10-16 21:18
,我用的也是gy86模块,虽然是很久之前的帖子了,但是我用模拟i2c读取6050是安全没有问题的,6050里也配置了bypass模式,8位读地址为0x3c, 在初始化6050 后,打算读hmc5883l的地址,发现器件一直没有应答,很是郁闷啊
297161893
3楼-- · 2019-10-16 22:42
junhuadesizhou 发表于 2016-12-21 11:14
,我用的也是gy86模块,虽然是很久之前的帖子了,但是我用模拟i2c读取6050是安全没有问题的,6050里也配置 ...

楼主解决这个没应答信号的问题了吗?我拿逻辑分析仪去抓波形也发现没应答信号,读出来的数据全是0xff
junhuadesizhou
4楼-- · 2019-10-16 22:55
 精彩回答 2  元偷偷看……
297161893
5楼-- · 2019-10-17 01:13
junhuadesizhou 发表于 2017-1-4 21:23
我现在是有应答了,但是第一次上电肯定不行,得多复位几次才有应答

规格书上没有复位指令吧?

一周热门 更多>