[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
");
}
//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
");
}
//***************************************************[/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
",x);
printf("y:%d
",y);
printf("z:%d
",z);
printf("angle:%.2f
",angle);
}
}[/mw_shl_code]
[mw_shl_code=c,true]
[/mw_shl_code]
---------------------------------
就是这个程序,楼主的代码已经贴出来了
---------------------------------
对的,是要把BYPASS模式打开的,要设置一下就可以了。我这个程序是适合只有HMC5883模块的(直接接单片机的IIC),想把那个图删掉没发现操作的地方,后来忙就忘了,误导你了不好意思。不过我当时在GY87上也调通了,就是对着手册设置个寄存器就行了。你先试一下,不行的话改天我有空把程序再改一下
---------------------------------
麻烦你给个gy87的程序吧,我觉得这个也不难,之前怀疑模块坏了(因为看到有人是买到坏的模块) 然后我又买了2个模块,还是没弄好,我在想要不要换一家买个试下呢~~~~~55555~~~~~
我的模块和你的一样,磁力计也是挂载在MPU6050上的,可是我看网上说需要把MPU6050的I2C改成直通模式才能直接的访问HMC5883L。但是我看你代码没有啊。
一周热门 更多>