STM32--I2C通信

时间:2024-10-25 17:04:49

对于I2C通信会分为两大块来讲解,第一块,就是介绍协议规则,然后用软件模拟的形式来实现协议,第二块,就是介绍STM32的12C外设,然后用硬件来实现协议,因为12C是同步时序,软件模拟协议也非常方便。

在学12C之前,我们已经学习了串口通信,串口通信,就是从TX引脚向RX引脚发送数据流,数据流以字节为单位,数据流以字节为单位,我们可以组合多个字节,另外串口通信的设计是,一条发送线、一条接收线,没有时钟线的异步全双工的协议。

如果现在需要设计一种在单片机和外部模块连接少量的几根线,实现单片机读写外部模块寄存器的功能的通信协议(基本要求)。其中

  1. 要求1:删掉一根通信线,只能在同一根线上进行发送和接收,也就是把全双工变成半双工。

  2. 要求2:所以为了安全起见,要求增加应答机制,要求每发送一个字节,对方都要给我个应答,每接收一个字节,我也要给对方一个应答。

  3. 第3个要求:一根线上能同时接多个模块,单片机可以指定,和任意一个模块通信,同时单片机在跟某个模块进行通信时,其他模块不能对正常的通信产生干扰。

  4. 第4个要求:串口是异步的时序,也就是发送方和接收方约定的传输速率是非常严格的,时钟不能有过大的偏差,也不能说在传输过程中,单片机有点事,进中断了,对于异步时序来说,这是不能中断的,单片机一个字节发一半暂停了,接收方可是不知道的,它仍然会按照原来那个约定的速率读取,这就会导致传输出错,所以异步时序的缺点就是,非常依赖硬件外设的支持,必须要有USART电路才能方便地使用,如果没有USART硬件电路的支持,那么串口是很难用软件来模拟的。所以要求要把这个协议改成同步的协议,另外加一条时钟线来指导对方读写,由于存在时钟线,对传输的时间要求就不高了,单片机也可以随时暂停传输,去处理其他事情,因为暂停传输的同时,时钟线也暂停了,所以传输双方都能定格在暂停的时刻,可以过一段时间再来继续,不会对传输造成影响,这就是同步时序的好处,使用同步时序就可以极大地降低单片机对硬件电路的依赖,即使没有硬件电路的支持,也可以很方便地用软件手动翻转电平来实现通信。异步时序的好处就是省一根时钟线,节省资源,缺点就是对时间要求严格,对硬件电路的依赖比较严重,同步时序的好处就是对时间要求不严格,对硬件电路不怎么依赖,在一些低端单片机,没有硬件资源的情况下,也很容易使用软件来模拟时序,缺点就是多一根时钟线。

一、I2C通信简介

  1. 基本定义与开发者1:

    • I2C(Inter-Integrated Circuit)总线是由 Philips 公司开发的一种简单、双向二线制同步串行总线,用于在集成电路之间进行短距离数据传输。也有人将其原缩写 IIC 写成 I²C,后因输入不便简化为 I2C,但意思相同。

  2. 硬件组成与连接方式

    • 总线线路:I2C 总线只需要两根线,即串行数据线(SDA)和串行时钟线(SCL)2。

      • SDA 线是双向的数据传输线,用于主机与从机之间收发数据通信,一根线兼具发送和接收,最大化利用资源。同一时间只能进行数据发送或者接收,不能同时进行。(满足要求1)

      • SCL 线由主机控制,是用于主机与从机间的时钟同步信号线。(满足要求4)

    • 上拉电阻:SDA 和 SCL 信号引脚是开漏输出,只能输出低电平不能输出高电平,所以需要通过上拉电阻接电源 VCC,以保证总线空闲时为高电平。上拉电阻阻值一般为 4.7KΩ 左右,常用的还有 1K、1.5K、2.2K、5.1K、10K 等3。

    • 设备连接:所有设备的 SDA 线并接在一起,所有设备的 SCL 线也并接在一起。总线上的每个设备都有一个特定的设备地址,以区分同一 I2C 总线上的其他设备。

  3. 通信模式1:

    • 主从模式:I2C 总线采用一主多从的通讯模式。主器件用于启动总线传送数据,并产生时钟以开放传送,被寻址的器件均被认为是从器件。在总线上主和从、发和收的关系不是恒定的,取决于此时数据传送方向。单片机作为主机,主导I2C总线的运行,挂载在12C总线的所有外部模块都是从机,从机只有被主机点名之后才能控制I2C总线,不能在未经允许的情况下去碰12C总线,防止冲突。

    • 多主模式多主多从,I2C 总线是一个真正的多主机总线,如果两个或多个主机同时初始化数据传输,可以通过冲突检测和仲裁防止数据破坏。在总线上任何一个模块都可以主动跳出来说,接下来我就是主机,你们都得听我的,但是,同一个时间只能有一个人说话,这时就相当于发生了总线冲突,在总线冲突时,12C协议会进行仲裁,仲裁胜利的一方取得总线控制权,失败的一方自动变回从机,当然由于时钟线也是由主机控制的,所以在多主机的模型下,还要进行时钟同步,多主机的情况下,协议是比较复杂的。(满足要求3)

  4. 数据传输过程

    • 起始条件与终止条件23:

      • 起始条件是在 SCL 高电平期间,SDA 从高电平切换到低电平;终止条件是在 SCL 高电平期间,SDA 从低电平切换到高电平。起始和终止都是由主机产生,在总线空闲状态时,从机不允许主动去操作总线。

    • 数据传输格式1:发送到 SDA 线上的每个字节必须为 8 位,每次传输可以发送的字节数量不受限制。每个字节后必须跟一个响应位。首先传输的是数据的最高位(MSB)。

    • 应答机制1:数据传输必须带响应,相关的响应时钟脉冲由主机产生。在响应的时钟脉冲期间发送器释放 SDA 线(高),接收器必须将 SDA 线拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平。(满足要求2)

    • 时钟同步:所有主机在 SCL 线上产生它们自己的时钟来传输 I2C 总线上的报文。数据只在时钟的高电平周期有效,时钟同步通过线与连接 I2C 接口到 SCL 线来执行1。

  5. 传输速率1:

    • 标准模式下可达 100kbit/s;快速模式下可达 400kbit/s;高速模式下可达 3.4Mbit/s。

  6. 应用场景:I2C 总线已经被广泛地应用于连接各种传感器、液晶屏幕、存储器等电子设备当中。如MPU6050模块,OLED模块,AT24C02存储器模块,DS3231实时时钟模块等等。

了解了I2C之后,为了了解I2C是怎么样实现这么多功能的,而且作为通信协议,它必须要在硬件(电路应该如何连接、端口的输入输出模式都是啥样的)和软件(时序是怎么定义的、字节如何传输,高位先行还是低位先行、一个完整的时序由哪些部分构成)上都作出规定,硬件的规定和软件的规定配合起来,就是一个完整的通信协议

二、I2C的硬件规定

  1. 连接方式

    • 所有 I2C 设备的 SCL(串行时钟线)应连接在一起,SDA(串行数据线)也应连接在一起。

    • 这意味着所有 I2C 设备在硬件层面上共享 SCL 和 SDA 线,形成一个总线结构。

  2. 输出模式

    • 设备的 SCL 和 SDA 均应配置成开漏输出模式。

    • 开漏输出模式意味着这些引脚在输出低电平时可以直接拉低,但在输出高电平时需要外部上拉电阻来拉高。

    • 因为现在是一主多从,主机拥有SCL的绝对控制权,所以主机的SCL可以配置成推挽输出,所有从机的SCL都配置成浮空输入或者上拉输入,数据流向是,主机发送,所有从机接收。但是SDA线,因为这是半双工的协议,所以主机的SDA在发送的时候是输出,在接收的时候是输入,同样,从机的SDA也会在输入和输出之间反复切换,如果能协调好输入输出的切换时机,那其实也没问题,但是这样做,如果总线时序没协调好,极有可能发生两个引脚同时处于输出的状态,如果这时又正好是一个输出高电平,个输出低电平,那这个状态就是电源短路,这个状态需要避免。所以为了避免总线没协调好导致电源短路这个问题,12C的设计是,禁止所有设备输出强上拉的高电平,采用外置弱上拉电阻加开漏输出的电路结构,

  3. 在接收的时候是输入上拉电阻

    • SCL 和 SDA 各需添加一个上拉电阻,阻值一般为 4.7KΩ 左右。

    • 上拉电阻的作用是在没有设备拉低 SCL 或 SDA 线时,将其拉高到高电平状态。这是通过一个电阻拉到高电平的,所以这是一个弱上拉。

    • 用之前将的弹簧和杆子的模型来解释就是,SCL或SDA就是一根杆子,为了防止有人向上推杆子,有人向下拉杆子,造成冲突,就规定,所有的人,不准向上推杆子,只能选择往下拉或者放手,然后,再外置一根弹簧向上拉,要输出低电平,就往下拽,弹簧被拉伸,杆子处于低电平状态;要输出高电平,就放手,杆子在弹簧的拉力下,回弹到高电平,这就是一个弱上拉的高电平,但是完全不影响数据传输。

    • 这样做的好处:第一,完全杜绝了电源短路现象,保证电路的安全。第二,避免了引脚模式的频繁切换,开漏加弱上拉的模式,同时兼具了输入和输出的功能,要是想输出,就去拉杆子或放手,操作杆子变化就行了;要是想输入,就直接放手,然后观察杆子高低就行了,因为开漏模式下,输出高电平就相当于断开引脚,所以在输入之前,可以直接输出高电平,不需要再切换成输入模式了。第三,就是这个模式会有"线与"的现象,就是只要有任意一个或多个设备输出了低电平,总线就处于低电平,只有所有设备都输出高电平,总线才处于高电平。

    • 12C可以利用这个电路特性,执行多主机模式下的时钟同步和总线仲裁,所以这里SCL虽然在一主多从模式下可以用推挽输出,但是它仍然采用了开漏加上拉输出的模式,因为在多主机模式下会利用到这个特征。

图示内容

  1. 左侧电路模型

    • 图中左侧展示了一个典型的 I2C 总线连接模型,一主多从的模式。

    • 从 CPU(*处理器)作为总线的主机引出 SCL 和 SDA 线,连接到 I2C 总线上。主机的权利很大,包括,对SCL线的完全控制,任何时候,都是主机完全掌控SCL线,另外在空闲状态下,主机可以主动发起对SDA的控制,只有在从机发送数据和从机应答的时候,主机才会转交SDA的控制权给从机。

    • 在 SCL 和 SDA 线上各有一个上拉电阻(R),连接到电源(Vdd)。

    • 总线上连接了多个被控 IC(集成电路),挂载在I2C总线上的从机,这些从机可以是姿态传感器、OLED、存储器、时钟模块等等,从机的权利比较小,对于SCL时钟线,在任何时刻都只能被动的读取,从机不允许控制SCL线,对于SDA数据线,从机不允许主动发起对SDA的控制,只有在主机发送读取从机的命令后,或者从机应答的时候,从机才能短暂地取得SDA的控制权,每个 IC 都有自己的 SCL 和 SDA 引脚。

  2. 右侧电路模型

    • 图中右侧展示了所有的设备,包括CPU和被控IC,它引脚的内部结构。

    • 有 SCL 和 SDA 两条线,分别连接到 SCL IN 和 DATA IN(输入)以及 SCL OUT 和 DATA OUT(输出)。

    • 这表示数据和时钟信号的输入和输出方向。

    • 首先引脚的信号进来,都可以通过一个数据缓冲器或者是施密特触发器,进行输入,因为输入对电路没有任何影响,所以任何设备在任何时刻都是可以输入的,但是在输出的这部分,采用的是开漏输出的配置,这里输出低电平,这个开关管导通,引脚直接接地,是强下拉,输出高电平,这个开关管断开,引脚什么都不接,处于浮空状态,这样的话,所有的设备都只能输出低电平而不能输出高电平,为了避免高电平造成的引脚浮空,这时就需要在总线外面,SCL和SDA各外置一个上拉电阻。

三、I2C的软件规定

基本时序单元

  1. 起始条件

    • 当 SCL(时钟线)处于高电平期间,SDA(数据线)从高电平切换到低电平,表示 I2C 通信的开始。

    • 图中用波形图展示了这一过程,SCL 保持高电平,SDA 从高电平下降到低电平。

    • 在12C总线处于空闲状态时,SCL和SDA都处于高电平状态,也就是没有任何一个设备去碰SCL和SDA,SCL和SDA由外挂的上拉电阻拉高至高电平,总线处于平静的高电平状态,当主机需要进行数据收发时,首先就要打破总线的宁静,产生一个起始条件,这个起始条件就是:SCL处于高电平不去动它,然后把SDA拽下来,产生一个下降沿,当从机捕获到这个SCL高电平,SDA下降沿信号时,就会进行自身的复位,等待主机的召唤,然后在SDA下降沿之后,主机要再把SCL拽下来;拽下SCL,一方面是占用这个总线,另一方面也是为了方便我们这些基本单元的拼接,就是之后会保证,除了起始和终止条件,每个时序单元的SCL都是以低电平开始,低电平结束。这样这些单元拼接起来,SCL才能续得上。

  2. 终止条件

    • 当 SCL(时钟线)处于高电平期间,SDA(数据线)从低电平切换到高电平,表示 I2C 通信的结束。

    • 图中用波形图展示了这一过程,SCL 保持高电平,SDA 从低电平上升到高电平。

    • SCL先放手,回弹到高电平,SDA再放手,回弹高电平,产生一个上升沿,这个上升沿触发终止条件,同时终止条件之后,SCL和SDA都是高电平,回归到最初的平静状态。

  3. 总结

    • 这个起始条件和终止条件就类似串口时序里的起始位和停止位,一个完整的数据帧,总是以起始条件开始、终止条件结束,另外,起始和终止,都是由主机产生的,从机不允许产生起始和终止,所以在总线空闲状态时,从机必须始终双手放开,不允许主动跳出来,去碰总线,如果允许的话,那就是多主机模型了。

  4. 发送一个字节

    • 在 SCL(时钟线)低电平期间,主机将数据位依次放到 SDA(数据线)上,从高位(B7)开始,依次到低位(B0)。主机在 SCL 低电平期间改变 SDA 的数据位。然后释放 SCL,从机将在 SCL 高电平期间读取数据位。在 SCL 高电平期间,SDA 不允许有数据变化。所以高电平期间,SDA不允许变化这个过程循环 8 次,即可发送一个字节。

    • 起始条件之后,第一个字节,也必须是主机发送的。主机如何发送呢?就是最开始,SCL低电平,主机如果想发送0,就拉低SDA到低电平,如果想发送1,就放手,SDA回弹到高电平,在SCL低电平期间,允许改变SDA的电平,当这一位放好之后,主机就松手时钟线,SCL回弹到高电平,在高电平期间,是从机读取SDA的时候,所以高电平期间,SDA不允许变化,SCL处于高电平之后,从机需要尽快地读取SDA,一般都是在上升没这个时刻,从机就已经读取完成了,因为时钟是主机控制的,从机并不知道什么时候就会产生下降沿了,从机要是磨磨唧唧的,主机可不会等的,所以从机在上升沿时,就会立刻把数据读走,那主机在放手SCL一段时间后,就可以继续拉低SCL,传输下一位了,主机也需要在SCL下降沿之后尽快把数据放在SDA上,但是主机有时钟的主导权,所以主机并不需要那么着急,只需要在低电平的任意时刻把数据放在SDA上就行了,数据放完之后,主机再松手SCL,SCL高电平,从机读取这一位。

    • 总结:主机拉低SCL,把数据放在SDA上,主机松开SCL,从机读取SDA的数据,在SCL的同步下,依次进行主机发送和从机接收,循环8次,就发送了8位数据,也就是一个字节,另外注意,这里是高位先行,所以第一位是一个字节的最高位B7,与串口不同。另外,由于这里有时钟线进行同步所以如果主机一个字节发送一半,突然进中断了,不操作SCL和SDA了,那时序就会在中断的位置不断拉长,SCL和SDA电平都暂停变化,传输也完全暂停,等中断结束后,主机回来继续操作,传输仍然不会出问题,这就是同步时序的好处,最后就是,由于这整个时序是主机发送一个字节,所以在这个单元里,SCL和SDA全程都由主机掌控,从机只能被动读取,这就是发送一个字节的时序。

  5. 接受一个字节

    • SCL低电平期间,从机将数据位依次放到SDA线上(高位先行),然后释放SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA,让从机取得SDA的控制权)

    • 为什么主机在接收之前,需要释放SDA?释放SDA其实就相当于切换成输入模式。所有设备包括主机都始终处于输入模式,当主机需要发送的时候,就可以主动去拉低SDA,而主机在被动接收的时候,就必须先释放SDA,不要去动它,以免影响别人发送。因为总线是线与的特征,任何一个设备拉低了,总线就是低电平,如果你接收的时候,还拽着SDA不放手,那别人无论发什么数据,总线都始终是低电平,主机拽着不放,别人就无法发送。

    • 从流程上来看,接收一个字节和发送一个字节是非常相似的,区别就是发送一个字节是,低电平主机放数据,高电平从机读数据;而接受一个字节是,低电平从机放数据,高电平主机读数据。这里的时序图也与上面的时序图十分相似,主机在接收之前要释放SDA,然后这时从机就取得了SDA的控制权,从机需要发送0,就把SDA拉低,从机需要发送1,就放手,SDA回弹高电平,然后同样的,低电平变换数据,高电平读取数据,这里实线部分表示主机控制的电平,虚线部分表示从机控制的电平,SCL全程由主机控制,SDA主机在接收前要释放,交由从机控制,之后还是一样,因为SCL时钟是由主机控制的。所以从机的数据变换基本上都是贴着SCL下降沿进行的,而主机可以在SCL高电平的任意时刻读取。

  6. 发送应答

    • 主机在接收完一个字节之后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答。

    • 时序与发送一个字节的其中一位相同,可以理解成发送一位,这一位就用来作为应答。

    • 当在接收一个字节之后,也要给从机发送一个应答位,发送应答位的目的是告诉从机,你是不是还要继续发,如果从机发送一个数据后,得到了主机的应答,那从机就还会继续发送;如果从机没得到主机的应答,那从机就会认为,我发送了一个数据,但是主机不理我,可能主机不想要了吧,这时从机就会乖乖地释放SDA,交出SDA的控制权,防止干扰主机之后的操作,这就是应答位的执行逻辑。

  7. 接受应答

    • 主机在发送完一个字节之后,在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA

    • 时序与接受一个字节的其中一位相同,可以理解成接受一位,这一位就用来作为应答。

    • 当在调用发送一个字节之后,就要紧跟着调用接收应答的时序,用来判断从机有没有收到刚才给它的数据,如果从机收到了,那在应答位这里,主机释放SDA的时候,从机就应该立刻把SDA拉下来,然后在SCL高电平期间,主机读取应答位,如果应答位为0,就说明从机确实收到了,这个场景就是,主机刚发送一个字节,然后说,有没有人收到啊,我现在把SDA放手了哈,如果有人收到的话,你就把SDA拽下来,然后主机高电平读取数据,发现确实有人给它拽下来了,那就说明有人收到了;如果主机发现,我松手了,结果这个SDA就跟着回弹到高电平了,那就说明没有人回应,刚发的一个字节可能没人收到,或者它收到了但是没给我回应。

完整时序(数据帧)

本文12C是一主多从的模型,主机可以访问总线上的任何一个设备,那如何发出指令,来确定要访问的是哪个设备呢?这就需要首先把每个从设备都确定一个唯一的设备地址,从机设备地址就相当于每个设备的名字,主机在起始条件之后,要先发送一个字节叫一下从机名字,所有从机都会收到第一个字节,和自己的名字进行比较,如果不一样,则认为主机没有叫我,之后的时序我就不管了,如果一样,就说明,主机现在在叫我,那我就响应之后主机的读写操作,在同一条12C总线里,挂载的每个设备地址必须不一样,否则,主机叫一个地址,有多个设备都响应,就会造成混乱。从机设备地址,在12C协议标准里分为7位地址和10位地址,本文只讨论7位地址的模式,因为7位地址比较简单而且应用范围最广。在每个12C设备出厂时,厂商都会为它分配一个7位的地址,这个地址具体是什么,可以在芯片手册里找到,比如MPU6050这个芯片的7位地址是1101 000,一般不同型号的芯片地址都是不同的,相同型号的芯片地址都是一样的,那如果有相同的芯片挂载在同一条总线怎么办呢,这就需要用到地址中的可变部分了,般器件地址的最后几位是可以在电路中改变的,比如MPU6050地址的最后一位,就可以由板子上的ADO引脚确定,这个引脚接低电平,那它的地址就是1101000,这个引脚接高电平,那它的地址就是1101001。这样,即使相同型号的芯片,挂载在同一个总线上,也可以通过切换地址低位的方式,保证每个设备的地址都不一样,这就是I2C设备的从机地址。

  1. 指定地址写

    1. 对于指定设备(Slave Address 从机地址来确定),在指定地址(Reg Address 就是某个设备内部的RegAddress,寄存器地址)下,写入指定数据(Data 写入寄存器的数据

    2. 对于时序图的解析:在这里,上面的线是SCL,下面的线是SDA,空闲状态,它俩都是高电平,然后主机需要给从机写入数据的时候,首先,SCL高电平期间,拉低SDA,产生起始条件(Start,S),在起始条件之后,紧跟着的时序,必须是发送一个字节的时序,字节的内容,必须是从机地址+读写位,正好从机地址是7位,读写位是1位,加起来是一个字节(8位),发送从机地址,就是确定通信的对象,发送读写位,就是确认我接下来是要写入还是要读出。具体发送的时候,低电平期间,SDA变换数据高电平期间,从机读取SDA,这里用绿色的线,来标明了从机读到的数据。

    3. 时序案例:
      1. 首个字节:高7位,表示从机地址,比如这个波形下,主机寻找的从机地址就是11010000,这个就是MPU6050的地址,然后最低位,表示读写位,0表示,之后的时序主机要进行写入操作,1表示,之后的时序主机要进行读出操作,这里,是0,说明之后我们要进行写入操作那目前主机是发送了一个字节,字节的内容转换为16进制,高位先行,就是0xD0。

      2. 应答位:然后根据协议规定,紧跟着的单元,就得是接收人机的应答位(Receive Ack,RA),在这个时刻,主机要释放SDA,所以如果单看主机的波形,应该是释放SDA之后,引脚电平回弹到高电平,但是根据协议规定,从机要在这个位拉低SDA,所以单看从机的波形,应该是该应答的时候,从机立刻拽住SDA,然后应答结束之后,从机再放开SDA,那现在综合两者的波形,结合线与的特性,在主机释放SDA之后,由于SDA也被从机拽住了,所以主机松手后,SDA并没有回弹高电平,这个过程,就代表从机产生了应答,最终高电平期间,主机读取SDA,发现是0,就说明,我进行寻址,有人给我应答了,传输没问题。如果主机读取SDA,发现是1就说明,我进行寻址,应答位期间,我松手了但是没人拽住它,没人给我应答,那就直接产生停止条件吧,并提示一些信息。后面的上升沿,就是应答位结束后,从机释放SDA产生的,从机交出了SDA的控制权,因为从机要在低电平尽快变换数据,所以这个上升沿和SCL的下降沿,几乎是同时发生的。

      3. 发送字节:同样的时序,再来一遍,第二个字节,就可以送到指定设备的内部了,从机设备可以自己定义第二个字节和后续字节的用途,般第二个字节可以是寄存器地址或者是指令控制字等;比如MPU6050定义的第二个字节就是寄存器地址,比如AD转换器,第二个字节可能就是指令控制字;比如存储器,第二个字节可能就是存储器地址,那图示这里,主机发送这样一个波形,一一判定,数据为00011001,即主机向从机发送了0x19这个数据,在MPU6050里,就表示我要操作你0x19地址下的寄存器了,接着同样,是从机应答,接着同样,是从机应答。

      4. 应答位:主机释放SDA,从机拽住SDA,SDA表现为低电平,主机收到应答位为0,表示收到了从机的应答。

      5. 发送字节:这个字节就是主机想要写入到0x19地址下寄存器的内容了,比如我这里发送了0xAA的波形,就表示,我要在0x19地址下,写入0xAA。

      6. 接收应答位:如果主机不需要继续传输了,就可以产生停止条件(Stop,P)。

      7. 停止位:先拉低SDA,为后续SDA的上升沿作准备然后释放SCL,再释放SDA,这样就产生了SCL高电平期间,SDA的上升沿。

      8. 这样完整的时序就结束了。这个数据帧的目的就是,对于指定从机地址为1101000的设备,在其内部0x19地址的寄存器中,写入OXAA这个数据,这就是指定地址写的时序。

  2. 当前地址读

    1. 对于指定设备(Slave Address),在当前地址指针指示的地址下,读取从机数据(Data)

    2. 时序案例:
      1. 起始位:那最开始,还是SCL高电平期间,拉低SDA,产生起始条件。

      2. 发送字节:起始条件后,主机必须首先调用发送一个字节,来进行从机的寻址和指定读写标志位,比如图示的波形,表示本次寻址的目标是1101000的设备,同时,最后一位读写标志为1,表示主机接下来想要读取数据。。

      3. 应答位:紧跟着,发送一个字节之后,接收一下从机应答位,人机应答0,代表从机收到了第一个字节。

      4. 主机接受字节:从应答位结束之后,数据的传输方向就要反过来了因为刚才主机发出了读的指令,所以这之后,主机就不能继续发送了,要把SDA的控制权交给从机,主机调用接收一个字节的时序,进行接收操作。后面从机就得到了主机的允许,可以在SCL低电平期间写入SDA,然后主机在SCL高电平期间读取SDA,那最终,主机在SCL高电平期间依次读取8位,就接收到了从机发送的一个字节数据,00001111,也就是0x0F。

      5. 补充(当前地址读时序的操作逻辑):并且,会有一个单独的指针变量那这个数据是从机哪个寄存器的数据呢?可以知道在读的时序中,12C协议的规定是,主机进行寻址时,一旦读写标志位给1了,下一个字节就要立马转为读的时序,所以主机还来不及指定,想要读哪个寄存器,就得开始接收了,所以这里就没有指定地址这个环节,那主机并没有指定寄存器的地址,从机到底该发哪个寄存器的数据呢,这就需要用到上面说的当前地址指针了,在从机中,所有的寄存器被分配到了一个线性区域中,指示着其中一个寄存器,这个指针上电默认,一般指向0地址,并且,每写入一个字节和读出一个字节后,这个指针就会自动自增一次,移动到下一个位置,那么在调用当前地址读的时序时,主机没有指定要读哪个地址,从机就会返回当前指针指向的寄存器的值。那假设,我刚刚调用了这个指定地址写的时序,在0x19的位置写入了0xAA,那么指针就会+1,移动到0x1A的位置,我再调用这个当前地址读的时序,返回的就是0x1A地址下的值,如果再调用一次呢,返回的就是0x1B地址下的值,以此类推。由于不能指定读的地址,这个时序使用的频率也不是很高。

  3. 指定地址读:

    1. 对于指定设备(Slave Address),在指定地址(Reg Address)下,读取从机数据(Data

    2. 将指定地址写,后面写入数据的那一部分时序拿掉,然后把前面一段设置地址,还没有指定写什么数据的时序,给它追加到这个当前地址读时序的前面,就得到了指定地址读的时序,一般把它称作复合格式。前面有指定地址写,但是只指定了地址,还没有写入数据 ;后面的部分是当前地址读,因为刚刚指定了地址,所以在调用当前地址读两者就加在一起了,就是制定地址读了,所以,指定地址读的时序会复杂一些。

    3. 时序案例:
      1. 起始位:首先,最开始,仍然是启动条件。

      2. 发送字节:然后发送一个字节,进行寻址,这里指定从机地址是1101000,读写标志位是0,代表要进行写的操作。

      3. 应答位:从机应答。(也可以在这里再加入一个停止条件,因为写入的地址会存在地址指针里面,所以这个地址并不会因为时序的停止而消失)

      4. 发送字节:第二个字节,用来指定地址,这个数据就写入到了从机的地址指针里了,也就是说,从机接收到这个数据之后,它的寄存器指针就指向了0x19这个位置。之后,我们要写入的数据,不给它发,而是直接再来个起始条件。

      5. 重复起始位:这个Sr(Start Repeat)的意思就是重复起始条件,相当于另起一个时序,因为指定读写标志位只能是跟着起始条件的第一个字节,所以如果想切换读写方向只能再来个起始条件。

      6. 发送字节:然后起始条件后,重新寻址并且指定读写标志位,此时读写标志位是1,代表这就是指定地址读要开始读了,接着,主机接收一个字节这个字节就是0x19地址下的数据,这就是指定地址读。

      7. 应答位:主机非应答。在读完一个字节之后,一定要给从机发个非应答,(Send Ack,SAD),就是该主机应答的时候,主机不把SDA拉低,从机读到SDA为1,就代表主机没有应答,从机收到非应答之后,就知道主机不想要继续了,从机就会释放总线,把SDA控制权交还给主机,如果主机读完仍然给从机应答了,从机就会认为主机还想要数据,就会继续发送下一个数据,而这时,主机如果想产生停止条件,SDA可能就会因为被从机拽住了,而不能正常弹回高电平。如果主机想连续读取多个字节,就需要在最后一个字节给非应答,而之前的所有字节都要给应答。简单来说就是主机给应答了,从机就会继续发主机给非应答了,从机就不会再发了,交出SDA的控制权从机控制SDA发送一个字节的权利,开始于读写标志位为1,结束于主机给应答为1。

      8. 停止位:结束时序。

      9. 补充:也可以在第一个应答位再加入一个停止条件,因为写入的地址会存在地址指针里面,所以这个地址并不会因为时序的停止而消失,这样时序就是两条完整的时序,就可以再起始,读当前位置,停止,这样两条时序也可以完成任务但是12C协议官方规定的复合格式是一整个数据帧。相当于把两条时序拼接成一条了就是先起始、再重复起始、再停止,相当于把两条时序拼接成一条了。

  4. 指定地址读/写多个字节

    1. 指定地址写多个字节:在指定地址写的时序的基础上,如果你只想写一个字节,那就停止,就行了如果你想写多个字节,就可以把这最后一部分,多重复几次,比如这里,重复三遍发送一个字节和接收应答,这样第一个数据就写入到了指定地址0x19的位置,这样这个时序就进阶为,在指定的位置开始,按顺序连续写入多个字节。比如你需要连续写入多个寄存器,就可以这样操作,这样在一条数据帧里,就可以同时写入多个字节,执行效率高。

    2. 当前位置/指定位置读多个字节:也可以多次执行这最后一部分时序,由于地址指针在读后也会自增,所以这样就可以连续读出一片区域的寄存器,效率也会非常高。

以上就是12C总线的硬件规定和软件规定了,有了这些规定,我们就可以按照硬件规定来连接线路,用软件规定来操作总线,以此实现指定位置写寄存器和指定位置读寄存器,有了这两个功能,主机就可以完全掌控外挂模块的运行了,也就实现了设计这个协议的目的。

四、MPU6050简介

  1. 基本概念:

    1. MPU6050是一个6轴姿态传感器,可以测量芯片自身XYZ轴的加速度、角速度参数,通过数据融合,可进一步得到姿态角(欧拉角),常应用于平衡车、飞行器等需要检测自身姿态的场景

    2. 在现实的三维空间里,只有XYZ,3个轴,这个MPU6050芯片里面,有加速度计和陀螺仪两种传感器,分别可以测量XYZ,3个轴的加速度和角速度,加起来总共就是6个轴,所以这个芯片是6轴姿态传感器,如果芯片里再集成一个3轴的磁场传感器,测量XYZ轴的磁场强度,那就叫作9轴姿态传感器,如果再集成一个气压传感器,测量气压大小,那就叫作10轴姿态传感器,一般气压值反映的是高度信息,海拔越高,气压越低,所以气压计是单独测量垂直地面的高度信息的。

    3. 加速度计和陀螺仪的基本原理都是设计一种装置,当传感器所感应的参数变化时,这个装置能带动电位器滑动,或者装置本身的电阻,可以随感应参数变化而变化,这样再外接一个电源,通过电阻分压,就能把现实世界的各种状态用电压表示出来了。总之电子的传感器最终也是输出一个随姿态变化而变化的电压,要想量化这个电压信号,

  2. 基本构成

    • 三轴陀螺仪(Gyroscope):用于测量物体在三维空间中绕 X、Y、Z 三个轴的角速度,能够感知物体的旋转运动状态,比如设备的转动、旋转等动作。例如,当手机进行旋转操作时,陀螺仪可以检测到相应的角速度变化。(陀螺仪具有动态稳定性,不具有静态稳定性)

    • 三轴加速度计(Accelerometer):可测量物体在 X、Y、Z 三个方向上的加速度,能反映物体的倾斜、震动等运动情况。比如当设备处于静止状态时,加速度计可以检测到重力加速度在三个轴上的分量;当设备发生震动时,加速度计能够测量到震动产生的加速度变化。(加速度计具有静态稳定性,不具有动态稳定性)

    • 数字运动处理器(DMP):这是 MPU6050 的核心处理单元,能够对陀螺仪和加速度计采集到的数据进行融合演算等处理,减轻主控制器(如单片机、微处理器等)的运算负担,提高数据处理效率。

  3. 引脚功能

    • SCL 和 SDA:这是连接微控制器(MCU)的 IIC 接口(Inter-Integrated Circuit,集成电路总线)。MCU 通过这个接口与 MPU6050 进行通信,实现对传感器的控制和数据读取。

    • XCL 和 XDA:辅助 IIC 接口,用于连接外部的从设备,比如磁力传感器。当连接磁力传感器后,MPU6050 可以组成一个九轴传感器,输出更全面的运动数据。

    • AD0:地址管脚,用于控制 IIC 地址的最低位。当 AD0 接 GND 时,MPU6050 的 IIC 从机地址是 0x68;当 AD0 接 VDD 时,IIC 从机地址是 0x69。

    • INT:数据输出的中断引脚,当 MPU6050 准备好数据之后,可以通过该中断引脚通知主控制器来获取数据,提高数据传输的实时性。

  4. 感测范围与精度

    • 陀螺仪感测范围:角速度全格感测范围通常有 ±250、±500、±1000 与 ±2000°/sec(度每秒)等可选择的量程,不同量程下精度不同,用户可根据实际应用需求进行编程设置。例如在对旋转速度要求不高但需要较高分辨率的场景下,可以选择较小的量程;在需要测量高速旋转的场景下,则选择较大的量程。满量程选的越大,测量范围就越广;满量程选的越小,测量分辨率越高。

    • 加速度计感测范围:用户可程式控制的加速度全格感测范围为 ±2g、±4g、±8g 与 ±16g,其中 “g” 是重力加速度单位,1g 约等于 9.8 米每平方秒。例如在测量轻微震动或倾斜时,可能选择较小的量程;在测量剧烈运动或高加速度场景时,选择较大的量程。

    • 16位ADC采集传感器的模拟信号量化范围:因为加速度计和陀螺仪的设计,可以知道电子的传感器最终也是输出一个随姿态变化而变化的电压,要想量化这个电压信号,就需要AD转换器,所以这个芯片内部也是自带了AD转换器,可以对各个模拟参量进行量化,这个ADC是16位的,那量化输出的数据变化范围就是2^16,如果作为无符号数的话,就是0~65535,这里因为传感器每个轴都有正负的数据,所以这个输出结果是一个有符号数,量化范围是-32768~32767。数据是16位的,会分为2个字节存储。

    • 例子:比如选择加速度计满量程为±16g,当读取AD值为最大值,32768时,那就表示此时测量的加速度为满量程16g,AD值为32768的一半时,就表示加速度为8g;如果选择满量程为±2g的话,那此时32768就对应2g的加速度,32768的一半就对应1g的加速度所以满量程选的越小,测量就会越细腻,因为AD值的范围是一定的。另外AD值和加速度值是线性关系、一一对应的由AD值求加速度,就是乘一个系数就可以了,这和学习ADC时,由AD值直接求电压是一个道理。

  5. 可配置的功能

    • 可配置的数字低通滤波器:可以对采集到的数据进行滤波处理,去除高频噪声,提高数据的稳定性和准确性。通过设置不同的滤波参数,可以让低频部分的数据通过,使输出的数据更加平滑。如果输出数据抖动太厉害,就可以加一点低通滤波,这样输出数据就会平缓一些。

    • 可配置的时钟源:与可配置的采样分频配合使用。MPU6050 可以选择不同的时钟源,以满足不同的应用需求。例如,可以选择内部时钟源或外部时钟源,并且可以根据需要对时钟频率进行调整。

    • 可配置的采样分频:与可配置的时钟源配合使用。用于设置采样速率,也就是数据的刷新率。通过调整采样分频寄存器的值,可以改变 MPU6050 的数据输出频率,以适应不同的应用场景对数据更新速度的要求。

    • 时钟源经过分频器的分频,可以为AD转换和内部其他电路提供时钟,控制分频系数,就可以控制AD转换的快慢了。

  6. 工作原理及数据输出

    • 工作原理:通过陀螺仪和加速度计分别采集物体的角速度和加速度数据,然后将这些原始数据传输到数字运动处理器(DMP)中进行处理。DMP 可以将原始的角速度数据转化为四元数,再通过简单的数学公式计算出欧拉角,从而得到物体在三维空间中的姿态信息,即物体绕坐标系三个坐标轴(X、Y、Z)的旋转角度。

    • 数据输出:MPU6050 可以以数字输出的形式提供融合演算后的数据,包括旋转矩阵、四元数、欧拉角等格式的数据,方便主控制器进行读取和进一步处理。

  7. 从机地址:

    • 当AD0=0时,地址为1101000

    • 当AD0=1时,地址为1101001

    • AD0就是板子引出来的一个引脚,可以调节12C从机地址的最低位,这里地址是7位的,如果像这样,用二进制来表示的话,一般没问题,如果在程序中,用十六进制表示的话,一般会有两种表示方式。以这个1101000的地址为例,第一种,就是单纯地把这7位二进制数转换为十六进制,这里1101000,低4位和高3位切开,转换十六进制,就是0x68,所以有的地方就说MPU6050的从机地址是0x68,所以将0x68为从机地址的话,在发送一个字节时,要把0x68左移一位,再按位或上读写位,读1写0。第二种表示方式,把0x68左移1位后的数据,当做从机地址,0x68左移1位之后,是0xD0,那这样,MPU6050的从机地址就是0xD0,这时,在实际发送第一个字节时,如果你要写,就直接把0xD0当作第一个字节,表示这里的从机地址;如果你要读,就把0xD0或上0x01,即OxD1当作第一个字节,这种表示方式,是把读写位也融入到从机地址里了,0xD0是写地址,0xD1是读地址。但是无论那种地址I2C收到的第一个字节都是一样的。

  8. 应用场景

    • 姿态控制领域:如平衡车、无人机等设备,需要实时监测设备的姿态变化,并根据姿态信息进行精确的控制和调整,以保持设备的平衡和稳定。

    • 运动追踪领域:可用于运动手环、智能手表等穿戴设备,对用户的运动状态进行监测和追踪,如步数统计、跑步距离测量、运动轨迹记录等。

    • 手势识别领域:通过识别用户手部的动作和姿态,实现对电子设备的手势控制,如手机的手势操作、智能电视的手势控制等。

    • 游戏领域:在体感游戏中,玩家的身体动作可以通过 MPU6050 等传感器转化为游戏中的操作指令,增强游戏的趣味性和沉浸感。

六、MPU6050硬件电路

  1. 硬件电路图

    1. 其中右边这个是MPU6050的芯片,左下角是一个8针的排针,左上角是一个LDO,低压差线性稳压器。

    2. MPU6050芯片:芯片本身的引脚是非常多的,包括时钟、12C通信引脚、供电、帧同步等等,不过大部分引脚本文还是用不到的,还有一些引脚,是这个芯片最小系统里的固定连接。

    3. 排针:

      1. VCC、GND:这些引脚用于提供电源。

      2. SCL、SDA:这些是 I2C 通信引脚,用于模块与其他设备之间的通信。在MPU6050芯片的右上角,SCL、SDA在模块中已经内置了两个4.7K的上拉电阻了,所以在接线的时候,直接把SCL和SDA接在GPIO口就行了,不需要再在外面另外接上拉电阻了。

      3. XCL、XDA:这些是主机 I2C 通信引脚,用于连接到主机设备。设计这两个引脚是为了扩展芯片功能,由于MPU6050是一个6轴姿态传感器,但是只有加速度计和陀螺仪的6个轴,融合出来的姿态角是有缺陷的,这个缺陷就是绕Z轴的角度,也就是偏航角,它的漂移无法通过加速度计进行纠正,这就相当于让你蒙眼坐在车里,让你辨别车子行驶的方向,短时间内,你可以通过陀螺仪得知方向的变化,从而确定变化后的行驶方向,但是时间一长,车子到处转弯,你没有稳定的参考了,就肯定会迷失方向,所以这时候,你就要带个指南针在身边,提供长时间的稳定偏航角进行参考,来对陀螺仪感知的方向进行纠正,这就是9轴姿态传感器多出的磁力计的作用。另外,如果要制作无人机,需要定高飞行,这时候就还需要增加气压计,扩展为10轴,提供一个高度信息的稳定参考。所以根据要求6轴传感器可能不符合要求,需要增加拓展,此时XCL、XDA这两个引脚就提现到他们的作用了,XCL和XDA,通常就是用于外接磁力计或者气压计,当接上磁力计或气压计之后,MPU6050的主机接口可以直接访问这些扩展芯片的数据,把这些扩展芯片的数据读取到MPU6050里面,在利用DMP单元,进行数据融合和姿态解算。

      4. AD0:这个引脚用于从机地址最低位。接低电平的话,7位从机地址就是1101000,接高电平的话,7位从机地址就是1101001。这里电路中,可以看到,有一个电阻,默认弱下拉到低电平了,所以引脚悬空的话,就是低电平,如果想接高电平,可以把ADO直接引到VCC,强上拉至平高电平。

      5. INT:这个引脚用于中断信号输出。可以配置芯片内部的一些事件,来触发中断的输出,比如数据准备好了、I2C主机错误等。另外芯片内部还内置了一些实用的小功能,比如*落体检测、运动检测、零运动检测等,这些信号都可以触发INT引脚产生电平跳变,需要的话可以进行中断信号的配置。

    4. LDO:这部分是供电的逻辑,MPU6050芯片的VDD供电是2.375-3.46V,属于是3.3V供电的设备,不能直接接5V,所以为了扩大供电范围,这个模块就加了个3.3V的稳压器,输入端电压VCC 5V可以在3.3V到5V之间,然后经过3.3V的稳压器,输出稳定的3.3V电压,给芯片端供电。右侧是电源指示灯,只要3.3V端有电,电源指示灯就会亮。所以这一部分可以根据相应的需求进行,如果你已经有稳定的3.3V电源了,就不再需要这一部分了。

    5. 在本实验中,直接VCC、GND接上电,SCL和SDA接上12C通信的GPIO口就行了。

七、MPU6050的模块框图

  • 模块框图概述

MPU6050 框图顶部有绿色标题 “MPU6050 框图”,并且有注释表明此电路图等同于芯片内部封装。该框图展示了 MPU - 60X0 模块的内部结构,涵盖多个功能模块和引脚。

  • 引脚功能

1. 时钟相关引脚

  • CLKIN 和 CLKOUT
    • 功能:CLKIN 是时钟输入引脚,外部时钟信号由此进入模块,为模块内的各种操作提供基准时钟。CLKOUT 是时钟输出引脚,它将模块内部产生的时钟信号输出,可用于同步与该模块连接的其他外部设备的操作。这两个引脚对于确保模块操作的同步性至关重要。例如,在一个需要多个传感器协同工作的系统中,MPU6050 通过 CLKOUT 引脚输出时钟信号给其他传感器,使它们能在相同的时间基准下工作。

    • 在框图中的作用:属于时钟模块的输入输出引脚,但是一般使用内部时钟。在硬件电路中,CLKIN直接接了GND,CLKOUT没有引出,所以这部分可以不用关心。

  • X0
    • 功能:作为外部时钟输入引脚,它提供了另一种外部时钟接入的途径。在某些应用场景下,当系统有特定的外部时钟源可用时,可通过 X0 引脚将该时钟信号输入到 MPU6050 模块中,使模块能根据此外部时钟进行工作。

2. 电源相关引脚

  • VDD、GND
    • 功能:VDD 是电源正极输入引脚,为 MPU6050 提供工作所需电能。GND 为接地引脚,与电源负极相连,构成电流回路。稳定的电源供应是模块正常运行的基础,在连接电源时,必须确保 VDD 和 GND 连接正确且稳定。

  • REGOUT
    • 功能:稳压电源输出引脚,它可以为外部的一些对电源稳定性要求较高的小功率电路提供稳定的电源。例如,在一个小型传感器网络中,MPU6050 的 REGOUT 引脚可以为一些辅助的低功耗传感器供电。

  • VLOGIC
    • 功能:独立的逻辑电源引脚,可以支持供电和IO口不一样的电平等级,为模块内的逻辑电路部分提供特定的电源,确保逻辑电路的正常工作。不同的电源引脚有助于将模块内不同功能部分的电源进行分离,提高电路的稳定性和可靠性。

3. 其他引脚

  • CPOUT
    • 功能:电荷泵输出引脚,电荷泵在模块中通常用于产生高于电源电压的电压或者用于一些特殊的电源转换操作。CPOUT 引脚输出的电荷泵信号可能用于驱动某些需要较高电压的内部电路或者外部连接的设备。

    • 电荷泵的升压原理:比如我有个电池,电压是5V,再来个电容,首先电池和电容并联,电池给电容充电,充满之后,电容也相当于一个5V的电池了,然后再把电池和电容串联起来,电池5V,电容也是5V,这样输出就是10V的电压了,就可以凭空把电池电压升高至两倍了,不过由于这个电容电荷比较少,用一下就不行了,所以这个并联、串联的切换速度要快,趁电容还没放电完,就要及时并联充电这样一直持续,并联充电,串联放电,并联充电,串联放电,然后续再加个电源滤波,就能进行平稳的升压了。

    • 在这里,由于陀螺仪内部是需要个高电压支持的,所以这里设计了一个电荷泵进行升压,当然这个升压过程是自动的,不需要管。

  • INT
    • 功能:中断输出引脚。当模块内发生特定事件,如数据采集完成、传感器检测到异常等符合预设中断条件的情况时,模块会通过 INT 引脚向外部设备发送中断信号。外部设备接收到中断信号后,可以及时对相应事件进行处理。例如,当加速度计检测到超过预设阈值的加速度时,会通过 INT 引脚向微控制器发送中断信号,以便微控制器立即采取相应措施。

  • FSYNC
    • 功能:帧同步。本文不涉及。

4. 通信接口相关的引脚

  • (CS)    AD0 / (SDO)    SCL / (SCLK)    SDA / (SD)
    • 功能:是从机的12C和SPI通信接口,用于和STM32通信。
  • AUX_CL  /  AUX_DA
    • 功能:是主机的12C通信接口,用于和MPU6050扩展的设备进行通信。
  • 功能模块

1. 通信接口模块

  • Slave I2C and SPI Serial Interface
    • 功能:从机 I2C 和 SPI 串行接口,使 MPU6050 能够作为从设备与外部的主设备进行通信。在 I2C 模式下,通过 SCL(时钟线)和 SDA(数据线)与主设备交换数据,可用于传输传感器采集的数据和接收主设备发送的配置指令等。在 SPI 模式下,通过多个引脚(如片选、时钟、数据输入和输出引脚)实现高速数据传输,适用于对数据传输速度要求较高的应用场景。

  • Master I2C Serial Interface
    • 功能:主机 I2C 串行接口,允许 MPU6050 作为主机与其他 I2C 从设备进行通信。这在一些需要 MPU6050 控制其他 I2C 设备的系统中非常有用,例如在一个集成了多个传感器的系统中,MPU6050 可以通过主机 I2C 接口读取其他从机传感器的数据。

  • Serial Interface Bypass
    • 功能:串行接口旁路模块,该模块可能用于在特定情况下实现对串行接口数据的直接传输或特殊处理。例如,在某些调试或特定的数据传输模式下,可以通过该旁路模块实现更灵活的数据操作。

    • 工作流程:相当于开关,如果拨到上面,辅助的12C引脚就和正常的I2C引脚接到一起,这样两路总线就合在一起了,STM32可以控制所有设备(包括MOU6050的扩展设备);如果拨到下面,辅助的I2C引脚就由MPU6050控制,两条12C总线独立分开,这时STM32是MPU6050的大哥,MPU6050又是扩展设备的大哥。

2. 寄存器模块

  • Interrupt Status Register
    • 功能:中断状态寄存器,可以控制内部的哪些事件到中断引脚的输出。

    • 引脚:INT(控制内部的哪些事件到中断引脚的输出)

  • FIFO
    • 功能:是先入先出寄存器,可以对数据流进行缓存。本文暂时不使用。

  • Config Registers
    • 功能:配置寄存器,可以对内部的各个电路进行配置,

  • Sensor Registers
    • 功能:传感器寄存器,也就是数据寄存器,存储了各个传感器的数据。

3. 数据处理和校准模块

  • Factory Calibration
    • 功能:工厂校准模块,用于校准传感器数据。在芯片生产过程中,由于制造工艺的偏差,传感器的测量数据可能存