由于用mpu6050模块,所以要用上i2c通信原理。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了由于用mpu6050模块,所以要用上i2c通信原理。相关的知识,希望对你有一定的参考价值。

                   i2c通信原理
i2c总线只有两根双向信号线,一根是数据线SDA,一根是时钟线SCL。
每个接到i2c总线上的器件都有唯一的地址,主机与其他器件之间的数据传送可以是由主机发送给其他器件。主机为发送器,从机为接收器。在80c51单片机系统中,通常80C51单片机为主机,

                                     
    1:数据位的有效规定:

1.1:总线在进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,时钟线为低电平期间时,数据线上的高电平和低电平才能允许变化。

1.2:起始信号和终止信号都是由主机发出的,起始信号产生后,总线就处于占用状态;终止信号产生后,总线就处于空闲状态

1.3:连接到i2c总线上的上的器件,若具有i2c总线的硬件接口,则很容易检测到起始和终止信号。接收器件在接收到一个完整的数据字节后,有可能需要完成一些其他的工作,如处理内部中断函数等,不能立即接收下一个字节数据,这时,接收器件可以将SCL时钟线拉成低电平,从而使主机处于等待状态,等到接收器准备好接收下一个字节后,再释放SCL时钟线,使之为高电平,从而数据传送继续进行。

    2:数据传送格式:

2.1:字节传送与应答
每一个字节必须保证是8位长度,数据传送时,先传送最高位,每一个被传送字节后面都必须跟随一个应答位(即一个数据帧有9位),由于某种原因从机不对主机寻址信号应答时(如从机正在进行实时性的处理工作而无法接收总线上的数据,它必须将数据线SDA置于高电平,主机产生一个终止信号以结束总线的数据传送。如果从机对主机进行了应答,但在接收数据一段时间后无法接收更多的数据,从机可通过对无法接收的第一个数据字节的“非应答”通知主机,主机则应发出终止信号以结束数据的继续传送。当主机接收数据时,它收到最后一个数据字节后,必须向从机发出一个结束传送的信号,这个信号是对从机的非应答来实现的,然后从机释放数据线SDA,以允许主机产生终止信号。 

2.2:数据帧格式
i2c总线上的数据信号是广义的。既包括地址信号,又包括真正的数据信号。在起始信号产生后,必须传送一个从机的地址(7位),第8位是数据传送的方向位(R/T),用“0”表示主机发送数据(T),“1”表示主机接收数据(R),每次数据传送总是由主机产生的终止信号结束。但是,若主机希望继续占用总线进行新的数据传送,则可以不产生终止信号,马上再次发出起始信号对另一从机进行寻址。

2.3:数据传送过程中几种组合方式
   
A表示应答,A非表示非应答(高电平),S表示起始信号,P表示终止信号

   a:主机向从机发送数据,数据传送方向在整个传送过程中不变

主机S -> 从机地址 -> 0 -> 从机A -> 主机发数据 -> 从机A -> 主机发数据 -> 从机A非 -> 主机P
 
  b:主机在第一个字节后,立即从从机读数据

主机S -> 从机地址 -> 1 -> 从机A -> 从机发数据 ->主机A -> 从机发数据 ->主机A非 ->  主机P

 c:在传送过程中,当需要改变传送方向时,起始信号和从机地址都被重复产生一次,但两次读/写方向位正好相反

主机S -> 从机地址 -> 0 -> 从机A -> 主机发数据 ->从机A或A非 -> 主机S->从机地址 -> 1 -> 从机A ->从机发数据 -> 主机A非-> 主机 P


     3:总线的寻址

3.1:主机发送地址时,总线上的每个从机都将这7位地址码与自己的地址进行比较,如果相同则认为自己正被主机寻址,根据R/T位将自己确定为发送器或接收器。从机的地址由固定部分和可编程部分组成,在一个系统种可能希望接入多个相同的主机,从机地址中可编程部分决定了可接入总线该类器件的最大数目

3.2:典型信号模拟:
    (1)数据线状态函数:

      u8    funcGetI2CStatus(void)
   {
    return I2C_sda;
   }

    (2)起始信号模拟函数:

     u8 I_start(void )//起始信号模拟
    { 
    SDAHigh(HIGH);         /* SDA 为 高电平*/
    I2C_delay();          /* SDA 稳定     */
    SCLHigh(HIGH);         /* SCL 为高电平*/
    I2C_delay();
    if(!funcGetI2CStatus())
    {
        return I2C_BUS_BUSY;
    }
     SDAHigh(LOW);          /* SDA 产生下降沿*/
    I2C_delay();
    SCLHigh(LOW);
    I2C_delay();
      if(funcGetI2CStatus())
     {
        return    I2C_BUS_ERROR;
    }
    else 
        return I2C_BUS_READY;
     }
 
    (3)终止信号模拟函数
  

     void I_stop(void)//终止信号模拟
     { 
    SDAHigh(LOW);
    I2C_delay();
    SCLHigh(HIGH);     /*SCL1 为高电平期间,SDA1产生一个上升沿*/
    I2C_delay();
    SDAHigh(HIGH);
    }

    (4)应答信号模拟函数
  
     void I_ACK(void) //应答信号模拟
    { 
    SDAHigh(LOW);
    I2C_delay();
    SCLHigh(HIGH);
    I2C_delay();
    SDAHigh(HIGH);
    I2C_delay();
    }
 
     4.串行E2PROM的扩展:
4.1:写入过程:
 单片机进行写操作时,首先发送该器件的7位地址码和和写方向位“0”,发送完后释放SDA线并在SCL线上产生第9个时钟信号。被选中的存储器件在确认是自己的地址后,在SDA线上产生一个应答信号作为相应,单片机收到应答后就可以传送数据了.传送数据时,单片机首先发送一个字节的被写入器件的存储区的首地址,收到存储器件的应答后,单片机就逐个发送各数据字节,但每发送一个字节后都要等待应答。
 AT24C系列器件片内地址在接收到每一个数据字节地址后自动加1,在芯片的“一次装载字节数”(不同芯片字节数不同)限度内,只需输入首地址。装载字节数超过芯片的“一次装载数”时,数据地址将“上卷”,前面的数据将被覆盖。
 当要写入的数据传送完后,单片机应发出终止信号以结束写入操作。写入n个字节的数据格式:
S ->主机发送器件地址+0->从机A->主机写入首地址-> 从机A -> 主机发送数据1-> 从机A ->...->主机发送数据n ->从机A ->主机发送P.

4.2:读出过程
 单片机先发送该器件的7位地址码和写方向位“0”,发送完后释放SDA数据线并在SCL线上产生第9个时钟信号。被选中的存储器器件在确认是自己的地址后,在SDA线上产生一个应答信号作为回应。然后再发一个字节的要读出器件的存储区的首地址,收到应答后,单片机要重复一次起始信号并发出器件地址和读方向位(“1),收到器件应答后就可以读出数据字节,每读出一个字节,单片机都要回复应答信号。当最后一个字节数据读完后,单片机应返回以"非应答"(高电平),并发出终止信号以结束读操作。
S ->主机发送器件地址+0 ->从机A ->主机读出首地址 ->从机A -> 主机发送器件地址+1 -> 从机A ->从机发送数据 -> 主机A ->... ->从机发送数据n ->主机非应答 ->主机p.

4.3:移位操作
左移时最低位补0,最高位移入PSW的CY位。
右移时最高位保持原数,最低位移除。
   
  
    

以上是关于由于用mpu6050模块,所以要用上i2c通信原理。的主要内容,如果未能解决你的问题,请参考以下文章

ARM开发板linux下用I2C读取mpu6050的数据

Aduino ESP9266通过I2C接口读取MPU6050模块数据+OLED显示

MicroPython ESP32ssd1306驱动0.96“I2C屏幕+mpu6050图形控制

MPU6050 I2C master模式调试记录

MPU6050带字符驱动的i2c从设备驱动1

RT-Thread&ART-PI使用软件I2C读取mpu6050