I2C .1

208 阅读6分钟

理论学习:

I2C通讯协议,简单双向,二线制同步串行总线,只需要两根线即可在连接总线上的器件之间传输信息。

广泛用于数据采集领域的串行AD,图像处理领域的摄像头配置。由于I2C协议占用引脚特别少,硬件实现简单,可扩展性强,被广泛用于在系统内多个集成电路之间的通讯。

I2C物理层:

image.png 特点:

1 支持多个通信主机和从机

2 两线制 I2C_SCL 串行时钟线,用于同步通讯数据,I2C_SDA: 双向串行数据线,传输通讯数据。

3 总机通过地址 实现与不同设备的通讯。

4 空闲状态为高阻态,因为接了上拉电阻

5 多个主机同时使用总线,通过 仲裁 确定哪个设备使用总线

6 标准模式100kb/s 快速模式400kb/s 高速3.4Mb/s

I2C协议层:

image.png

第一个状态为 总线空闲状态

第二个状态为 起始信号

第三个状态为 数据读写状态

第四个状态 停止信号

SDA跳转到高电平 回到总线空闲状态 image.png

每次只写入1bit,8位有效数据位,SDA保持一个时钟周期的低电平,ACK应答信号。

器件地址:

器件地址,位宽为7位,0b5640 7bit都被设置了。eeprom只被设置了高四位。

最低为读写控制位 0 为写入,1为读出。控制命令发送到总线上,所有从机都会接收到,比较地址后,回应应答信号。两者完成数据交互。

存储空间 有需要单字节的也有需要两字节的 完成存储空间的寻址。

单字节写操作:

SDA 主机给从机发送 起始信号 器件地址 读写操作(0 写操作)

EEPROM 收到后 器件地址进行比较,回复应答信号,主机收到ack后,建立连接,先发送高字节再发送低字节 , 每发送一个地址从机回应一个ack,然后开始数据data写入,然后ack,最后主机发送stop信号。

起始信号 器件地址+读写操作 ,从机比较器件地址后发送ack应答信号,主机和从机建立连接。 主机发送存储空间地址给从机先高位再低位,如果有两个字节地址,先发送高字节地址,再发送低字节地址,每次发送完成发送ack信号给主机,再发送data数据,ack后,主机发送stop。

页写操作:

和单字节操作类似。

器件地址分为两字节的和单字节的。

起始信号 器件地址 读写操作 ack 器件地址 数据n ack 数据n-1 ack... stop

24C64 一次不能超过32Byte数据。单页存储32字节

页写操作一次写的不能超过 存储容量

数据读操作:

image.png

随机读:

随即为地址随机, 高字节在前低位在后,高位在前,低位在后。

起始信号给从机 器件地址+读写控制位(0数据写入) 从机回应ack 写入地址 ack 再次发送起始信号 发送控制指令( 器件地址+读写控制位(1数据读取)) ack 接收数据data 主机给从机发送一个周期高电平1bit(无应答信号) 主机发送stop信号。

顺序读: 数据量增多

读取数据 :

读一个数据 ack 读第二个 ack ... 无应答信号 stop

24C64 13bit的地址。 EEPROM只设置了高四位地址 A2A1A0 自己设置的。

实现数码管显示:动态显示模块

顶层模块: I2C_eeprom

I2C_rw_data: 读写数据控制

I2C_ctrl: 控制模块

image.png

I2C——ctrl image.png

输入信号:

wr_en rd_en

i2c_start addr_num byte_addr wr_data

当wr_en和i2c_start有效 写操作

当 rd_en和i2c_start有效 读操作

给模块输入addr_num 高电平两字节 写入数据存储地址16位,低电平写入数据存储地址byte_addr低八位。

输出信号:

i2c_clk 位本模块工作时钟,为系统时钟分频得到1MHZ 为i2c_scl的四倍

i2c_end 高电平有效时候,为读写完成单字节

rd_data

i2c_scl i2c_sda : 传输给eeprom存储芯片。

本次操作都采用单字节读写操作。

状态机实现状态转移:

IDLE

读写开始信号有效时,跳转

START

SEND_D_A 控制指令写入完成

ACK_1 响应信号有效,存储地址为两个字节

SEND_B_H 高八位地址写入完成

ACK_2 响应信号有效

SEND_B_L 第八位地址吸入完成

ACK_3 响应信号有效 写使能信号有效

WR_DATA 单字节数据写入完成

ACK_4 响应信号有效

STOP

image.png

数据读取:

IDLE

读写开始信号有效时,跳转

START

SEND_D_A 控制指令写入完成

ACK_1 响应信号有效,存储地址为两个字节

SEND_B_H 高八位地址写入完成

ACK_2 响应信号有效

SEND_B_L 第八位地址吸入完成

ACK_3 响应信号有效 读使能信号有效

START2

SEND_R_A 发送读地址

ACK_5

RD_DATA 单字节数据读取完毕

N_ACK 无响应状态

STOP

分析:

i2c_clk : easy

i2c_clk也作为I2C_rw_data控制时钟 1MHZ

首先要生成,通过分频实现。

cnt_clk ,50MHZ通过50次分频 达到1MHZ。 分频计数器

i2c_start

image.png

wr_en

拉高后一直保持高电平

byte_addr

由I2C_rw_data生成,

wr_data

addr_num

低电平表示单字节

高电平表示两字节

state定义状态变量

state:

IDLE START (4个i2c-clk周期,因为为i2c_scl的一个周期)
cnt_i2c_clk : 计数0123

cnt_i2c_clk_en: 控制循环计数

cnt_bit:控制字 01234567 cnt_i2c_clk计数到3 ,cnt_bit记为1,并且 有应答信号时候 cnt_bit 保持为0,发送八位地址, 。。。。

i2c_scl 串行同步时钟

初始因为上拉电阻被拉高,周期为4倍 i2c_clk,通过cnt_i2c_clk来实现控制。

i2c_SDA 串行数据

开始信号下,被拉低,随后保持低电平,出了开始信号拉低,器件地址+读写控制0表示数据写入,完成了控制信号写入。

响应信号有效,发送存储地址高八位,响应信号有效低电平,发送存储地址低八位,响应信号有效,写入数据,响应信号有效,发送停止信号,stop 保持高电平。

sda_out

当i2c_sda做输出 和sda_out相同

sda_en

加使能信号

当sda作为输入作为低电平,当sda作为输出作为高电平。

ack响应信号的提取

初始为高电平,作为状态机跳转

sda_in

将sda信号给sda

i2c_end

结束信号,一个字节写入后,拉高一个时钟周期,表示一次读写完成。

数据读取的部分和写入类似

rd_en

状态机state跳转时候,

读使能信号有效后,跳转到start2状态下 再次发送控制字节 为读控制 响应信号有效后 跳转到 读取数据状态 无响应状态 STOP状态