第16节 第二步模拟IIC之——PP推免和OD开漏模式对比_哔哩哔哩_bilibili

一、I2C协议简介

实验板:蓝桥杯嵌入式,STM32G4RBT6

  • I2C是一种简单的双向两线制总线协议标准,支持同步串行半双工通讯。
  • SDA:双向串行数据总线,只能一位一位的发送数据。
  • SCL:串行时钟线,用于数据收发同步
  • **半双工通信**:可以实现双向的通信,但不能在两个方向上同时进行,必须交替进行,

二、I2C物理层

设备间的常用连接方式

  • 在一个I2C通信总线中,可以连接多个I2C通讯设备。支持多个通讯主机多个通信从机
image-20240920153511997

三、I2C协议层

主机写数据到从机

image-20240920154403849
  • 在I2C总线上,每个设备的地址都是唯一的,当主机广播的地址与某个设备地址相同时,设备会自动匹配,匹配成功后,这个设备就被选中了,没被选中的设备将会忽略之后的数据信号
  • 主机发送完数据,从机应答了,主机照样可以直接发送停止信号终止通讯。
  • 从机地址可以是7位或者10位,在地址位之后,是读写的权限的选择位,0表示写权限,1表示读权限。
  • I2C规定,通信时的时钟,起始信号,停止信号只能由主机产生

主机从从机读取数据

image-20240920160821303
  • 在接受到任何数据时,无论时主机还是从机,都要做出应答信号(我还要数据)或非应答信号(我不要数据了)

读写数据混合格式

8d6a0670-ca9e-473b-b625-d6da0fab7cee
  • 第一次通讯是确定读写从机设备内部寄存器或存储器的地址
  • 第二次则是读或写上一次确定内部寄存器或存储器的地址上面的数据。

3.1 空闲状态

I2C总线的SDA和SCL两条信号线同时处于高电平时,则为总线空闲状态,所有挂载在总线上的设备都输出高阻态(相当于断开与总线的连接),两条总线被上拉电阻的把电平拉高。

3.2 起始信号与停止信号

image-20240920180358340

起始信号:当SCL线在高电平期间 SDA 线高电平向低电平切换
停止信号:当SCL线在高电平期间 SDA 线低电平向高电平切换

传输数据:当SCL线在高电平期间SDA 线电平状态保持不变,否则会误判为起始或停止

起始信号和停止信号只能由主机产生

3.3 数据有效性

021ca9d7-3767-4b9b-a25b-8905ab64172e image-20240920182422762
  • SDA数据线在SCL的每个时钟周期(时钟脉冲)传输一位数据
  • SCL为高电平期间:SDA表示数据有效,此时SDA的电平要稳定,SDA的高低电平代表数据1或0
  • SCL为低电平时:SDA的数据无效,一般在这个时候SDA进行电平转化,为下次数据传输做准备
  • 数据和地址进行传输时,==先传输高位==,每次传输的字节不受限制

3.4 地址及数据方向

image-20240920190314548
  • 读数据方向时,主机会==释放对 SDA 信号线的控制==,由==从机控制 SDA 信号线==(向主机发送数据),主机接收信号
  • 写数据方向时,SDA 由主机控制(向从机发送数据),从机接收信号

3.5 应答和非应答信号

I2C 的数据和地址传输都带响应当数据接收端(无论主从机)接收到 I2C 传输的一个字节数据或地址后:

  • 若希望对方继续发送数据,则向对方发送“应答(ACK)”信号(低电平)

  • 若希望对方结束数据传输,则向对方发送“非应答(NACK)”信号(高电平)发送方接收到该信号后会产生一个停止信号,结束信号传输。

  • 在一个字节传输的8个时钟后的第9个时钟期间,接收器必须回送一个应答位(ACK)或者是非应答位(NACK)给发送器 。

  • 在第 9 个时钟时,数据发送端会释放 SDA 的控制权,由数据接收端控制 SDA,给发送端传输应答或非应答信号

5a15817b-bf12-4c4d-b3cd-c0ad501b5e5e image-20240920222354354

3.6 写入一个字节时序

image-20240920222442639

3.7 读出一个字节时序

image-20240920222451423

3.8 单次写入多个字节时序

image-20240920222600643

3.9 单次读出多个字节时序

image-20240920222553835

四、软件IIC

4.1 开始停止信号

五、硬件IIC

六、 实验

实验:使用STM32F407作实验平台,将数据写入AT24C02,并读取出来

image-20250427144311918

ACK后面SDA变高,是从机停止发出低电平SDA线出现短暂高电平

1. Driver_i2c.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#ifndef __DRIVER_IIC_H 
#define __DRIVER_IIC_H

#include "stm32f10x.h"

#define ACK 0
#define NACK 1

#define SCL_HIGH (GPIOB->ODR |= GPIO_ODR_ODR10)
#define SCL_LOW (GPIOB->ODR &= ~GPIO_ODR_ODR10)

#define SDA_HIGH (GPIOB->ODR |= GPIO_ODR_ODR11)
#define SDA_LOW (GPIOB->ODR &= ~GPIO_ODR_ODR11)

#define READ_SDA (GPIOB->IDR & GPIO_IDR_IDR11)


/* 引脚初始化 */
void Driver_I2C_Init(void);

/* 开始信号 */
void Driver_I2C_Start(void);

/* 停止信号 */
void Driver_I2C2_Stop(void);

/* 应答信号 */
void Driver_I2C_Ack(void);

/* 非应答信号 */
void Driver_I2C_NAck(void);

/* 等待接收方的应答 */
unsigned char Driver_I2C2_WaitAck(void);

/* 发送一个字节的数据 */
void Driver_I2C_SendByte(unsigned char byte);

/* 接收一个字节的数据 */
unsigned char Driver_I2C_ReadByte(void);

#endif

2. Driver_i2c.c

1

3. main.c

1

image-20240921013215257 image-20240921013424465