理论学习:
I2C通讯协议,简单双向,二线制同步串行总线,只需要两根线即可在连接总线上的器件之间传输信息。
广泛用于数据采集领域的串行AD,图像处理领域的摄像头配置。由于I2C协议占用引脚特别少,硬件实现简单,可扩展性强,被广泛用于在系统内多个集成电路之间的通讯。
I2C物理层:
特点:
1 支持多个通信主机和从机
2 两线制 I2C_SCL 串行时钟线,用于同步通讯数据,I2C_SDA: 双向串行数据线,传输通讯数据。
3 总机通过地址 实现与不同设备的通讯。
4 空闲状态为高阻态,因为接了上拉电阻
5 多个主机同时使用总线,通过 仲裁 确定哪个设备使用总线
6 标准模式100kb/s 快速模式400kb/s 高速3.4Mb/s
I2C协议层:
第一个状态为 总线空闲状态
第二个状态为 起始信号
第三个状态为 数据读写状态
第四个状态 停止信号
SDA跳转到高电平 回到总线空闲状态
每次只写入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字节
页写操作一次写的不能超过 存储容量
数据读操作:
随机读:
随即为地址随机, 高字节在前低位在后,高位在前,低位在后。
起始信号给从机 器件地址+读写控制位(0数据写入) 从机回应ack 写入地址 ack 再次发送起始信号 发送控制指令( 器件地址+读写控制位(1数据读取)) ack 接收数据data 主机给从机发送一个周期高电平1bit(无应答信号) 主机发送stop信号。
顺序读: 数据量增多
读取数据 :
读一个数据 ack 读第二个 ack ... 无应答信号 stop
24C64 13bit的地址。 EEPROM只设置了高四位地址 A2A1A0 自己设置的。
实现数码管显示:动态显示模块
顶层模块: I2C_eeprom
I2C_rw_data: 读写数据控制
I2C_ctrl: 控制模块
I2C——ctrl
输入信号:
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
数据读取:
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
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状态