STM32——I2C协议以及软件读写

I2C协议中SCL用于同布,当某一方发送/接收数据时,另一方将会发应答表示数据已收到。

一主多从:类似于老师是主在讲课,学生是从机,只有老师点名学生才能应答,否则不能自己应答。

之后是硬件电路的设置

对于SCL来说是一主多从不会出现什么问题,但是这个协议中SDA属于半双工,主机和从机的状态都是在输出和输入中跳转,当时序没有协调好时,可能会出现一个输出高电平、一个输出低电平,两者相遇就会造成电路短路的情况。因此为防止这种情况下面的2、3条用于限制

第二条的意思就是从机默认输出低电平且无驱动能力,避免主从的相互干扰

右图是从机内部结构,左边是SCL,右边是SDA

以下是SCL数据输入时,电路无影响

本节设置为开漏输出模式,保留低电平开关,无高电平开关,低电平开关按下时,导通低电平,

当低电平开关断开时,处于浮空状态,因此

假设有一根杆子,本来有向下拉和向上推两种状态,但是在这里规定任何人都不能向上推,只有向下拉和放手两种状态,向下拉时是低电平导通,而放手则是上方有一个弹簧(弱上拉)会有向上的状态。此时杆子不会同时出现强拉和强推现象。

输入是拉杆子或者放手;输出是放手观察杆子高低,输出高电平

只要其中一个输出低电平,总线就输出低电平。

之后是软件部分:只有主机能产生起始和终止

之后由主机发送字节时,SCL向下拉处于低电平时SDA的数据可为0/1,当SCL放手后,从机开始读取数据,8次后传输一个字节,主机发送从机接收。从高位开始发送。

SCL和SDA都由主机控制,从机只是被动读取

过程类似就是主从位置互换,主机接收前,需要释放SDA从才能输入数据

实线是主机控制,虚线是从机控制!

假设主机在发送一个字节后,把SDA放手,如果有从机接收那么SDA就会被下拉,如果SDA一直是放手状态,就说明数据无人接收。

主机接收数据时,从机发送应答,如果主机没向下拉SDA,从机就会交出SDA控制权,防止干扰主机后续操作。

之后是I2C的时序:

首先是起始条件,之后对从机地址进行输入(7位从机地址+一位读写位)R为1,W为0;

之后输入应答位,0代表从机响应

之后输入寄存器的地址,表示要对从机的这个地址下的寄存器进行数据输入,然后发送应答位

最后输入数据,如果完毕就发送终止条件。

之后是:

只输入从机地址,相当于从机的数据是一个线性结构,当得到读指令时就给地址指针当前指向的数据,之后地址自增1。假如在上一部分的写操作中,在0X19寄存器中写入数据,此时变成读指令,地址指针就会先自增到0X1A,读取数据,如果继续读,就是在OX1B的寄存器读取数据。

用途不多。

此时主机给SA表示非应答,此时主机不再接受其他数据,从机释放SDA权利,否则从机继续给数据让主机读。

第三种:

采用复合模式,先将指定地址写的前两部分放到指定地址读时序前,然后再输入从机地址+读写位再读出数据。Sr表示重复起始条件。

I2C规定格式:先起始——重复起始——停止

之后是MPU6050芯片的介绍

6轴:3个轴的加速度+3个轴的角速度(9轴:再加3个轴的磁场强度,10轴:再加一个气压)

加速度计A:可以想象成一个正方体里边放着一个相同质量的小球,小球放在里边相当于底面受力,此时Z轴为正值,具有静态稳定性

陀螺仪传感器G:可以想象成游乐场的飞椅,通过旋转产生两个相对的飞椅夹角,合起来就是中间轴的角速度,进行积分就是角度(存在一定漂移),具有动态稳定性

量化范围和以下两种的量程是一一线性对应的

对于从机地址有两种说法

对于1101000来说:1、没有融入读写位,相当于7位0110 1000,直接转换为16进制为0X68,之后需要将地址位左移一位,加入读写位

2、融入读写位的地址,例如是写操作,1101 0000,为0XD0地址

以下是芯片的硬件电路:

左下角的XCL和XDA可以用来外接芯片,如无人机需要气压信息时,需要10轴,这两个就可以直接接其他芯片,将信息输入到6050芯片内进行姿态解算等完成功能,如果不需要姿态解算,也可直接与6050芯片的SCL和SDA连接一个气压计/磁力计等。

MPU6050内部就有上拉电阻,因此不需要再额外加电阻,直接与SCL和SDA连接,即可

应用场景:

除了以下两个寄存器地址外,其余寄存器地址均为0X00

之后是代码和实验部分:

主要是以下三个部分,先是编写I2C的GPIO口初始化、6个时基单元(起始条件、终止条件、发送一个字节、接收一个字节、发送应答、接收应答)

之后写MPU6050中指定位置读、指定位置写、写寄存器对芯片进行配制、读寄存器得到传感器数据

最后是主程序中初始化OLED和I2C,读取数据、显示数据

先对I2C进行编辑:

1、初始化GPIO口,SCL和SDA都选用开漏输出模式

2、分别编写6个时基单元

为方便,此处增加三个函数,分别是SCL的写和SDA的读、写

其中写函数SCL和SDA格式一致只有引脚不一样,只有SDA需要读

之后是起始条件,根据理论知识可得,起始条件:释放SDA(1)——SCL(1)——SDA(0)——SCL(0),保证SDA有下降沿

终止条件:SDA(0)——SCL(1)——SDA(1),保证SDA有上升沿

发送一个字节,采用高位发送,一位一位发,首先发送数据的最高位,此时SCL为低电平,立马将数据放在SDA上,

Byte&0X80采用按位与操作,例如i=0时,此时Byte&10000000,后7位都是0,最高位与1相与,如果是1输出1,如果是0输出0,得到Byte的最高一位值,之后采用右移方法,0X80右移一位为0X40即0100 0000 与Byte取出次高位从,以此类推,从而将1个字节中的每一位取出并发送

之后是接收字节:例如当读取的第一位为1时,执行Byte或等于0X80,此时Byte最高位是1,如果读取的第一位不为1,if不成立,Byte最高位直接为0,以此类推得到8位数据。

发送应答:发一位,0表示应答,此时SCL低电平,把AckBit放在SDA上进行传输,SCL高电平读取,之后拉低进行后续操作

接收应答:接1位,0表示应答

之后是MPU6050芯片的代码编写:

首先是指定地址写:

根据以上理论知识发送一个字节:起始条件——从机地址+写——应答——指定寄存器地址——应答——发送数据——应答——终止条件

指定地址读1个字节:

起始条件——从机地址+写——应答——制定寄存器地址——应答——重复起始条件——从机地址+读——应答——接收数据——非应答——终止条件

测试写寄存器能否实现:首先解除睡眠模式给0X6B输入0X00,之后随机找一个寄存器写入随机内容,并读取显示在OLED上看写功能是否实现:

之后对寄存器进行初始化配置:DIV为10分频,陀螺仪和加速度都选择最大量程

再加上ID号的函数

之后编写6轴的数据代码,采用指针方式,先分别读取高8位和低8位然后将高8位左移8位与低8位拼接成16位数据之后返回给指针,6个操作都相同。

对于主函数来说:

通过指针变量不断读取数据并显示

实验结果如下所示:

对于加速度而言,类比于一个放在正方体内的一个小球的受力情况:

首先是水平放置时,只有Z轴受力,X、Y近似为0

水平放置

之后是X轴上倾为正、下倾为负

上倾

下倾

Y轴左倾为正,右倾为负

左倾

右倾

Z轴翻转之后为负

翻转面包板

通过上述实验,充分理解了软件发送和接收数据的过程,之后将学习硬件的操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hssfscv

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值