开发环境
- 软件:Quartus II 64-Bit
- 开发板及芯片型号:至芯 EP4CE6E22C8N 1.2V
协议核心概述
1. 物理层特性
- 双线制:仅需 SCL(时钟线)和 SDA(数据线)两根线,均需外接上拉电阻,空闲时保持高电平。
- 多主多从:支持多个主机和从机,通过设备地址(通常 7 位)区分不同外设,地址后接 1 位读写标志位(0 写 / 1 读)。
- 半双工通信:数据线 SDA 同一时刻只能单向传输,由主机控制时序。
2. 关键时序状态
- 起始条件(Start):SCL 高电平时,SDA 由高→低跳变,标志通信开始。
- 停止条件(Stop):SCL 高电平时,SDA 由低→高跳变,标志通信结束。
- 数据传输:SCL 低电平时更新 SDA 数据,SCL 高电平时保持稳定,数据按高位优先传输。
- 应答机制(ACK/NACK):每传输 8 位数据后,接收方在第 9 个 SCL 周期拉低 SDA(ACK)或保持高电平(NACK)。
3. 状态机驱动
通过状态机划分 IIC 操作阶段,典型状态包括:空闲态(IDLE)、起始态(START)、写数据(WR_DATA)、读数据(RD_DATA)、应答(ACK)、停止态(STOP)。
4. 时钟分频与时序控制
将 FPGA 系统时钟(如 50MHz)分频至 IIC 速率(如 100kHz 或 400kHz),需计算分频参数。在 SCL 低电平中点更新 SDA 数据,确保时序稳定。
示例状态机跳转逻辑:
case(state)
IDLE: if(读写请求) next_state <= START;
START: next_state <= WR_DATA;
WR_DATA:next_state <= ACK;
ACK: if(操作类型) next_state <= STOP else next_state <= RD_DATA;
STOP: next_state <= IDLE;
endcase
- 写操作:主机依次发送设备地址(+ 写标志)、寄存器地址、数据,每字节后检测 ACK。
- 读操作:主机发送设备地址(+ 写标志)→寄存器地址→重新发送起始信号→设备地址(+ 读标志)→接收数据并发送 ACK/NACK。
基础知识
1. I2C(IIC)通讯协议
I2C 通讯协议(Inter-Integrated Circuit)是由 Philips 公司开发的一种简单、双向二线同步串行总线,只需要两根线就可以在连接于总线上的器件之间传送信息。
优点:
- 多设备支持:每个设备都有唯一的地址。
- 简单:协议相对简单,易于实现和调试。
- 低功耗:空闲状态下器件可进入低功耗模式。
- 仲裁:防止多个主机同时使用总线时的冲突。
- 速度:标准模式 100kb/s,快速模式 400kb/s。
缺点:
- 速度较慢:适用于低速设备。
- 受限制:总线长度和设备数量受限。
- 冲突:需要额外的冲突检测和处理机制。
**应用案例:**小型传感器、LCD 屏幕、RTC(实时时钟)模块等。
2. I2C 物理层
- I2C_SCL:串行时钟线,用于同步通讯数据。
- I2C_SDA:双向串行数据线,传输通讯数据。
3. I2C 协议层
包含 4 个状态:总线空闲状态、起始信号、数据读写状态、停止信号。
在 SCL 为高电平的时候进行数据的写入,低电平的时候进行数据的更新。当从机设备正确接受到信号时,会把 SDA 数据线拉低,称为响应位(ACK)。
关于器件的地址: 器件地址被定义为 7Bit 的数据,厂商出厂设置。部分引脚允许用户自行设置。最后一位为读写控制位,0 表示写入,1 表示读取。
4. 数据传输流程
- 地址分配:每个设备有唯一地址。
- 开始条件:主机发送特定电平变化。
- 发送地址:发送 7 位地址 + R/W 位。
- 确认应答:目标设备拉低 SDA 表示接收成功。
- 数据传输:主机发送或从机发送数据。
- 非应答(NACK):无法接收时不拉低 SDA。
- 停止条件:主机发送停止信号结束传输。
- 多主机环境:使用仲裁机制决定控制权。
IIC 驱动 7Pin 0.96 寸 OLED 显示屏实例
1. 硬件修改
默认使用 SPI 协议驱动,改为 IIC 协议需修改电路:
- 将背面 R3 电阻移动到 R4 的位置。
- 短接 R8 电阻。
改造后需连接 7 个管脚:
- CS:接地。
- DC:选择 IIC 通信地址;接地时为 0x78,接高电平时为 0x7A(测试程序用 0x78)。
- RES:复位脚。方案包括接电源正(不稳定)、接开发板复位脚、IO 脚控制(拉低延迟 200ms 后拉高)或 RC 复位电路。
- D0:IIC 时钟线(SCK)。
- D1:IIC 数据线(SDA)。
- GND:接地。
- VDD:电源线。
2. OLED 刷新方式
- 页地址模式:一页写完自动换页。
- 水平地址模式:一列写完自动换列。
- 垂直地址模式:类似水平模式。
3. OLED 关键命令介绍
- 0xAE/0xAF:关闭/开启显示。
- 0x20-0x22:数据存储模式(默认为 0x22)。
- 0x00-0x0F:列地址低四位。
- 0x10-0x1F:列地址高四位。
- 0xB0-0xB7:设置 Page。
IIC 数据格式:OLED 地址 + 命令/数据 + 值。
- OLED 地址:从机地址(如 0x78)。
- 命令/数据:0x00 表示命令,0x40 表示数据。
- 值:具体指令或数据。
初始化代码示例:
always@(*) begin
case(Init_index)
'd0: Init_data_reg <= {8'h78, 8'h00, 8'hAE}; // 关闭显示
'd1: Init_data_reg <= {8'h78, 8'h00, 8'h00};
// ... 其他初始化命令
default: Init_data_reg <= {8'h78, 8'h00, 8'hAE};
endcase
end
IIC 驱动 4Pin OLED 显示器显示 DHT11 温湿度数据
1. 字模设计
需根据字体大小(如 1616 数字字母,816 汉字)生成对应的点阵数据。
2. 程序设计
顶层模块
module main(
input sys_clk,
input rst_n,
inout dht11,
output OLED_SCL,
inout OLED_SDA
);
wire dht11_done;
reg dht11_req;
wire[7:0] tempH, tempL, humidityH, humidityL;
// ... 实例化 DHT11 和 OLED_Top 模块
endmodule
IIC_Driver 模块
实现了 IIC 通信的状态机,包含空闲、起始、写数据、读数据、应答、停止等状态。支持分频计数、字节计数及 ACK/NACK 检测。
DHT11 模块
负责采集温湿度数据,包含时序控制、数据解析及校验逻辑。
OLED 相关模块
- OLED_FontData:存储字模数据。
- OLED_Init:初始化序列控制。
- OLED_Refresh:全屏刷新。
- OLED_ShowData:显示数值。
- OLED_ShowFont:显示字符。
- OLED_Top:顶层控制状态机。
以上模块协同工作,实现 FPGA 通过 IIC 协议驱动 OLED 屏幕,并实时显示 DHT11 采集的温湿度数据。

