当前位置: 首页 > news >正文

别再怕IIC时序了!用Verilog状态机清晰图解LM75/AT24C128的读写全过程

用Verilog状态机彻底解析IIC协议:从LM75温度读取到AT24C128存储操作实战

IIC(Inter-Integrated Circuit)总线是嵌入式系统中最常用的串行通信协议之一,但它的时序控制和状态跳转逻辑常常让开发者感到困惑。本文将用Verilog状态机的设计思路,带你彻底理解IIC协议的核心机制,并通过LM75温度传感器和AT24C128 EEPROM两个典型设备的操作实例,展示如何构建一个稳健可靠的IIC控制器。

1. IIC协议核心机制解析

IIC协议的精髓在于其简洁的两线制(SCL时钟线和SDA数据线)设计和严格定义的时序规范。要真正掌握IIC,必须理解以下几个关键概念:

基本信号类型

  • 起始条件(START):SCL为高电平时,SDA从高到低的跳变
  • 停止条件(STOP):SCL为高电平时,SDA从低到高的跳变
  • 数据有效性:SDA数据在SCL高电平期间必须保持稳定
  • 应答机制(ACK/NACK):每个字节传输后接收方必须发送应答信号

关键时序参数

参数描述典型值(100kHz)典型值(400kHz)
tSU;STA起始条件建立时间4.7μs0.6μs
tHD;STA起始条件保持时间4.0μs0.6μs
tSU;DAT数据建立时间250ns100ns
tHD;DAT数据保持时间0ns0ns
tSU;STO停止条件建立时间4.0μs0.6μs

注意:实际设计中应留有时序裕量,避免因信号传输延迟导致通信失败

2. Verilog状态机设计方法论

设计一个稳健的IIC控制器需要采用分层状态机架构,将复杂的通信过程分解为可管理的状态序列。

2.1 顶层状态设计

顶层状态控制整个通信流程:

parameter MAIN_IDLE = 'd20; // 空闲状态 parameter MAIN_STAR = 'd21; // 起始条件 parameter MAIN_DEV0 = 'd22; // 发送设备地址(写) parameter MAIN_ADDR = 'd23; // 发送内存地址 parameter MAIN_REST = 'd24; // 重复起始条件 parameter MAIN_DEV1 = 'd25; // 发送设备地址(读) parameter MAIN_R8BI = 'd26; // 读取数据字节 parameter MAIN_W8BI = 'd27; // 写入数据字节 parameter MAIN_STOP = 'd28; // 停止条件

2.2 底层比特级控制

每个顶层状态又细分为底层状态,精确控制每个时钟周期:

// 写数据状态序列 parameter W1BY_SCLL = 'd6; // SCL低电平期间准备数据 parameter W1BY_SCLH = 'd7; // SCL高电平期间保持数据 parameter W1AK_SCLL = 'd8; // 等待ACK的SCL低电平 parameter W1AK_SCLH = 'd9; // 采样ACK的SCL高电平 // 读数据状态序列 parameter R1BY_SCLL = 'd11; // SCL低电平期间释放SDA parameter R1BY_SCLH = 'd12; // SCL高电平期间采样数据 parameter R1AK_SCLL = 'd13; // 发送ACK的SCL低电平 parameter R1AK_SCLH = 'd14; // 发送ACK的SCL高电平

2.3 状态跳转逻辑示例

以下是写操作的状态跳转核心代码:

always @(posedge clk or posedge rst) begin if(rst) begin cur_state <= MAIN_IDLE; end else begin case(cur_state) MAIN_IDLE: if(req) cur_state <= MAIN_STAR; MAIN_STAR: if(down_ack) cur_state <= MAIN_DEV0; MAIN_DEV0: if(down_ack) cur_state <= (err_ack) ? MAIN_STOP : MAIN_ADDR; MAIN_ADDR: if(down_ack) cur_state <= (err_ack) ? MAIN_STOP : (wr || ADDR_NUM==0) ? MAIN_W8BI : MAIN_REST; // ...其他状态跳转逻辑 endcase end end

3. LM75温度传感器操作实战

LM75是一款广泛使用的数字温度传感器,通过IIC接口提供9位到12位的温度数据。

3.1 LM75关键特性

  • 温度测量范围:-55°C 到 +125°C
  • 精度:±2°C(-25°C 到 +100°C)
  • 温度寄存器格式:16位,高9位有效,LSB=0.125°C
  • 设备地址:固定部分1001xxx,可通过引脚配置低三位

寄存器映射

寄存器地址功能描述
0x00温度值(只读)
0x01配置寄存器
0x02超温阈值
0x03迟滞温度

3.2 读取温度值的状态机流程

  1. 发送设备地址(写模式)

    • 状态序列:MAIN_STAR → MAIN_DEV0
    • 设备地址:7'b1001xxx + 1'b0(写)
  2. 发送温度寄存器地址(0x00)

    • 状态序列:MAIN_ADDR → W1BY_SCLL → W1BY_SCLH (循环8次)
  3. 重复起始条件

    • 状态序列:MAIN_REST → START_SCLL → START_SCLH
  4. 发送设备地址(读模式)

    • 状态序列:MAIN_DEV1
    • 设备地址:7'b1001xxx + 1'b1(读)
  5. 读取温度数据

    • 状态序列:MAIN_R8BI → R1BY_SCLL → R1BY_SCLH (循环8次)
    • 最后发送NACK表示读取结束
  6. 停止条件

    • 状态序列:MAIN_STOP → STOP_SCLL → STOP_SCLH

提示:LM75的温度数据格式为补码形式,转换时需特别注意符号位处理

4. AT24C128 EEPROM操作详解

AT24C128是128Kbit(16K×8)的串行EEPROM,具有页写和顺序读功能。

4.1 设备特性与注意事项

  • 支持100kHz(1.8V)和400kHz(2.5V)两种速度
  • 页写模式:最多64字节/页
  • 写入周期时间:典型5ms
  • 设备地址:1010xxx,其中xxx由A2,A1,A0引脚决定

重要限制

  • 两次写入操作之间必须留有足够时间(通常5ms)
  • 单字节写入和页写入的时序要求不同
  • 超过页边界时会回卷到页首

4.2 写操作状态机设计

单字节写入的状态序列:

开始 → 设备地址(写) → 应答 → 高字节地址 → 应答 → 低字节地址 → 应答 → 数据字节 → 应答 → 停止

对应的Verilog状态跳转:

MAIN_STAR → MAIN_DEV0 → MAIN_ADDR → W1BY_SCLL → W1BY_SCLH → ... → MAIN_W8BI → W1BY_SCLL → W1BY_SCLH → MAIN_STOP

4.3 读操作特殊处理

顺序读操作需要特别注意"伪写入"阶段:

  1. 先以写模式发送内存地址
  2. 发送重复起始条件
  3. 切换为读模式并接收数据

状态序列示例:

开始 → 设备地址(写) → 应答 → 地址高字节 → 应答 → 地址低字节 → 应答 → 重复开始 → 设备地址(读) → 应答 → 读取数据(带ACK/NACK) → ... → 停止

5. 关键时序参数的Verilog实现

精确控制时序是IIC可靠通信的核心。以下是400kHz模式下的典型实现:

parameter tSYSCLK = 20; // 系统时钟周期20ns(50MHz) parameter tCLK = 4000/tSYSCLK; // SCL周期2500ns(400kHz) parameter tLOW = 2000/tSYSCLK; // SCL低电平时间1000ns parameter tHIGH = tCLK-tLOW; // SCL高电平时间1500ns parameter tHDDAT = 1000/tSYSCLK; // 数据保持时间 parameter tSUDAT = tLOW-tHDDAT; // 数据建立时间 // 时序控制计数器 always @(posedge clk or posedge rst) begin if(rst) delay_cnt <= 0; else if(state_change) delay_cnt <= 0; else delay_cnt <= delay_cnt + 1; end

总线释放时机

  • 主设备发送完最后一个ACK后,应在50ns内释放SDA
  • 从设备切换方向时,主设备应等待足够时间(通常300-400ns)
// 总线释放实现示例 R1AK_SCLL: begin if(delay_cnt==tHDDAT) begin sda_is_out <= 1; // 准备发送ACK/NACK sda_o <= (data_cnt==DATA_NUM); // 最后一个字节发NACK end end

在实际项目中调试IIC通信时,最常遇到的问题往往与时序裕量不足或总线竞争有关。特别是在多主设备系统中,必须严格遵循总线仲裁规则,确保不会出现两个设备同时驱动总线的情况。

http://www.cnnetsun.cn/news/2037916.html

相关文章:

  • GD32串口转RS485/422踩坑实录:115200波特率下数据乱码,我如何定位到IP核设计问题?
  • AI在网络安全中的实战应用与ROI优化策略
  • AI Agent:从“科幻概念“到“生活必需品“的进化之路
  • 从SIRAL高度计的三种模式说起:CryoSat-2如何成为海冰厚度测量的‘游戏规则改变者’
  • 【人生底稿・番外篇 09】足球青春篇:37岁老码农,藏在球场晚风里的整条青春长河
  • 浏览器扩展开发插件与内容脚本
  • 如何在30分钟内搭建企业级工作流系统:RuoYi-Flowable-Plus终极指南
  • Minimax算法在策略游戏中的实现与优化
  • 别再死记命令了!用一张图搞懂思科ASA5505防火墙的‘安全等级’与流量放行逻辑
  • 终极指南:3步快速备份微博到PDF,永久保存你的数字记忆
  • 你的1.54寸ST7789V2屏幕只显示单色?手把手教你玩转STM32的SPI驱动与显存管理
  • KEIL5编译报错‘Target not created’?别慌,手把手教你搞定‘ERROR: PUBLIC REFERS TO IGNORED SEGMENT’这个内存溢出老大难
  • 同轴线仿真性能优化:如何通过HFSS设置获得低于-30dB的反射系数?
  • 腾讯面试官问:Prompt、RAG、微调,什么时候分别值得上?
  • 如何用Guns框架快速搭建企业级多租户系统:从入门到实战的完整指南
  • 告别Python依赖:用纯C语言在STM32F4上复现LeNet-5(附完整代码)
  • Excalidraw-CN 未来展望:从 ReveZone 升级看白板技术演进
  • 识质存在修改器 风灵月影 支持最新版本
  • MySQL视图:虚拟表的实战技巧
  • 如何用AutoLegalityMod插件3分钟生成100%合法的宝可梦数据
  • Android 本地音乐播放(读取系统媒体库 + MediaPlayer)
  • RV1126视频采集避坑指南:RKMedia VI模块的5个关键配置项详解
  • 终极指南:如何用SketchUp STL插件轻松实现3D打印模型转换
  • 分钟搞懂深度学习AI:实操篇:ResNet
  • 【Excel提效 No.011】一句话搞定多工作表纵向合并
  • 大模型RAG (二)
  • 告别Excel配置表:在Unity中搭建Luban+Jenkins的自动化配置管线
  • UE5Varest发送https请求发不出去,收不到任何回复
  • 避开这些坑!STM32G474读写FLASH时,关于保护、对齐和中断的避坑指南
  • 【音视频 | ALSA】从内核到应用:深入解析ALSA框架的层次结构与核心组件