马学家 发表于 2013-6-17 16:50:00

帮忙来看个mpu6050程序

本帖最后由 马学家 于 2013-6-17 16:52 编辑

这个程序是网上找的,成功读出了数据,模拟IIC,但是我研究代码时却又个疑惑,读数据时SDA端口应该设置成输入模式啊,但是程序里却没有设置,好像也不影响,大神来解释下啊

还有个问题是读数据时好像要先写slaveadress,再写寄存器地址,在写操作数,这过程是不是个规矩啊,数据手册上好像没说啊。。

IIC.C#include "stm32f10x.h"
#include "iic_analog.h"


/************************************************************/
/*模拟IIC引脚初始化函数*/
/************************************************************/
void IIC_GPIO_Configuration( GPIO_TypeDef * GPIOx_SDA , uint16_t SDA_Pin , GPIO_TypeDef * GPIOx_SCL , uint16_t SCL_Pin )
{
        GPIO_InitTypeDef GPIO_InitStructure;
        uint32_t RCC_GPIOx_SDA = 0;
        uint32_t RCC_GPIOx_SCL = 0;

        //得到滤波后的引脚端口
        RCC_GPIOx_SDA = GPIO_Filter( GPIOx_SDA );
        RCC_GPIOx_SCL = GPIO_Filter( GPIOx_SCL );
       
        //使能时钟
    RCC_APB2PeriphClockCmd(RCC_GPIOx_SDA,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_GPIOx_SCL,ENABLE);

        //配置引脚
        GPIO_InitStructure.GPIO_Pin = SDA_Pin;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
        GPIO_Init(GPIOx_SDA, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = SCL_Pin;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
        GPIO_Init(GPIOx_SCL, &GPIO_InitStructure);

        //初始化ICC的模式
        SET_SDA;
        SET_SCL;
}


/************************************************************/
/************************************************************/
void IIC_Delay(void)
{
        u32 i = 5;
        while( i-- );
}

/*******************************************************************
TWI_START
发送启动数据
*******************************************************************/
u8 IIC_Start(void)
{
        SET_SDA;
        IIC_DELAY;

        SET_SCL;
        IIC_DELAY;

        if( IIC_SDA_STATE == RESET )
        {
                return IIC_BUS_BUSY;
        }

        RESET_SDA;
        IIC_DELAY;

        RESET_SCL;
        IIC_DELAY;

        if( IIC_SDA_STATE == SET )
        {
                return IIC_BUS_ERROR;
        }

        return IIC_BUS_READY;
}

/*******************************************************************
TWI_STOP
发送停止数据
*******************************************************************/
void IIC_Stop(void)
{
        RESET_SDA;
        IIC_DELAY;

        SET_SCL;
        IIC_DELAY;

        SET_SDA;
        IIC_DELAY;
}

/*******************************************************************************
* 函数名称:TWI_SendNACK                                                                     
* 描    述:收到数据,发送NACK                                                                                                                                       
*******************************************************************************/
void IIC_SendNACK(void)
{
        RESET_SDA;
        IIC_DELAY;
        SET_SCL;
        IIC_DELAY;
        RESET_SCL;
        IIC_DELAY;
}

/*******************************************************************************
* 函数名称:TWI_SendACK                                                                     
* 描    述:收到数据,发送ACK                                                                                                                                       
*******************************************************************************/
void IIC_SendACK(void)
{
        SET_SDA;
        IIC_DELAY;
        SET_SCL;
        IIC_DELAY;
        RESET_SCL;
        IIC_DELAY;
}

/*******************************************************************************
* 函数名称:TWI_SendByte                                                                     
* 描    述:发送一个字节                                                                                                                                    
*******************************************************************************/
u8 IIC_SendByte(u8 Data)
{
       u8 i;
       RESET_SCL;
       for(i=0;i<8;i++)
       {
                //---------数据建立----------
                if(Data&0x80)
                {
                        SET_SDA;
                }
                else
                {
                        RESET_SDA;
                }
                Data<<=1;
                IIC_DELAY;
                //---数据建立保持一定延时----
                //----产生一个上升沿[正脉冲]
                SET_SCL;
                IIC_DELAY;
                RESET_SCL;
                IIC_DELAY;//延时,防止SCL还没变成低时改变SDA,从而产生START/STOP信号
                //---------------------------   
       }
       //接收从机的应答
       SET_SDA;
       IIC_DELAY;
       SET_SCL;
       IIC_DELAY;   
       if(IIC_SDA_STATE)
       {
                RESET_SCL;
                return IIC_NACK;
       }
       else
       {
                RESET_SCL;
                return IIC_ACK;
       }   
}

/*******************************************************************************
* 函数名称:TWI_ReceiveByte                                                                     
* 描    述:接收一个字节                                                                                                                                       
*******************************************************************************/
u8 IIC_RecvByte(void)
{
       u8 i,Dat = 0;
       SET_SDA;
       RESET_SCL;
       Dat=0;
       for(i=0;i<8;i++)
       {
                SET_SCL;//产生时钟上升沿[正脉冲],让从机准备好数据
                IIC_DELAY;
                Dat<<=1;
                if(IIC_SDA_STATE) //读引脚状态
                {
                        Dat|=0x01;
                }   
                RESET_SCL;//准备好再次接收数据
                IIC_DELAY;//等待数据准备好         
       }
       return Dat;
}

/******单字节写入*******************************************/
void Single_Write_IIC(u8 SlaveAddress,u8 REG_Address,u8 REG_data)
{
    IIC_Start();                  //起始信号
    IIC_SendByte(SlaveAddress);   //发送设备地址+写信号
    IIC_SendByte(REG_Address);    //内部寄存器地址, //请参考中文pdf22页
    IIC_SendByte(REG_data);       //内部寄存器数据, //请参考中文pdf22页
    IIC_Stop();                   //发送停止信号
}

/********单字节读取*****************************************/
u8 Single_Read_IIC(u8 SlaveAddress, u8 REG_Address)
{
        u8 REG_data;
    IIC_Start();                        //起始信号
    IIC_SendByte(SlaveAddress);         //发送设备地址+写信号
    IIC_SendByte(REG_Address);            //发送存储单元地址,//从0开始       
    IIC_Start();                        //起始信号
    IIC_SendByte(SlaveAddress+1);         //发送设备地址+读信号
    REG_data = IIC_RecvByte();            //读出寄存器数据
        IIC_SendACK();   
        IIC_Stop();                           //停止信号
    return REG_data;
}

/*******************************************************************
引脚端口过滤器 返回值为 引脚端口的时钟编号
*******************************************************************/
uint16_t GPIO_Filter( GPIO_TypeDef * GPIOx )
{       
        uint32_t RCC_GPIOx = 0;

        if( GPIOx == GPIOA )
        {
                RCC_GPIOx = RCC_APB2Periph_GPIOA;
        }
        else if( GPIOx == GPIOA )
        {
                RCC_GPIOx = RCC_APB2Periph_GPIOA;
        }
        else if( GPIOx == GPIOB )
        {
                RCC_GPIOx = RCC_APB2Periph_GPIOB;
        }
        else if( GPIOx == GPIOC )
        {
                RCC_GPIOx = RCC_APB2Periph_GPIOC;
        }
        else if( GPIOx == GPIOD )
        {
                RCC_GPIOx = RCC_APB2Periph_GPIOD;
        }
        else if( GPIOx == GPIOE )
        {
                RCC_GPIOx = RCC_APB2Periph_GPIOE;
        }
        else if( GPIOx == GPIOF )
        {
                RCC_GPIOx = RCC_APB2Periph_GPIOF;
        }
        else if( GPIOx == GPIOG )
        {
                RCC_GPIOx = RCC_APB2Periph_GPIOG;
        }

        return RCC_GPIOx;
}
IIC.H#ifndef _iic_analog_h_
#define _iic_analog_h_

#include "stm32f10x.h"

/*********************************************************************************/
/*修改模拟IIC的读取引脚以及引脚的端口号                                                                                       */
/*这些宏定义定义好了以后引脚初始化函数会自行初始化时钟使能等必要的参数                       */
/*********************************************************************************/
#define IIC_GPIO (GPIOC)
#define IIC_GOIO_SDA (GPIOC)
#define IIC_GPIO_SCL (GPIOC)
#define IIC_SDA (GPIO_Pin_8)
#define IIC_SCL (GPIO_Pin_7)
/*********************************************************************************/




/************************************************************************************/
/*使用此函数 初始化 模拟IIC其中参数 在以上宏定义中 有定义 使用时只需要修改宏定义即可 */
/* 此函数调用时 请复制以下代码
        IIC_GPIO_Configuration( IIC_GOIO_SDA , IIC_SDA , IIC_GPIO_SCL , IIC_SCL );*/
/************************************************************************************/
//IIC 引脚配置
extern void IIC_GPIO_Configuration( GPIO_TypeDef * GPIOx_SDA , uint16_t SDA_Pin , GPIO_TypeDef * GPIOx_SCL , uint16_t SCL_Pin );






/*********************************************************************************/
/*使用以下代码时请勿修改                                                                                                               */
/*                                                                                                                                                               */
/*********************************************************************************/
//使用软件模拟I2C
#define SET_SDA                { GPIO_SetBits( IIC_GPIO , IIC_SDA ); }
#define RESET_SDA        { GPIO_ResetBits( IIC_GPIO , IIC_SDA );}
#define SET_SCL                { GPIO_SetBits( IIC_GPIO , IIC_SCL ); }
#define RESET_SCL         { GPIO_ResetBits( IIC_GPIO , IIC_SCL); }
#define IIC_SDA_STATE (IIC_GPIO->IDR&IIC_SDA)
#define IIC_SCL_STATE (IIC_GPIO->IDR&IIC_SDA)

#define IIC_DELAY { IIC_Delay(); }

enum IIC_REPLAY_ENUM
{
        IIC_NACK = 0,
        IIC_ACK = 1
};

enum IIC_BUS_STATE_ENUM
{
        IIC_BUS_READY = 0,
        IIC_BUS_BUSY=1,
        IIC_BUS_ERROR=2
};

//IIC 延时
extern void IIC_Delay(void);
//IIC 启动函数
extern u8 IIC_Start(void);
//IIC 停止函数
extern void IIC_Stop(void);
//IIC 发送动作
extern void IIC_SendACK(void);
//IIC 停止动作
extern void IIC_SendNACK(void);
//IIC 发送单字节
extern u8 IIC_SendByte(u8 Data);
//IIC 接收单字节
extern u8 IIC_RecvByte(void);
//IIC 写入单字节
extern void Single_Write_IIC(u8 SlaveAddress,u8 REG_Address,u8 REG_data);
//IIC 读取单字节
extern u8 Single_Read_IIC(u8 SlaveAddress, u8 REG_Address);


//GPIO 过滤器
extern uint16_t GPIO_Filter( GPIO_TypeDef * GPIOx );

#endif
6050.c#include "stm32f10x.h"
#include "MPU6050.h"
#include "iic_analog.h"

void delay_IIC( int ms );



void Sys_Configuration(void)
{
        IIC_GPIO_Configuration( IIC_GOIO_SDA , IIC_SDA , IIC_GPIO_SCL , IIC_SCL );
        MPU6050_Inital();
}




void MPU6050_Inital(void)
{
        delay_IIC( 100 );
        //解除休眠
        Single_Write_IIC( SLAVEADRESS , PWR_MGMT_1 , 0x00 );
        Single_Write_IIC( SLAVEADRESS , SMPLRT_DIV , 0x07 );
        Single_Write_IIC( SLAVEADRESS , CONFIG , 0x07 );
        Single_Write_IIC( SLAVEADRESS , GYRO_CONFIG , 0x18 );
        Single_Write_IIC( SLAVEADRESS , ACCEL_CONFIG , 0x01 );
        delay_IIC( 100 );
}


short getAccX(void)
{
        short AccX = 0;
        char AccXH = 0 , AccXL = 0;

        AccXH = Single_Read_IIC( SLAVEADRESS , ACCEL_XOUT_H );
        AccXL = Single_Read_IIC( SLAVEADRESS , ACCEL_XOUT_L );

        AccX = (AccXH<<8)|AccXL;

        return AccX;
}

short getAccY(void)
{
        short AccY = 0;
        char AccYH = 0 , AccYL = 0;

        AccYH = Single_Read_IIC( SLAVEADRESS , ACCEL_YOUT_H );
        AccYL = Single_Read_IIC( SLAVEADRESS , ACCEL_YOUT_L );

        AccY = (AccYH<<8)|AccYL;

        return AccY;
}

short getAccZ(void)
{
        short AccZ = 0;
        char AccZH = 0 , AccZL = 0;

        AccZH = Single_Read_IIC( SLAVEADRESS , ACCEL_ZOUT_H );
        AccZL = Single_Read_IIC( SLAVEADRESS , ACCEL_ZOUT_L );

        AccZ = (AccZH<<8)|AccZL;

        return AccZ;
}

short getGyroX(void)
{
        short GyroX = 0;
        char GyroXH = 0 , GyroXL = 0;
       
        GyroXH = Single_Read_IIC( SLAVEADRESS , GYRO_XOUT_H );
        GyroXL = Single_Read_IIC( SLAVEADRESS , GYRO_XOUT_H );
       
        GyroX = (GyroXH<<8)|GyroXL;
       
        return GyroX;       
}

short getGyroY(void)
{
           short GyroY = 0;
        char GyroYH = 0 , GyroYL = 0;
       
        GyroYH = Single_Read_IIC( SLAVEADRESS , GYRO_YOUT_H );
        GyroYL = Single_Read_IIC( SLAVEADRESS , GYRO_YOUT_H );
       
        GyroY = (GyroYH<<8)|GyroYL;
       
        return GyroY;       
}

short getGyroZ(void)
{
           short GyroZ = 0;
        char GyroZH = 0 , GyroZL = 0;
       
        GyroZH = Single_Read_IIC( SLAVEADRESS , GYRO_ZOUT_H );
        GyroZL = Single_Read_IIC( SLAVEADRESS , GYRO_ZOUT_H );
       
        GyroZ = (GyroZH<<8)|GyroZL;
       
        return GyroZ;       
}

short getTemperature(void)
{
        short temperature = 0;
        char temperatureH = 0 , temperatureL = 0;

        temperatureH = Single_Read_IIC( SLAVEADRESS , TEMP_OUT_H );
        temperatureL = Single_Read_IIC( SLAVEADRESS , TEMP_OUT_L );

        temperature = (temperatureH<<8)|temperatureL;

        return temperature;
}


void delay_IIC( int ms )
{
        int i,j;
        for( i = 0 ; i < ms ; i++ )
        {
                for( j = 0 ; j < 30000 ; j++ );
        }
}
6050.h#ifndef _MPU6050_h_
#define _MPU6050_h_

#define        SMPLRT_DIV                0x19        //陀螺仪采样率,典型值:0x07(125Hz)
#define        CONFIG                        0x1A        //低通滤波频率,典型值:0x06(5Hz)
#define        GYRO_CONFIG                0x1B        //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
#define        ACCEL_CONFIG        0x1C        //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
#define        ACCEL_XOUT_H        0x3B       
#define        ACCEL_XOUT_L        0x3C
#define        ACCEL_YOUT_H        0x3D
#define        ACCEL_YOUT_L        0x3E
#define        ACCEL_ZOUT_H        0x3F
#define        ACCEL_ZOUT_L        0x40
#define        TEMP_OUT_H                0x41
#define        TEMP_OUT_L                0x42
#define        GYRO_XOUT_H                0x43
#define        GYRO_XOUT_L                0x44       
#define        GYRO_YOUT_H                0x45
#define        GYRO_YOUT_L                0x46
#define        GYRO_ZOUT_H                0x47
#define        GYRO_ZOUT_L                0x48
#define        PWR_MGMT_1                0x6B        //电源管理,典型值:0x00(正常启用)
#define        WHO_AM_I                0x75        //IIC地址寄存器(默认数值0x68,只读)
#define        SLAVEADRESS                0xD0        //IIC写入时的地址字节数据,+1为读取

//初始化MPU6050
extern void MPU6050_Inital(void);


//获取加速度计的值
extern short getAccX(void);
extern short getAccY(void);
extern short getAccZ(void);

//获取陀螺仪的值
extern short getGyroX(void);
extern short getGyroY(void);
extern short getGyroZ(void);

//获取温度
extern short getTemperature(void);

//系统初始化
extern void Sys_Configuration(void);
#endif

马学家 发表于 2013-6-17 20:18:30

我好像明白了,GPIO配置成了开漏输出,其他程序都配制成了推挽,手册 上说开漏的话可以读状态。。。

马学家 发表于 2013-6-17 20:18:49

仅此而已,QQ群里网友帮我的

laoqier 发表于 2013-7-22 15:09:02

马学家 发表于 2013-6-17 20:18 static/image/common/back.gif
仅此而已,QQ群里网友帮我的

楼主哪个QQ群 加一下大家一起交流交流

可与愉快谔谔 发表于 2013-7-22 15:52:40

SCL一直是输出的SDA有时需要输出,有时需要输入 具体参考I2C通信协议

ranjiexu 发表于 2013-9-3 09:38:55

GY521和MPU 6050是等同的吗?读取到的数据要怎么处理啊?
{:sad:}

马学家 发表于 2013-9-3 10:11:25

可与愉快谔谔 发表于 2013-7-22 15:52 static/image/common/back.gif
SCL一直是输出的SDA有时需要输出,有时需要输入 具体参考I2C通信协议

是这样的,不过stm32的GPIO有时候不需要来回配置输入和输出,因为他比较高级

xascss 发表于 2013-9-14 20:30:10

请教我也用这个代码 为什么无法获取到数据 能不能分享一下你的完对比一下{:kiss:}

qwerwe 发表于 2013-9-14 22:32:52

楼主的程序看过了,但是烧写不进去啊!

ln08136207 发表于 2013-9-18 11:07:13

马学家 发表于 2013-9-3 10:11 static/image/common/back.gif
是这样的,不过stm32的GPIO有时候不需要来回配置输入和输出,因为他比较高级 ...

不是因为高级,你看一下STM32的pin内部连接图就知道了,在设置成OD输出时,输入通道并没有被断开,因此,在OD模式,同时外部上拉,可以通过读取输入输入数据寄存器来判断外部信号(1或0)。

小小怪 发表于 2013-11-16 10:16:38

xascss 发表于 2013-9-14 20:30 static/image/common/back.gif
请教我也用这个代码 为什么无法获取到数据 能不能分享一下你的完对比一下 ...

我刚刚试过了读不了数据看IIC时序 貌似有问题

smurfjack 发表于 2013-11-17 21:31:40

偶就是卡在这里了
页: [1]
查看完整版本: 帮忙来看个mpu6050程序