iic通信协议是什么

时间:2024-04-30
  I2C(Inter-Integrated Circuit)是一种串行通信协议,用于在集成电路之间进行通信。它是由飞利浦(现在的恩智浦半导体)开发的,并广泛应用于各种电子设备和系统中。I2C通信协议具有以下特点:
  双线制: I2C协议使用两根线进行通信,即数据线(SDA)和时钟线(SCL)。
  主从结构: 在I2C通信中,通常存在一个主设备(Master)和一个或多个从设备(Slave)。主设备负责发起通信和控制总线,而从设备则被动响应主设备的指令。
  地址机制: 每个从设备都有一个的7位地址,用于主设备识别和选择特定的从设备进行通信。
  同步传输: 通信是同步的,由时钟线(SCL)上的时钟信号来驱动数据传输。
  起始和停止条件: 通信的起始和停止由主设备发出的特殊条件来标识,即起始条件(Start)和停止条件(Stop)。

  数据传输: 数据传输通过数据线(SDA)进行,在时钟信号的控制下,每个数据字节都由8位数据和一个确认位(ACK)组成。

  1.开始信号——在SCLK的高电平器件,拉低SDA的信号(由1 变为0)。
  2.控制字节——即器件地址,就是你操作那一块EEPROM。
  3.ACK信号——由从机发出,主机为接收,所以在此阶段,sda_link必须置为0,即为读取这个应答信号,所以在SCLK的高点平期间。
  4.字节地址——即某一块EEPROM里面的哪一个地址。
  5.ACK信号——与上述相同。
  6.数据信号——即你往某个地址里面写入的8位数据。
  7.ACK信号——上述相同。
  8.结束信号——在SCLK的高电平期间,拉高SDA信号,表示通信结束。
  再来看读的时序:
  由上图可看出读时序的前面处理方式与写相同,不同的时在第三个ACK信号来了之后,如果是读,那么会又有一个起始信号,紧接着读器件地址,然后应答,再然后读数据,再然后在SCLK的低电平期间发送一个NO ACK信号,要记住这个信号由主机发出,然后紧接着一个结束信号。
  由上述读写时序我们可知,通信的起始均在SCLK的高电平期间发生跳变,这就据定了我们其他信号跳变均在SCLK的下降沿,SCLK高电平期间数据稳定,适用于读(即低电平改变数据,高电平采集数据)。
  具体过程如下:
  首先板子上电来个初始化需要来个延时,具体多少用计数器自己搞定。
  代码如下:
  reg [6:0] hadware_initial_delay;
  wire hadware_initial_delay_done;
  always@(posedge clk or negedge rst_n)
  if(!rst_n)
  hadware_initial_delay《=7’d0;
  else
  if(hadware_initial_delay《=7’d49)
  hadware_initial_delay《=hadware_initial_delay+1;else
  hadware_initial_delay《=hadware_initial_delay;assign hadware_initial_delay_done=(hadware_initial_delay==7’d50)?1’b1:1’b0;OK,我们要知道IIC的速率一般就几百KH而我们的系统时钟为50M,所以需要分频:
  代码如下:
  reg [8:0] sclk_cnt;
  always@(posedge clk or negedge rst_n)
  if(!rst_n)
  sclk_cnt《=9’d0;
  else
  if(hadware_initial_delay_done)
  begin
  if(sclk_cnt《9’d499)
  sclk_cnt《=sclk_cnt+1;
  else
  sclk_cnt《=0;
  end
  assign sclk=(sclk_cnt《=9’d249)?1’b1:1’b0;OK,我们知道SCLK高电平期间采集数据,低电平期间改变数据,那么当然,这个“期间”肯定时时钟沿中间啦,毕竟更容易满足建立时间与保持时间,很稳定的。
  具体代码如下:
  wire sclk_posedge_middle=(sclk_cnt==9’d124)?1’b1:1’b0;wire sclk_negedge_middle=(sclk_cnt==9’d374)?1’b1:1’b0;OK,读写定义了那么多个过程,当然需要状态机来搞定啦,定义变量如下:
  parameter IDLE = 4’d0 ;
  parameter START1 = 4’d1 ;
  parameter ADD1 = 4’d2 ;
  parameter ACK1 = 4’d3 ;
  parameter ADD2 = 4’d4 ;
  parameter ACK2 = 4’d5 ;
  parameter DATA = 4’d6 ;
  parameter ACK3 = 4’d7 ;
  parameter STOP1 = 4’d8 ;
  parameter START2 = 4’d9 ;
  parameter ADD3 = 4’d10;
  parameter ACK4 = 4’d11;
  parameter DATA_READ = 4’d12;
  parameter NO_ACK = 4’d13;
  parameter STOP2 = 4’d14;
  OK,再来个宏定义,假设写入是这几个地址,这几个数据。
  define DEVICE_READ 8‘b1010_0001
  define DEVICE_WRITE 8’b1010_0000
  define WRITE_DATA 8’b0001_0001
  define BYTE_ADDR 8’b0000_0011
  SDA双向端口,这个记住,一般这样搞;
  reg sda_link;
  reg sda_out_r;
  assign sda=sda_link?sda_out_r:1’bz;
  当作为输出时,对吧,使sda_link拉高,作为输入时,输入高阻。
  各过程如下:
  reg [3:0] current_state;
  //reg [3:0] next_state;
  reg [7:0] db_r;
  reg [3:0] num;
  reg [7:0] data_out_reg;
  always@(posedge clk or negedge rst_n)
  if(!rst_n)
  begin
  sda_link《=0;
  db_r《=0;
  num《=0;
  current_state《=IDLE;
  sda_out_r《=0;
  data_out_reg《=8’b0;
  end
  else
  begin
  case(current_state)
  IDLE:begin
  sda_out_r《=1;
  sda_link《=1;
  if(!sw1_r||!sw2_r)
  current_state《=START1;
  else
  current_state《=IDLE;
  end
  START1:if(sclk_posedge_middle)
  begin
  sda_out_r《=0;
  db_r《=`DEVICE_WRITE;
  current_state《=ADD1;
  end
  else
  current_state《=START1;
  ADD1 :
  if(sclk_negedge_middle)
  begin
  if(num==4‘d8)
  begin
  sda_link《=0;
  num《=0;
  current_state《=ACK1;
  sda_out_r《=1;
  end
  else
  begin
  current_state《=ADD1;
  sda_out_r《=db_r[7-num];
  num《=num+1;
  end
  end
  else
  current_state《=ADD1;
  ACK1:
  if(sclk_posedge_middle)
  // begin
  // if(!sda)
  // begin
  begin // */current_state《=ADD2;
  db_r《=`BYTE_ADDR;
  end
  else
  current_state《=ACK1;
  ADD2:begin
  sda_link《=1;
  if(sclk_negedge_middle)begin
  if(num==4’d8)
  begin
  sda_link《=0;
  current_state《=ACK2;
  num《=4‘d0;
  sda_out_r《=1;
  end
  else
  begin
  num《=num+1;
  current_state《=ADD2;
  sda_out_r《=db_r[7-num];
  end
  end
  else
  current_state《=ADD2;
  end
  ACK2:
  if(sclk_posedge_middle)
  ////begin
  //if(!sda)
  begin
  begin
  if(!sw1_r)
  begin
  db_r《=`WRITE_DATA;
  current_state《=DATA;
  end
  else
  if(!sw2_r)
  begin
  current_state《=START2;
  sda_out_r《=1;
  end
  end
  else
  current_state《=ACK2;
  DATA: begin
  sda_link《=1;
  if(sclk_negedge_middle)
  begin
  if(num==4’d8)
  begin
  num《=4‘d0;
  current_state《=ACK3;
  sda_out_r《=1;
  sda_link《=0;
  end
  else
  begin
  num《=num+1;
  current_state《=DATA;
  sda_out_r《=db_r[7-num];
  end
  end
  else
  current_state《=DATA;
  end
  ACK3: if(sclk_posedge_middle)
  // begin
  // if(!sda)
  current_state《=STOP1;
  // end
  STOP1:
  begin
  sda_link《=1;
  sda_out_r《=0;
  if(sclk_posedge_middle)
  begin
  sda_out_r《=1;
  if(sw1_r)
  // 你要是不等它松开才恢复初始状态,那么你一旦恢复初始状态SW1_r就为低电平,他又开始写了,所以为了避免重复写入数据。
  current_state《=IDLE;
  else
  current_state《=STOP1;
  end
  else
  current_state《=STOP1;
  end
  START2:begin
  sda_link《=1;
  if(sclk_posedge_middle)
  begin
  sda_out_r《=0;
  sda_link《=1;
  db_r《=`DEVICE_READ;
  current_state《=ADD3 ;
  end
  end
  ADD3: begin
  if(sclk_negedge_middle)
  begin
  if(num==4’d8)
  begin
  num《=0;
  sda_link《=0;
  sda_out_r《=1;
  current_state《=ACK4;
  end
  else
  begin
  num《=num+1;
  sda_out_r《=db_r[7-num];
  current_state《=ADD3;
  end
  end
  else
  current_state《=ADD3;
  end
  ACK4:
  if(sclk_posedge_middle)
  // begin
  // if(!sda)
  current_state《=DATA_READ;
  else
  current_state《=ACK4;
  // end
  DATA_READ:
  begin
  sda_link《=0;
  if(sclk_posedge_middle)
  begin
  if(num==4‘d8)
  begin
  sda_link《=1;
  sda_out_r《=1;
  current_state《=NO_ACK;
  num《=4’d0;
  end
  else
  begin
  num《=num+1;
  current_state《=DATA_READ;
  data_out_reg[7-num]《=sda;
  end
  end
  end
  NO_ACK:
  if(sclk_negedge_middle)
  begin
  sda_out_r《=1;
  current_state《=STOP2;
  end
  else
  current_state《=NO_ACK;
  STOP2:begin
  sda_out_r《=0;
  sda_link《=1;
  if(sclk_posedge_middle)
  begin
  sda_out_r《=1;
  current_state《=IDLE;
  end
  else
  current_state《=STOP2;
  end
  default:current_state《=IDLE;
  endcase
  end
  assign data_out=data_out_reg;
  endmodule
  仿真结果如下:

上一篇:电磁感应
下一篇:什么是MOS管?NMOS、PMOS和三极管的区别

免责声明: 凡注明来源本网的所有作品,均为本网合法拥有版权或有权使用的作品,欢迎转载,注明出处。非本网作品均来自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

相关技术资料