硬件I2C驱动MPU6050

发布者:书卷气息最新更新时间:2022-05-26 来源: eefocus关键字:硬件I2C  驱动MPU6050  时序 手机看文章 扫描二维码
随时随地手机看文章

I2C

I2C有两条总线线路,分别是SCL(时钟线)和SDA(数据线)。

I2C的时序非常重要:读数据和写数据的时序有点不一样,在写程序的时候就体现得到。

I2C的SCL高电平时有效,SDA高电平为1,低电平为0。


I2C的驱动:

I2C.h

#ifndef  __I2c__H

#define  __I2c__H


#include "stm32f4xx.h"



#define MPU_ADDRESS         0xd0

#define I2C_SCL_CLK         RCC_AHB1Periph_GPIOB

#define I2C_SDA_CLK         RCC_AHB1Periph_GPIOB

#define MPU_I2C_CLK         RCC_APB1Periph_I2C1

#define I2C_SCL_PORT        GPIOB

#define I2C_SDA_PORT        GPIOB

#define MPU_I2C_PORT        I2C1

#define I2C_SCL_PIN         GPIO_Pin_6

#define I2C_SDA_PIN         GPIO_Pin_7

#define I2C_SCL_SOURCE_PIN  GPIO_PinSource6

#define I2C_SDA_SOURCE_PIN  GPIO_PinSource7

#define SCL_I2C_AF          GPIO_AF_I2C1

#define SDA_I2C_AF          GPIO_AF_I2C1

 


void I2C_GPIO_config(void);

void MPU_I2c_config(void);

void MPU6050_I2C_Init(void);

uint8_t MPU6050_WriteByte(uint8_t addr,uint8_t data);

uint8_t MPU6050_ReadByte(uint8_t addr); 

uint16_t MPU6050_Readbuffer(uint8_t addr,short*buffer,uint8_t num);


#endif


1.初始化I2C的引脚,开启复用功能

I2C需要配置成开漏输出


void I2C_GPIO_config(void)

{

    RCC_AHB1PeriphClockCmd(I2C_SCL_CLK|

                           I2C_SDA_CLK,

                                        ENABLE);

    

    GPIO_PinAFConfig(I2C_SCL_PORT,I2C_SCL_SOURCE_PIN,SCL_I2C_AF);

    GPIO_PinAFConfig(I2C_SDA_PORT,I2C_SDA_SOURCE_PIN,SDA_I2C_AF);

    

    GPIO_InitTypeDef GPIO_InitStruct;

    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF;

    GPIO_InitStruct.GPIO_OType=GPIO_OType_OD;

    GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;

    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_100MHz;

    GPIO_InitStruct.GPIO_Pin=I2C_SCL_PIN;

    GPIO_Init(I2C_SCL_PORT, & GPIO_InitStruct);

    

    GPIO_InitStruct.GPIO_Pin=I2C_SDA_PIN;

    GPIO_Init(I2C_SDA_PORT, & GPIO_InitStruct);

    

}


2.初始化I2C

I2C_OwnAddress1(MCU的设备地址,只要和I2C上挂载的设备地址不一样即可)

记得使能I2C


void MPU_I2c_config(void)

{

    RCC_APB1PeriphClockCmd(MPU_I2C_CLK,ENABLE);

    

    //I2C_DeInit(MPU_I2C_PORT);

    I2C_InitTypeDef I2C_InitStruct;

    I2C_InitStruct.I2C_Mode=I2C_Mode_I2C;

    I2C_InitStruct.I2C_ClockSpeed=100000;

    I2C_InitStruct.I2C_DutyCycle=I2C_DutyCycle_2 ;

    I2C_InitStruct.I2C_OwnAddress1=0x0a;

    I2C_InitStruct.I2C_Ack=I2C_Ack_Enable;

    I2C_InitStruct.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit;

    I2C_Init(MPU_I2C_PORT,&I2C_InitStruct);

    

    I2C_Cmd(MPU_I2C_PORT,ENABLE);

}


3.编写I2C写一个字节的函数

体现I2C读数据的时序

注意应答事件,这里很容易写错,有两个EV6,分别是作为发送端和接收端


uint8_t MPU6050_WriteByte(uint8_t addr,uint8_t data)

{

    while(I2C_GetFlagStatus(MPU_I2C_PORT,I2C_FLAG_BUSY));//检查总线是否在忙

    I2C_GenerateSTART(MPU_I2C_PORT ,ENABLE);//发送起始信号

    while(I2C_CheckEvent(MPU_I2C_PORT,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);//应答

    I2C_Send7bitAddress(MPU_I2C_PORT,MPU_ADDRESS,I2C_Direction_Transmitter);//发送挂在在I2C上设备的地址

    while(I2C_CheckEvent(MPU_I2C_PORT,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)!=SUCCESS);//应答

    I2C_SendData(MPU_I2C_PORT,addr);//发送写入设备的内部地址

    while(I2C_CheckEvent(MPU_I2C_PORT,I2C_EVENT_MASTER_BYTE_TRANSMITTED)!=SUCCESS);//应答

    I2C_SendData(MPU_I2C_PORT,data);//发送写入的数据

    while(I2C_CheckEvent(MPU_I2C_PORT,I2C_EVENT_MASTER_BYTE_TRANSMITTED)!=SUCCESS);//应答

    I2C_GenerateSTOP(MPU_I2C_PORT ,ENABLE);//发送停止信号

    return 0;

}


4.编写I2C读入一个字节的函数

在读数据过程中,需要发送两次的起始信号,第一次发送起始信号是要告诉I2C上挂载的设备要操作它的内部地址,第二次发送起始信号告诉设备现在要读它


uint8_t MPU6050_ReadByte(uint8_t addr)

{

    uint8_t readdata=0;

    I2C_GenerateSTART(MPU_I2C_PORT ,ENABLE);//发送起始信号

    while(I2C_CheckEvent(MPU_I2C_PORT,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);//应答

    I2C_Send7bitAddress(MPU_I2C_PORT,MPU_ADDRESS,I2C_Direction_Transmitter);//发送设备地址

    while(I2C_CheckEvent(MPU_I2C_PORT,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)!=SUCCESS);//应答

    I2C_Cmd(MPU_I2C_PORT,ENABLE);//清除事件EV6

    I2C_SendData(MPU_I2C_PORT,addr);//发送要读取设备的内部地址

    while(I2C_CheckEvent(MPU_I2C_PORT,I2C_EVENT_MASTER_BYTE_TRANSMITTING)!=SUCCESS);//应答

    I2C_GenerateSTART(MPU_I2C_PORT ,ENABLE);发送第二次起始信号

    while(I2C_CheckEvent(MPU_I2C_PORT,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);//应答

    I2C_Send7bitAddress(MPU_I2C_PORT,MPU_ADDRESS,I2C_Direction_Receiver);//发送设备地址

    while(I2C_CheckEvent(MPU_I2C_PORT,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)!=SUCCESS);//应答

    I2C_AcknowledgeConfig(MPU_I2C_PORT ,DISABLE);//失能应答

    readdata=I2C_ReceiveData(MPU_I2C_PORT);//读取数据

    while(I2C_CheckEvent(MPU_I2C_PORT,I2C_EVENT_MASTER_BYTE_RECEIVED)!=SUCCESS);//应答

    I2C_GenerateSTOP(MPU_I2C_PORT ,ENABLE);//发送停止信号

    I2C_AcknowledgeConfig(MPU_I2C_PORT ,ENABLE);//使能应答

    return readdata;返回读取数据

}


5.编写I2C连续读取函数

和读取一个字节函数区别不大


uint16_t MPU6050_Readbuffer(uint8_t addr,short *buffer,uint8_t num)

{

    while(I2C_GetFlagStatus(MPU_I2C_PORT,I2C_FLAG_BUSY));

    I2C_GenerateSTART(MPU_I2C_PORT ,ENABLE);

    while(I2C_CheckEvent(MPU_I2C_PORT, I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);

    I2C_Send7bitAddress(MPU_I2C_PORT, MPU_ADDRESS,I2C_Direction_Transmitter);

    while(I2C_CheckEvent(MPU_I2C_PORT, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)!=SUCCESS);

    I2C_Cmd(MPU_I2C_PORT,ENABLE);

    I2C_SendData(MPU_I2C_PORT,addr);

    while(I2C_CheckEvent(MPU_I2C_PORT, I2C_EVENT_MASTER_BYTE_TRANSMITTED)!=SUCCESS);

    

    I2C_GenerateSTART(MPU_I2C_PORT ,ENABLE);

    while(I2C_CheckEvent(MPU_I2C_PORT, I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);

    I2C_Send7bitAddress(MPU_I2C_PORT, MPU_ADDRESS,I2C_Direction_Receiver);

    while(I2C_CheckEvent(MPU_I2C_PORT, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)!=SUCCESS);

    while(num)

    {

        if(num==1)

        {

            I2C_AcknowledgeConfig(MPU_I2C_PORT, DISABLE);

            I2C_GenerateSTOP(MPU_I2C_PORT, ENABLE);

        }

        while(I2C_CheckEvent(MPU_I2C_PORT, I2C_EVENT_MASTER_BYTE_RECEIVED)!=SUCCESS);


        { 

          *buffer=I2C_ReceiveData(MPU_I2C_PORT);

          buffer++;

          num--;

        }//这个中括号表示连续读取

    }

    I2C_AcknowledgeConfig(MPU_I2C_PORT,ENABLE);

    return 1;

}


MPU6050的驱动

MPU6050.h

#ifndef  __MPU6050__H

#define  __MPU6050__H


#include "stm32f4xx.h"

#include "I2c.h"

#include "USART.h"

#include "stdio.h"

#include "Delay.h"


#define MPU6050_RA_WHO_AM_I       0x75

#define MPU6050_RA_PWR_MGMI       0x6B

#define MPU6050_RA_SAP_RT_DIV     0x19

#define MPU6050_RA_CONFIG         0x1A

#define MPU6050_RA_ACCEL_CONFIG   0x1C

#define MPU6050_RA_GYRO_CONFIG    0x1B

#define MPU6050_RA_FIFO_ENABLE    0X23


#define MPU6050_RA_ACCEL0_MESUME   0X3B


#define MPU6050_RA_GRYO0_MESUME    0X43


uint8_t MPU6050_ReadID(void);

void MPU6050_Init(void);

void MPU6050_Write(uint8_t addr,uint8_t data);

uint8_t MPU6050_Read(uint8_t addr);

void MPU6050_ReadACCEL(uint8_t addr,short *acc_data,uint8_t num);

void MPU6050_ReadGYRO(uint8_t addr,short *gyro_data,uint8_t num);

#endif


1.MPU6050读字节函数 写字节函数

void MPU6050_Write(uint8_t addr,uint8_t data)

{

    MPU6050_WriteByte(addr,data);

}


uint8_t MPU6050_Read(uint8_t addr)

{

    uint8_t readdata=0;

    readdata=MPU6050_ReadByte(addr);

    return readdata;

}   


uint16_t MPU6050_Readdata(uint8_t addr,short *buffer,uint8_t num)

{

    MPU6050_Readbuffer(addr,buffer,num);

    return 0;

}


2.初始化MPU6050

初始化MPU6050思路:

1.MPU6050上电后处于休眠状态,所以要解除休眠状态,“POWER MANAGEMENT 1”寄存器中sleep位置0,就解除休眠状态

2.SAMPLE RATE DIVIDER 频率采样分频器

3.配置外部引脚采样,初始化不需要你用到什么,选择不做任何配置

4.陀螺仪配置(开启自检,选择量程)

5.加速度计(开启自检,选择量程)


void MPU6050_Init(void)

{//MPU6050上电要预热

    delay (500);

    MPU6050_Write(MPU6050_RA_PWR_MGMI,0x00);

    MPU6050_Write(MPU6050_RA_SAP_RT_DIV,0x07);

    MPU6050_Write(MPU6050_RA_CONFIG,0x06);

    MPU6050_Write(MPU6050_RA_ACCEL_CONFIG,0xF8);

    MPU6050_Write(MPU6050_RA_GYRO_CONFIG,0xF8);

}


3.读取MPU6050 ID的函数

根据手册 ID在设备地址的基础上右移一位



uint8_t MPU6050_ReadID(void)

{

    uint8_t ID=0;

    ID=MPU6050_Read(MPU6050_RA_WHO_AM_I);

    ID = ID>>1;

    if(ID!=0x68)

    {

        printf("检测不到MPU6050n");

        printf("error ID=0x%x",ID);

        return 0;

    }

    else

    {

        printf("检测到MPU6050n");

        return 1;

    }

    

}


4.编写读取加速度计和陀螺仪的函数

void MPU6050_ReadACCEL(uint8_t addr,short*acc_data,uint8_t num)

{

    short buf[6];

    MPU6050_Readdata(addr,buf,num);

    acc_data[0]=((buf[0]<<8)|(buf[1]));

    acc_data[1]=((buf[2]<<8)|(buf[3]));

    acc_data[2]=((buf[4]<<8)|(buf[5]));

}


void MPU6050_ReadGYRO(uint8_t addr,short *gyro_data,uint8_t num)

[1] [2]
关键字:硬件I2C  驱动MPU6050  时序 引用地址:硬件I2C驱动MPU6050

上一篇:STM32 高级定时器 输出PWM (用DHT11测得的温度去调节RGB灯的亮度)
下一篇:RCC 使用HSE/HSI配置系统时钟

推荐阅读最新更新时间:2024-11-16 23:45

如何看懂时序图?
操作时序永远使用是任何一片IC芯片的最主要的内容。一个芯片的所有使用细节都会在它的官方器件手册上包含。所以使用一个器件事情,要充分做好的第一件事就是要把它的器件手册上有用的内容提取,掌握。介于中国目前的芯片设计能力有限,所以大部分的器件都是外国几个IC巨头比如TI、AT、MAXIM这些公司生产的,器件资料自然也是英文的多,所以,英文的基础要在阅读这些数据手册时得到提高哦。即便有中文翻译版本,还是建议看英文原版,看不懂时不妨再参考中文版,这样比较利于提高。 我们首先来看1602的引脚定义,1602的引脚是很整齐的SIP单列直插封装,所以器件手册只给出了引脚的功能数据表: 我们只需要关注以下几个管脚: 3脚:VL,液晶显示偏
[单片机]
如何看懂<font color='red'>时序</font>图?
多轴机器人和机床应用中的时序挑战
简介 在工业机器人和机床应用中,可能涉及在特定空间内精准协调多个轴的移动,以完成手头的工作。机器人一般有 6 个轴,这些轴必须协调有序,如果有时候机器人沿轨道移动,则会有 7 个轴。在 CNC 加工中,5 轴协调很常见,但是有些应用会用到多达 12 个轴,其中工具和工件在特定空间内相对移动。每个轴都包含一个伺服驱动器、一个电机,有时候,在电机和轴接头,或者末端执行器之间会加装一个变速箱。然后,系统通过工业以太网互联,一般采用 LINE 型拓扑,具体如图 1 所示。电机控制器将所需的空间轨迹转换为每个伺服轴所需的单个位置基准,然后在网络上循环传输。 图 1. 多轴机床的网络拓扑结构。 控制周期 这些应用按定义的周期时间运行,
[嵌入式]
多轴机器人和机床应用中的<font color='red'>时序</font>挑战
STM32的硬件I2C与AT24C16
CubeMX的配置 下面这些是我修改过的地方,只要注意I2C和系统时钟等基础配置即可,不想说太多,以图为言 AT24C64的自制库 AT24C64.c #include AT24C64.h #include i2c.h void AT24CXX_Write(u16 reg_address,u8 data) { static HAL_StatusTypeDef i; i = HAL_I2C_Mem_Write(&hi2c1,AT24CXX_DEV_ADDRESS,reg_address,I2C_MEMADD_SIZE_16BIT,&data,1,100); AT24CXX_DELAY_MS(5);
[单片机]
16位高速A/D转换器在高速DSP处理器中的应用
  由于DSP有先进的并行结构使其特别适合于信号处理,故已经越来越多的应用于工业控制领域和各类仪器仪表的开发设计。而在用数字信号微处理器构成的智能仪器仪表中,外部的各种模拟信号必须通过A/D转换器变换为数字信号后才能送入微处理器芯片。而BB公司的高精度转换器ADS7805具有较高的性能价格比,最高的转换频率可达100KHz,在仪器仪表中得到广泛的应用。ADS7805芯片有28脚双排直插式或贴片式封装,只需单端5V电源供电即可正常工作;芯片内部含有采样保持、电压基准和时钟等电路,极大简化用户的电路设计,同时提高了系统的稳定性。ADS7805采用CMOS工艺制造,功耗低(最大功耗为100mW),单通道输入,模拟输入电压的范围为±10V
[嵌入式]
单片机的时序分析
前面我们介绍了延时程序,但这还不完善,因为,我们只知道DJNZ R6,D2这句话会被执行62500次,但是执行这么多次需要多长时间呢?是否满足我们的要求呢?我们还不知道,所以下面要来解决这个问题。 先提一个问题:我们学校里什么是最重要的。(铃声)校长可以出差,老师可以休息,但学校一日无铃声必定大乱。整个学校就是在铃声的统一指挥下,步调一致,统一协调地工作着。这个铃是按一定的时间安排来响的,我们可以称之为“时序��时间的顺序”。一个由人组成的单位尚且要有一定的时序,计算机当然更要有严格的时序。事实上,计算机更象一个大钟,什么时候分针动,什么时候秒针动,什么时候时针动,都有严格的规定,一点也不能乱。计算机要完成的事更复杂
[单片机]
多路时序脉冲发生器
多路时序脉冲发生器
[模拟电子]
多路<font color='red'>时序</font>脉冲发生器
基于DSP的车辆视频处理系统的研究与实现
   引言   目前,交通监控应用系统大多以紧急报警、车辆定位与语音通信为主,图像方面的应用不多。本文正是基于这样的考虑,设计了车辆图像采集与处理系统。该系统采集车后方的图像信息,实时地传送给前方的显示屏显示,司机可通过显示屏实时观测后方路面及车辆状况,倒车时可以及时发现后方障碍物及行人,安全避让。 图1 实时图像采集处理系统组成框图 (a) 采集一行图像(720个采样点)的时序图 (b) 采集一帧图像的时序图 图2 数字视频信号输出时序图 图3 采用CPLD完成视频采集控制 实时图像采集处理系统的组成及工作原理   本系统由模拟摄像头采集视频数据,通过视频解码芯片将模拟视频信号转换为数字视频信号。CPLD
[嵌入式]
Cirrus Logic时钟IC系列产品可提供最佳抖动性能
2007年10月18日,Cirrus Logic公司(纳斯达克代码:CRUS)CS2XXX系列产品的推出是Cirrus Logic公司充分利用其在高精度混合信号音频IC解决方案方面的经验和创新能力,以强大势头进入时钟IC市场的标志。这些新的IC产品包括CS2000、CS2100、CS2200和CS2300,主要专注于如音频/视频接收机、混音控制台、多声道录音机、数字录音机和机顶盒等音频应用,可为制造商确保音频系统设计内清洁时钟这一复杂任务的管理提供卓越的解决方案。 精确的时钟解决方案对电子类应用来说尤为重要,因其主要用于同步专业及消费音频设备的元件,这可直接影响音质。它们通常是为系统内部的其他元件提供时序脉冲的电子电路里的无源或
[新品]

推荐帖子

ADS1298的常见问题
本帖最后由dontium于2015-1-2311:21编辑ADS1298的常见问题1、问:我想使用不带MMB0的ADS1298ECGFEEVM,这是否可能?答:是的,完全没问题!不过应首先考虑到以下几个方面:-电路板电源ADS1298ECGFE板的电源来自10引脚双排插座J4。通过MMB0连接头J5,可将+5V、+3.3V以及+1.8V交付给ADS1298板。+5V供电电压通过稳压器,可为ADS1298芯片提供模拟电压
模拟IC 模拟与混合信号
高分辨率ADC的板布线
本文描述的是系统设计方面的一些关键性问题,特别关注印制电路板(PCB)地和电源平面布线技术。现代化的ADC需要现代化的板设计。没有精确的时钟源或仔细设计的板布线,则高性能变换器将达不到其性能指标。  单IF外差接收机结构和高级的功率nobrid=nobr74style=CURSOR:pointer;COLOR:#cb4bfc;BORDER-BOTTOM:rgb(102,0,255)1pxdotted;BACKGROUND-COLOR:transparent;TEX
kandy2059 RF/无线
运算放大器、比较器设计指南 第十四版
本帖最后由paulhyde于2014-9-1504:25编辑介绍的比较详细!!!!!!!!运算放大器、比较器设计指南第十四版本帖最后由paulhyde于2014-9-1504:25编辑本帖最后由paulhyde于2014-9-1504:25编辑真是好人认真负责真是好人认真负责本帖最后由paulhyde于2014-9-1504:25编辑很好,复习复习模电,哈哈回复楼主kmopty
kmopty 电子竞赛
基于ARM 和Qt/E的车载HMI终端设计
车载HMI是人与车辆之间的关键设备,使人能够对车辆的运行实现控制;设计了一种触摸控制与数字显示合理结合的车载HMI终端,采用ARM作为处理器,通过移植Qt/E对系统加以实现;该终端通过在Polo车CAN总线试验台测试,实现了对基本设备的触摸控制和车辆状态信息的实时显示,表明所设计的终端能够满足车载HMI的基本要求。  0引言  改善HMI(HumanMachineInterface)终端性能可降低车辆控制系统操作的复杂性,也可提高驾驶员对自己车辆的控制力。车载HMI通过
fish001 微控制器 MCU
功率放大器知识
功率放大电路的原理及其知识........功率放大器知识这个资料4个芯币,楼主不厚道啊....呵呵,楼主的价格有点贵,,,不要发大财哦哈哈虽仍是菜鸟,但毕竟已非今日才入门,不想拾人牙慧,故现在我会先跟帖再下档案,实际上,我不太喜欢下人家的东西(虽然有币),而我发布的,都是图(不需登录也可见)。楼主太不厚道了,要5个币,下载完了才发现上当了,不就华成英的讲义么,人家全套模拟电路的下载也没有要币的。
Jackiedzc 模拟电子
【2024 DigiKey创意大赛】+基于大语言模型的智能家居平台+最终提交贴
基于大语言模型的智能家居平台作者:SeasonMay一、作品简介本作品以乐鑫的ESP32-S3-LCD-EV-BOARD为家居平台的核心主控,搭配以DFROBOT的TCS3200颜色传感器(SEN0101)以及Adafruit的15x7矩阵灯板作为家居平台的主要演示场景平台,并以Adafruit的FeatherTFTESP32-S3作为协控中心,处理器件与上位机等的通信服务等任务。全家福如下:1.ESP32-S3-LCD-EV-Board是一款基于
SeasonMay DigiKey得捷技术专区
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved