OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 9954|回复: 21

求助关于用模拟I2C读取HMC5883L磁罗盘数据的问题?

[复制链接]

5

主题

27

帖子

0

精华

初级会员

Rank: 2

积分
85
金钱
85
注册时间
2015-4-6
在线时间
4 小时
发表于 2015-5-7 21:37:15 | 显示全部楼层 |阅读模式
5金钱
[mw_shl_code=c,true]求哪位高手帮我看看哪里的问题,读取数据用的I2C时序全是原子哥例程里照搬的,读取HMC5883L数据部分也是根据一位吧友的改的(改动很小),现在读取数据返回的全是65535,检测引脚电压一直为3.3V,不确定是不是硬件问题。硬件用的是GY-87的模块,包含MPU6050,BMP180,HMC5883L三个传感器,我现在只用这一个,对另外两个也没处理,不知道有没有影响?[/mw_shl_code] [mw_shl_code=c,true][/mw_shl_code]
IIC.h文件
[mw_shl_code=c,true]#ifndef __IIC_H #define __IIC_H #include "sys.h" #include "delay.h" #include "USART3.h" //IO方向设置 #define SDA_IN() {GPIOA->CRH&=0XFFFF0FFF;GPIOA->CRH|=8<<12;} //PA11 通用推挽输出模式,最大速度50MHZ #define SDA_OUT() {GPIOA->CRH&=0XFFFF0FFF;GPIOA->CRH|=3<<12;} //PA11 上拉/下拉输入模式 //IO操作函数 #define IIC_SCL PAout(10) //SCL #define IIC_SDA PAout(11) //SDA #define READ_SDA PAin(11) //输入SDA //IIC所有操作函数 void IIC_Init(void); //初始化IIC的IO口 void IIC_Start(void); //发送IIC开始信号 void IIC_Stop(void); //发送IIC停止信号 void IIC_Send_Byte(u8 txd); //IIC发送一个字节 u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节 //读一个字节,ack = 1时, 发送ACK, ack = 0,发送nACK u8 IIC_Wait_Ack(void); //IIC等待ACK信号 void IIC_Ack(void); //IIC发送ACK信号 void IIC_NAck(void); //IIC不发送ACK信号 void IIC(void); #endif [/mw_shl_code]
IIC.c文件
[mw_shl_code=c,true]#include "IIC.h" #include "USART3.h" void IIC_Init(void) { // RCC->APB2ENR |= 1 << 4; // GPIOC->CRH &= 0xfff00fff; //PC11 PC12推挽输出 // GPIOC->CRH |= 0x00033000; // GPIOC->ODR |= 3 << 11; //PC11 PC12输出高 // // RCC->APB2ENR |= 1 << 3;//先使能外设IO PORTB时钟 // GPIOB->CRL &= 0X00FFFFFF;//PB6-SCL PB7-SDA 推挽输出 // GPIOB->CRL |= 0X33000000; // GPIOB->ODR |= 0X03 << 6; // 拉高 GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_SetBits(GPIOA,GPIO_Pin_10|GPIO_Pin_11); //PA10,PA11 输出高 printf("i'm iic init\n"); } //void IIC(void) //此函数功能是点亮开发板上PC13所连小灯,验证PCout()位带操作是否可用 //{ // GPIO_InitTypeDef GPIO_InitStructure; // RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE ); // // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出 // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // GPIO_Init(GPIOC, &GPIO_InitStructure); // PCout(13)=0; //SCL //} //产生IIC起始信号 void IIC_Start(void) { SDA_OUT(); //sda线输出 IIC_SDA=1; IIC_SCL=1; delay_us(4); IIC_SDA=0;//START:when CLK is high,DATA change form high to low delay_us(4); IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 } //产生IIC停止信号 void IIC_Stop(void) { SDA_OUT();//sda线输出 IIC_SCL=0; IIC_SDA=0;//STOP:when CLK is high DATA change form low to high delay_us(4); IIC_SCL=1; IIC_SDA=1;//发送I2C总线结束信号 delay_us(4); } //等待应答信号到来 //返回值:1,接收应答失败 // 0,接收应答成功 u8 IIC_Wait_Ack(void) { u8 ucErrTime=0; SDA_IN(); //SDA设置为输入 IIC_SDA=1;delay_us(1); IIC_SCL=1;delay_us(1); while(READ_SDA) { ucErrTime++; if(ucErrTime>250) { IIC_Stop(); return 1; } } IIC_SCL=0;//时钟输出0 return 0; } //产生ACK应答 void IIC_Ack(void) { IIC_SCL=0; SDA_OUT(); IIC_SDA=0; delay_us(2); IIC_SCL=1; delay_us(2); IIC_SCL=0; } //不产生ACK应答 void IIC_NAck(void) { IIC_SCL=0; SDA_OUT(); IIC_SDA=1; delay_us(2); IIC_SCL=1; delay_us(2); IIC_SCL=0; } //IIC发送一个字节 //返回从机有无应答 //1,有应答 //0,无应答 void IIC_Send_Byte(u8 txd) { u8 t; SDA_OUT(); IIC_SCL=0;//拉低时钟开始数据传输 for(t=0;t<8;t++) { //IIC_SDA=(txd&0x80)>>7; if((txd&0x80)>>7) IIC_SDA=1; else IIC_SDA=0; txd<<=1; delay_us(2); //对TEA5767这三个延时都是必须的 IIC_SCL=1; delay_us(2); IIC_SCL=0; delay_us(2); } } //读1个字节,ack=1时,发送ACK,ack=0,发送nACK u8 IIC_Read_Byte(unsigned char ack) { unsigned char i,receive=0; SDA_IN();//SDA设置为输入 for(i=0;i<8;i++ ) { IIC_SCL=0; delay_us(2); IIC_SCL=1; receive<<=1; if(READ_SDA)receive++; delay_us(1); } if (!ack) IIC_NAck();//发送nACK else IIC_Ack(); //发送ACK return receive; } [/mw_shl_code]
HMC5883L.h 文件
[mw_shl_code=c,true]#ifndef __HMC5883L_H #define __HMC5883L_H #include "sys.h" #include "IIC.h" #include "USART3.h" #define SlaveAddress 0x3C void Init_HMC5883(void); void Write_HMC5883(u8 add, u8 da); u8 Read_HMC5883(u8 REG_Address); void Multiple_read_HMC5883(u8*BUF); #endif [/mw_shl_code]
hmc5883l.c文件
[mw_shl_code=c,true]#include "HMC5883L.h" #include "IIC.h" #define SlaveAddress 0x3C void Init_HMC5883(void) { // //IIC_Init(); // Write_HMC5883(0x00, 0x78); //每次测量输出中选择采样平均数8; 在连续测量模式下的所有可选的输出速率75hz // Write_HMC5883(0x01, 0x00); //增益设置 // Write_HMC5883(0x02, 0x00); //连续测量模式 Write_HMC5883(0x00, 0x70); //每次测量输出中选择采样平均数8; 在连续测量模式下的所有可选的输出速率75hz Write_HMC5883(0x01, 0xA0); //增益设置 Write_HMC5883(0x02, 0x00); //连续测量模式 } void Write_HMC5883(u8 add, u8 da) { IIC_Start(); //起始信号 IIC_Send_Byte(SlaveAddress); //发送设备地址+写信号 IIC_Wait_Ack(); IIC_Send_Byte(add); //内部寄存器地址,请参考中文pdf IIC_Wait_Ack(); IIC_Send_Byte(da); //内部寄存器数据,请参考中文pdf IIC_Wait_Ack(); IIC_Stop(); //发送停止信号 delay_ms(10);//后加 } u8 Read_HMC5883(u8 REG_Address) { u8 REG_data; IIC_Start(); //起始信号 IIC_Send_Byte(SlaveAddress); //发送设备地址+写信号 IIC_Wait_Ack(); IIC_Send_Byte(REG_Address); //发送存储单元地址,从0开始 IIC_Wait_Ack(); IIC_Start(); //起始信号 IIC_Send_Byte(SlaveAddress+1); //发送设备地址+读信号 IIC_Wait_Ack(); REG_data=IIC_Read_Byte(0); //读出寄存器数据 IIC_Stop(); //停止信号 delay_ms(5);//后加 return REG_data; } //****************************************************** // //连续读出HMC5883内部角度数据,地址范围0x3~0x5 // //****************************************************** void Multiple_read_HMC5883(u8* BUF) { u8 i; IIC_Start(); //起始信号 IIC_Send_Byte(SlaveAddress); //发送设备地址+写信号 IIC_Wait_Ack(); IIC_Send_Byte(0x03); //发送存储单元地址,从0x3开始 IIC_Wait_Ack(); IIC_Start(); //起始信号 IIC_Send_Byte(SlaveAddress+1); //发送设备地址+读信号 IIC_Wait_Ack(); for (i=0; i<6; i++) //连续读取6个地址数据,存储中BUF { if (i == 5) { BUF = IIC_Read_Byte(0); //最后一个数据需要回NOACK } else { BUF = IIC_Read_Byte(1); //返回ACK } } IIC_Stop(); //停止信号 printf("i'm hmcmulread \n"); } //***************************************************[/mw_shl_code]

主函数
[mw_shl_code=c,true]#include "delay.h" #include "sys.h" #include "USART3.h" #include "gps.h" #include "string.h" #include "Distance.h" #include "stdio.h" #include <stm32f10x.h> #include "hmc5883l.h" #include "math.h" u8 BUF[6]; double angle; int main(void) { int x,y,z; // double x,y,z; SystemInit(); delay_init(); //延时函数初始化 NVIC_Configuration(); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 USART3_Init(9600); //初始化串口1 // IIC(); IIC_Init(); delay_ms(50); Init_HMC5883(); delay_ms(10); while(1) { delay_ms(20); Init_HMC5883(); Multiple_read_HMC5883(BUF); x=BUF[0] << 8 | BUF[1]; //Combine MSB and LSB of X Data output register z=BUF[2] << 8 | BUF[3]; //Combine MSB and LSB of Z Data output register y=BUF[4] << 8 | BUF[5]; //Combine MSB and LSB of Y Data output register /* if(x>32768) x = -(0xFFFF - x + 1); if(z>32768) z = -(0xFFFF - z + 1); if(y>32768) y = -(0xFFFF - y + 1); angle= (atan2((double)y,(double)x) * (180 / 3.14159265) + 180); // angle in degrees delay_ms(10); */ printf("x:%d \n",x); printf("y:%d \n",y); printf("z:%d \n",z); printf("angle:%.2f \n",angle); } }[/mw_shl_code] [mw_shl_code=c,true]

[/mw_shl_code]

最佳答案

查看完整内容[请看2#楼]

回复【5楼】opennedver: --------------------------------- 谢谢,已确定是硬件问题,换个就好了,证明程序是可用的。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

5

主题

27

帖子

0

精华

初级会员

Rank: 2

积分
85
金钱
85
注册时间
2015-4-6
在线时间
4 小时
 楼主| 发表于 2015-5-7 21:37:16 | 显示全部楼层
回复【5楼】opennedver:
---------------------------------
谢谢,已确定是硬件问题,换个就好了,证明程序是可用的。
回复

使用道具 举报

5

主题

27

帖子

0

精华

初级会员

Rank: 2

积分
85
金钱
85
注册时间
2015-4-6
在线时间
4 小时
 楼主| 发表于 2015-5-7 21:39:44 | 显示全部楼层

GY-87模块原理图

回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2015-5-8 00:31:48 | 显示全部楼层
帮顶。。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

12

主题

53

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
246
金钱
246
注册时间
2015-1-28
在线时间
50 小时
发表于 2015-5-8 20:23:56 | 显示全部楼层
65535测量值溢出报错了
回复

使用道具 举报

12

主题

53

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
246
金钱
246
注册时间
2015-1-28
在线时间
50 小时
发表于 2015-5-8 20:25:21 | 显示全部楼层
回复【2楼】蜕变:
---------------------------------
你把程序和电路图打包一下,我调试一下
回复

使用道具 举报

14

主题

42

帖子

0

精华

初级会员

Rank: 2

积分
143
金钱
143
注册时间
2015-2-16
在线时间
5 小时
发表于 2015-8-7 21:13:15 | 显示全部楼层
回复【6楼】蜕变:
---------------------------------
能否分享一下!我老是有问题,出不来!先谢过了!
回复

使用道具 举报

12

主题

53

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
246
金钱
246
注册时间
2015-1-28
在线时间
50 小时
发表于 2015-8-30 22:36:32 | 显示全部楼层
回复【7楼】流浪者转世:
---------------------------------
就是这个程序,楼主的代码已经贴出来了
回复

使用道具 举报

20

主题

122

帖子

0

精华

高级会员

Rank: 4

积分
637
金钱
637
注册时间
2014-6-20
在线时间
168 小时
发表于 2015-9-25 11:32:34 | 显示全部楼层
LZ  你这个hmc5883L 不应该是连在mpu6050上的吗?  不是应该设置 mpu6050  为bypass模式吗  怎么没见你初始化mpu?  跪求跪求啊!!!!!我也是gy87 调不出 hmc啊
回复

使用道具 举报

5

主题

27

帖子

0

精华

初级会员

Rank: 2

积分
85
金钱
85
注册时间
2015-4-6
在线时间
4 小时
 楼主| 发表于 2015-9-28 09:54:01 | 显示全部楼层
回复【9楼】Fliger:
---------------------------------
对的,是要把BYPASS模式打开的,要设置一下就可以了。我这个程序是适合只有HMC5883模块的(直接接单片机的IIC),想把那个图删掉没发现操作的地方,后来忙就忘了,误导你了不好意思。不过我当时在GY87上也调通了,就是对着手册设置个寄存器就行了。你先试一下,不行的话改天我有空把程序再改一下
回复

使用道具 举报

20

主题

122

帖子

0

精华

高级会员

Rank: 4

积分
637
金钱
637
注册时间
2014-6-20
在线时间
168 小时
发表于 2015-10-26 17:32:04 | 显示全部楼层
回复【10楼】蜕变:
---------------------------------
麻烦你给个gy87的程序吧,我觉得这个也不难,之前怀疑模块坏了(因为看到有人是买到坏的模块)  然后我又买了2个模块,还是没弄好,我在想要不要换一家买个试下呢~~~~~55555~~~~~
回复

使用道具 举报

12

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2013-12-22
在线时间
1 小时
发表于 2015-10-27 00:10:49 | 显示全部楼层
楼主是在做四轴吗?我虽然不是用的模块,不过也是mpu6050+hmc5883+bmp085的方案,可否加个QQ交流下?
哪管多少辛酸已获胜算!
回复

使用道具 举报

0

主题

14

帖子

0

精华

初级会员

Rank: 2

积分
63
金钱
63
注册时间
2015-3-3
在线时间
7 小时
发表于 2016-1-17 17:27:01 | 显示全部楼层
蜕变 发表于 2015-5-7 21:39
GY-87模块原理图

我的模块和你的一样,磁力计也是挂载在MPU6050上的,可是我看网上说需要把MPU6050的I2C改成直通模式才能直接的访问HMC5883L。但是我看你代码没有啊。
回复

使用道具 举报

1

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
170
金钱
170
注册时间
2015-12-14
在线时间
63 小时
发表于 2016-3-27 10:24:45 | 显示全部楼层
HMC5883L问题

HMC5883L手册上的输出范围0XF800-0X7FF(-2048----2047)
为什么我读出来的数很多超过0XF800了呢   如:65180
回复

使用道具 举报

2

主题

19

帖子

0

精华

新手上路

积分
43
金钱
43
注册时间
2016-3-22
在线时间
5 小时
发表于 2016-3-31 17:10:56 | 显示全部楼层
songhuagao,我也遇到这个问题了,输出的全是65535,你解决了吗
回复

使用道具 举报

0

主题

3

帖子

0

精华

新手入门

积分
23
金钱
23
注册时间
2016-4-18
在线时间
4 小时
发表于 2016-4-30 20:28:32 | 显示全部楼层
怎么会出来6w多的数呢
回复

使用道具 举报

1

主题

4

帖子

0

精华

初级会员

Rank: 2

积分
59
金钱
59
注册时间
2016-8-31
在线时间
14 小时
发表于 2016-9-1 17:19:27 | 显示全部楼层
楼主的硬件是怎么连接的呢?
回复

使用道具 举报

0

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
63
金钱
63
注册时间
2016-7-13
在线时间
18 小时
发表于 2016-10-14 14:42:55 | 显示全部楼层
楼主,我的代码和你差不多,怎么我的显示是180啊,角度
回复

使用道具 举报

0

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
63
金钱
63
注册时间
2016-7-13
在线时间
18 小时
发表于 2016-10-18 16:51:21 | 显示全部楼层
joyce931015 发表于 2016-3-31 17:10
songhuagao,我也遇到这个问题了,输出的全是65535,你解决了吗

耶,我也是65535,代码跟楼主的差不多,你的搞定了吗
回复

使用道具 举报

18

主题

79

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
302
金钱
302
注册时间
2016-10-1
在线时间
77 小时
发表于 2016-12-3 21:44:55 | 显示全部楼层
xiexie
回复

使用道具 举报

18

主题

79

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
302
金钱
302
注册时间
2016-10-1
在线时间
77 小时
发表于 2016-12-5 21:45:28 | 显示全部楼层
谢谢分享
回复

使用道具 举报

2

主题

6

帖子

0

精华

新手入门

积分
19
金钱
19
注册时间
2016-12-21
在线时间
4 小时
发表于 2016-12-21 11:30:54 | 显示全部楼层
我用的gy86 ,hmc 的i2c也是挂载在6050的副通道上的,bypass模式已经设置好,给0x6a寄存器的值为0x00,0x37寄存器的值为0x02,在初始化完6050后,就直接看看有没有hmc这个设备了,但是一直都没有器件应答啊,很是郁闷啊
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-26 08:35

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表