【STM32】I2C通信—软件模拟
【STM32】I2C通信—软件模拟
- 一、I2C协议
- 1.1 I2C简介
- 1.2 硬件电路
- 二、I2C时序基本单元
- 2.1 起始终止
- 2.2 发送一个字节
- 2.3 接收一个字节
- 2.4 发送接收应答ACK
- 三、I2C完整时序数据帧
- 3.1 指定地址写
- 3.2 当前地址读
- 3.3 指定地址读
- 四、MPU6050芯片
- 4.1 MPU6050简介
- 4.2 MPU6050参数
- 4.3 硬件电路
- 4.4 模块内部结构图
- 4.5 数据帧
- 4.6寄存器地址
- 五、软件模拟I2C读写MPU6050
一、I2C协议
1.1 I2C简介
I2C总线是一种通用数据总线(Inter Ic Bus)
两根通信线:SCL(Serial Clack),SDA(Serial Data)
同步,半双工,带数据应答机制
(异步时序的好处省一根时钟线,缺点是对硬件电路非常依赖)
支持总线挂载多设备(一主多从,多主多从)
- 一主多从:单片机作为主机,主导I2C总线运行,挂载在I2C总线的所有外部模块都是从机,从机只有在主机点名之后才能控制I2C总线
- 多主多从:在总线上任何一个模块都可以主动跳出来都当主机,此时I2C协议会进行仲裁
1.2 硬件电路
所有I2C设备的SCL连接一起,SDA连在一起。
设备的SCL和SDA均要配置成开漏输出模式(这个模式有个线与的现象,只要有一个设备输出低电平,总线就处于低电平。)
SCL和SDA各添加一个上拉电阻,阻值一般为4.7kΩ左右。
为什么 I2C 必须用开漏模式?
核心原因是为了实现 I2C 的 “线与逻辑”(Wired-AND) 和多设备共享总线:
线与逻辑:总线上多个设备可同时驱动 SDA/SCL 线,但只有当所有设备都 “释放” 总线(输出高阻态)时,上拉电阻才能将总线拉为高电平;只要有一个设备将总线拉低,总线就会保持低电平。这确保了多个设备通信时不会因 “同时输出高电平” 导致冲突或短路。
多设备兼容:无论总线上设备的电源电压是否一致(如 3.3V 和 5V 设备混合),开漏模式配合上拉电阻可避免高电压设备对低电压设备的损坏(只要上拉电压匹配低电压设备)。避免一个输出高电平,一个输出低电平导致正负极直接连通短路
二、I2C时序基本单元
2.1 起始终止
起始条件:SCL高电平时期,SDA从高电平切换低电平
终止条件:SCL高电平时期,SDA从低电平切换高电平
2.2 发送一个字节
发送一个字节:SCL 低电平期间,主机将数据位依次放到 SDA 线上(高位先行),然后释放 SCL,从机将在 SCL高电平期间读取数据位,所有 SCL 高电平期间 SDA 不允许有数据变化,依次循环上述过程 8 次,即发送一个字节。
(在SCL低电平时,主机改变SDA,在SCL高电平时,从机读取SDA)
2.3 接收一个字节
接收一个字节:SCL低电平期间,从机将数据位依次放到SDA线上**(高位先行),然后释放SCL,主机将在SCL高电平期间连续读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收前,需释放SDA)**
区别:发送一个数据,低电平主机放数据,高电平从机读数据
接收一个数据,高电平主机放数据,低电平从机读数据
2.4 发送接收应答ACK
发送应答:主机在接收完一个字节后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答。
接收应答:主机在接收完一个字节后,在下个时钟发送一位数据,判断从机是否应答数据0表示应答,数据1表示非应答。(主机在接收之前,需释放SDA)
三、I2C完整时序数据帧
3.1 指定地址写
指定地址写:对于指定设备(Slave Address 从机地址确定),在指定地址(reg address 内部寄存器地址)下写入指定数据
这段时序的意义:对于指定的从机地址为 1101000 的设备,在其内部 0x19 地址寄存器中,写入 0xAA 这个数据
3.2 当前地址读
当前地址读:对于指定设备(Slave Address),在当前地址指针指示下,读取从机数据
在从机中,所有寄存器被分配到了一个线性区域中,此时会有单独的指针变量,指示其中一个寄存器,每次写入一个字节后指针会自增一次,移动到下一次
3.3 指定地址读
指定地址读:对于指定设备(slave Adress),在指定地址下,读取从机数据
先用指定地址写将指针指到想要的寄存器,再重新起始条件开始当前地址读
最开始,启动条件,发送0XD0进行寻址,读写位为0,代表写入,经过从机应答,再发送一个字节,用来指定地址,此时就写到从机的地址指针里,此时寄存器指针指向了0X19,起始条件后,重新读写,并读标志位
Sr:重复起始条件,相当于另起一个时序。
四、MPU6050芯片
4.1 MPU6050简介
本次运用I2C通信让单片机与MPU6050芯片通信,获取姿态传感器数据。以下是对MPU6050的介绍
MPU 6050 是个 6 轴姿态传感器,可以测量芯片自身的 X,Y,Z 轴的加速度、角速度参数,通过数据融合,可进一步得到姿态角(欧拉角),常用于平衡车等需要检测姿态的场景
3 轴加速度计(Accelerometer):测量 X,Y,Z 轴加速度
3 轴陀螺仪传感器:(Gynoscope)测量 X,Y,Z 轴加速度
欧拉角是飞机机身相对于初始的三个轴的夹角,飞机机头下倾/上仰,这个轴的夹角叫作俯仰,pitch。
飞机机身左翻/右翻叫作滚转,Roll,飞机机身保持水平,机头向左转或者向右转叫作偏航,Yaw。
4.2 MPU6050参数
- 16位ADC采集传感器的模拟信号,量化范围-32768 - 32767(ADC对各个模拟参量进行量化),会分为2个字节进行存储。
- 加速度计满量程选择:±2 ±4 ±8 ±16(g)(16位AD值达到最大时,对应的物理参量具体是多少)
陀螺仪满量程选择:±250,±500,±1000,±2000(°/sec)(每秒旋转了多少度) - 可配置的数字低通滤波器(配置低通滤波,输出数据就会平缓,减少抖动)
- 可配置的时钟源:经过分频器分频,可以为AD转换和其他电路提供时钟,控制分频系数,就可以控制AD转换的快慢了。
- 可配置的采样频率
I2C从机地址:1101000(AD0=0) 110 1000 → 0x68 0x68未带读写位 0xD0带读写位
1101001(AD0=1)
4.3 硬件电路
- Vcc、GND:电源引脚。
- SCL、SDA:I2C 通信引脚,因内置 4.7kΩ 上拉电阻,可直接接在 GPIO 口。
- XCL、XDA:主机 I2C 通信引脚。
- AD0:从机地址最低位。
- INT:中断信号输出引脚,可配置芯片内部事件(如 I2C 主机错误,以及芯片内部自带的落体检测、运动检测等)来触发该引脚跳变。
4.4 模块内部结构图
4.5 数据帧
4.6寄存器地址
所有寄存器上电默认都是0x00,除了107号寄存器上电默认为0x40(睡眠),117号寄存器为0x68
五、软件模拟I2C读写MPU6050
实现I2C通信,读写寄存器,来操纵MPU6050
在程序中配置并操作SCL和SDA对应的端口即可
以下是编写程序时要注意的点
- 程序思路
软件I2C只需配置GPIO的读写函数即可
①把SCL和SDA都初始化为开漏输出模式,此模式下可以输入,输入时,先输出1,再直接输入数据寄存器即可
②把SCL和SDA置为高电平,此时I2C总线处于空闲状态
起始条件
确保I2C总线释放,先拉低SDA,再拉低SCL
终止条件
先拉低SDA,再释放SCL,SDA
发送一个字节(高位先行)
Byte & 0x80 相当于把 Byte 的最高位取出来,写1/0
每次定位,执行释放SCL,拉低SCL操作
接收一个字节(高位先行)
进来后,SCL为低电平,主机释放SDA,从机把数据位到SDA
此时主机释放SCL,用R_SDA读取
ReceiveAck
函数进来时,SCL低电平,主机释放SDA,防止从机干扰
同时从机把应答位放在SDA上,SCL高电平,主机读取应答位
SCL低电平,进入下一个时序单元。
有关【STM32】I2C通信—软件模拟就到这,希望对你有所帮助,感谢观看!
码文不易,留个赞再走吧~