基于FPGA的IIC通讯-MASTER发送篇

四、IIC通讯

(一)、概述

        本章节进入到IIC通讯篇章,本篇章开始就得开始付费啦,请关注的各位理解,因为代码每个人的想法不同书写的个人版权,请大家注意版权问题,IIC通讯主要分为两大部分,一个是主机读和主机写,另一个是从机接收,IIC具体的原理这里就不细讲,主要是依据IIC时序进行代码编写,本节主要是介绍IIC主机写程序,依据的是SMBUS2.0协议,它与IIC的不同在于存在IIC_SCL时钟的约束,即SMBUS是IIC的一个子集。

(二)、时序介绍

        了解IIC协议的小伙伴们因该都知道,IIC主要有几个重要的信号,分别是IIC读写开始信号,一个是应答信号,另一个是IIC停止信号,就以开始信号为例,什么时候表示IIC开始读写?在原理上我们知道IIC-SCL为高电平时,IIC-SDA从高电平转为低电平表示读写开始,但是需要保持多久才能时开始信号?

        这就涉及到建立时间与保持时间的概念了,如上图TBUF和THD_STA,它的意思是开始信号条件前需要保持最少TBUF的时间,并且IIC-SDA下降后需要等待THD_STA时间IIC-SCL才能从高电平变为低电平;从表中可以看到Min和Max字样,后面跟随着Units表示单位,所以可以知道开始信号条件前需要保持最少TBUF == 4.7us的时间,并且IIC-SDA下降后需要等待THD_STA == 4.0us的时间IIC-SCL才能从高电平变为低电平,这样就能表示IIC传输开始。

        又因为IIC的传输速率是10K到400Khz,但是SMBUS的传输速率是10K到100Khz,那我们产生的IIC-SCL就得符合上述标准;但是我们的IIC-SCL是要一直产生的吗?答案是不需要一直产生,因为IIC是两线协议,可能这两根线并不是挂载着一个主机一个从机的情况,可能有多个主机和多个从机的情况,所以我们并不需要一直的发送IIC-SCL;那么问题来了,如何保证时序要求在范围内,其实只要以及使用时钟的分频出所需要速率即可。

        在数据端也是需要遵循建立时间和保持时间,但是可以看到它的时间单位是在纳秒级别的,在变化速率为微妙级的情况下,我是进行忽略处理的;好的,现在话不多说,我的IIC-MASTER-WRITE的代码支持什么功能呢?一个是支持是否采用寄存器地址,另一个是支持连续写,可以任意涉及连续写的次数,代码如下:

// ********************************************************
// Copyright: CSDN account juningc
// The email address is: [email protected]
// Unauthorized copying is prohibited. If you need to use it, please contact the author
// All interpretation rights belong to the copyright author
// ********************************************************
module iic_write_master #
(
   parameter               DWID       = 8       ,
   parameter               UCNT       = 25      ,
   parameter               BUILD_TIME = 5       ,  //us
   parameter               HOLD_TIME  = 4          //us
)
(
   input                   clk_sys              ,
   input                   rst_sys              ,
   //
   input                   waddr_mode           , // 0:使用寄存器地址  1:不适用地址
   input                   write_dena           ,
   input      [6:0]        slave_addr           ,
   input      [7:0]        regis_addr           ,
   input      [DWID-1:0]   write_data           ,
   input      [3:0]        write_numb           , // 连续写次数,理论上可以写N个Byte,但是最好限制在4个以下
   output reg              bus_busy             , // 总线繁忙状态
   //
   input                   i2c_scl_m_i          ,
   output                  i2c_scl_m_o          ,
   out
### FPGA实现IIC Master的代码示例 以下是基于Verilog语言的一个简单IIC Master模块实现代码。该代码实现了基本的IIC通信功能,包括启动条件、停止条件、发送字节和接收应答等功能。 ```verilog module iic_master ( input wire clk, // 主时钟 input wire reset_n, // 复位信号,低电平有效 output reg sda, // 数据线SDA output reg scl, // 时钟线SCL input wire start_iic, // 启动IIC传输请求 input wire [7:0] data_out,// 要发送的数据 output reg ack_received, // 接收到ACK的状态标志 output reg busy // 总线忙状态指示 ); parameter IDLE = 2'b00; parameter START = 2'b01; parameter SEND_BYTE = 2'b10; parameter STOP = 2'b11; reg [1:0] state_reg, state_next; // 状态寄存器 reg [3:0] bit_count_reg, bit_count_next; // 计数器用于跟踪当前处理的比特位置 reg [7:0] byte_reg, byte_next; // 当前要发送的字节缓存 reg sda_reg, sda_next; // SDA内部寄存器 reg scl_reg, scl_next; // SCL内部寄存器 // 默认初始化 always @(posedge clk or negedge reset_n) begin if (!reset_n) begin state_reg <= IDLE; bit_count_reg <= 4'd0; byte_reg <= 8'h00; sda_reg <= 1'b1; scl_reg <= 1'b1; ack_received <= 1'b0; busy <= 1'b0; end else begin state_reg <= state_next; bit_count_reg <= bit_count_next; byte_reg <= byte_next; sda_reg <= sda_next; scl_reg <= scl_next; ack_received <= (state_reg == STOP && !scl_reg); busy <= !(state_reg == IDLE || state_reg == STOP); end end // 下一状态逻辑 always @(*) begin case(state_reg) IDLE: begin if(start_iic) begin state_next = START; bit_count_next = 4'd7; byte_next = data_out; sda_next = 1'b0; // 开始条件:拉低SDA scl_next = 1'b1; end else begin state_next = IDLE; bit_count_next = bit_count_reg; byte_next = byte_reg; sda_next = 1'b1; scl_next = 1'b1; end end START: begin state_next = SEND_BYTE; bit_count_next = bit_count_reg; byte_next = byte_reg; sda_next = sda_reg; scl_next = 1'b0; // 结束开始条件:释放SDA并保持SCL高 end SEND_BYTE: begin if(bit_count_reg >= 0) begin state_next = SEND_BYTE; bit_count_next = bit_count_reg - 1; byte_next = {byte_reg[6:0], 1'b0}; sda_next = byte_reg[7]; scl_next = ~scl_reg; // 切换SCL高低电平完成一位数据传输 end else begin state_next = STOP; bit_count_next = 4'd0; byte_next = 8'h00; sda_next = 1'b1; // 准备结束条件 scl_next = 1'b1; end end STOP: begin state_next = IDLE; bit_count_next = 4'd0; byte_next = 8'h00; sda_next = 1'b1; // 停止条件:先拉高SDA再拉高SCL scl_next = 1'b1; end default: begin state_next = IDLE; bit_count_next = 4'd0; byte_next = 8'h00; sda_next = 1'b1; scl_next = 1'b1; end endcase end assign sda = sda_reg; assign scl = scl_reg; endmodule ``` 此代码展示了如何通过有限状态机(FSM)来管理IIC协议中的各种操作阶段[^1]。它还涉及到了物理层的设计细节,例如SDA和SCL信号的具体驱动方法[^2]。 #### 关键点说明 - **FSM结构**:采用了一个简单的四态有限状态机(IDLE, START, SEND_BYTE, STOP),用来控制整个IIC事务流程。 - **同步逻辑**:所有的寄存器更新都在`clk`上升沿触发,并受`reset_n`复位信号影响。 - **异步事件响应**:当检测到`start_iic`信号激活时,立即进入START状态发起新的IIC事务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值