很多朋友对iic通信协议原理,iic通信协议是什么不是很了解,六月小编刚好整理了这方面的知识,今天就来带大家一探究竟。什么是iic通信协议
很多朋友对iic通信协议原理,iic通信协议是什么不是很了解,六月小编刚好整理了这方面的知识,今天就来带大家一探究竟。
什么是iic通信协议?IIC协议是两线制,信号线包含SDA和SCL,信号线是双向的,开路结构,需要通过上拉电阻到VCC。具体电阻值影响信号响应速度和驱动能力。
首先,IIC通信、UART和SPI统称为串行接口通信,但它们之间还是有区别的,比如UART的负逻辑,UART通信不需要时钟,只需要特定的波特率。SPI和IIC可以有一个主机和多个从机,但IIC适合短距离传输,如芯片到芯片的通信和摄像头配置。要去掉IIC,先看IIC的硬件接口:
如图,我们知道一个IIC主机可以挂多个从机,所以地址线A2、A1、A0可以执行片选的功能,所以WP引脚的作用是当WP挂起或接地时,意味着此时的EEPROM可以读或写,当WP接通电源时,只能读不能写。SCL和SDL引脚必须拔掉,否则驱动能力不够,无法进行正常的IIC通信。好了,硬件接口已经介绍清楚了,现在来看协议。
首先,IIC分为字节读写和页面读写。先看字节读写的协议:如上图所示,如果我们要将一个字节的数据写入EEPROM,就得有以下步骤: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信号来了之后,如果是读,会有另一个start信号,接着是读设备地址,然后是响应,然后是读数据,然后在SCLK低电平期间发送一个NO ACK信号。请记住,这个信号是由主机发送的,然后是结束信号。
从上面的读写时序可以知道,通信的开始在SCLK高电平期间跳变,这就决定了其他信号跳变都在SCLK的下降沿,而在SCLK高电平期间数据稳定,适合读取(即低电平改变数据,高电平采集数据)。具体流程如下:首先初始化板卡需要一个延时,多少由计数器自己完成。代码如下:reg[6:0]hadware _ initial _ delay;wire hadware _ initial _ delay _ done;
始终@(posedge时钟或negedge rst_n)if(!rst _ n)hadware _ initial _ delay"=7 ' d0;else if(had ware _ initial _ delay"=7 ' d49)had ware _ initial _ delay"=had ware _ initial _ delay 1;else hadware _ initial _ delay"=hadware _ initial _ delay;赋值hadware _ initial _ delay _ done=(hadware _ initial _ delay==7 ' d50)?1 ' B1:1 ' B0;好吧,我们要知道IIC的速率一般就几百KH而我们的系统时钟为50M,所以需要分频:代码如下:reg[8:0]sclk _ CNT;
always@(posedge clk或negedge rst_n)if(!rst _ n)sclk _ CNT “=9 ' d0;else if(hadware _ initial _ delay _ done)beginif(sclk _ CNT《9 ' d499》sclk _ CNT 《=sclk _ CNT 1;else sclk _ CNT"=0;end assign sclk=(sclk _ CNT"=9 ' d249)?1 ' B1:1 ' B0;好的,我们知道SCLK在高电平期间收集数据,在低电平期间改变数据,所以当然,这个“周期”在时钟边沿中间肯定是最好的。毕竟更容易满足建立时间和保持时间,非常稳定。具体代码如下:
wire sclk _ pos edge _ middle=(sclk _ CNT==9 ' d124)? 1 ' B1:1 ' B0; wire sclk _ neg edge _ middle=(sclk _ CNT==9 ' d374)? 1 ' B1:1 ' B0; Well, there are so many processes defined in reading and writing. Of course, the state machine is needed to handle them. The variables are defined as follows: 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 Well, let's have another macro definition, assuming that these addresses and these data are written. Define device _ read 8' b 1010 _ 0001 define device _ write 8' b 1010 _ 0000 define write _ data 8' b 0001 _ 0001 define bytes. reg sda _ linkreg 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;始终@(posedge时钟或negedge rst_n)if(!rst _ n)begin sda _ link"=0;db _ r"=0;num"=0;当前状态"=空闲;sda _ out _ r"=0;data _ out _ reg"=8 ' B0endelsbegincase(current _ state)IDLE:begin sda _ out _ r"=1;sda _ link"=1;如果(!sw1_r||!sw2_r)
当前状态"=开始1;elsecurrent _ state"=IDLEend start 1:if(sclk _ pos edge _ middle)开始da _ out _ r"=0;db _ r"=` device _ WRITEcurrent _ state"=add 1;endelse current _ state"=start 1;add 1:if(sclk _ neg edge _ middle)begin if(num==4 ' D8)begin sda _ link"=0;num"=0;current _ state"=ack 1;sda _ out _ r"=1;endelsbegincurrent _ state"=add 1;sda _ out _ r"=db _ r[7-num];num"=num 1;endendelsecurent _ state"=add 1;ack 1:if(sclk _ pos edge _ middle)//begin
//如果(!sda)//begin begin//*/current _ state"=add 2;db _ r"=` byte _ ADDR;endelse current _ state"=ack 1;add 2:begin sda _ link"=1;if(sclk _ neg edge _ middle)begin if(num==4 ' D8)begin sda _ link"=0;current _ state"=ack 2;num"=4 ' d0sda _ out _ r"=1;endelsbeginnum"=num 1;current _ state"=add 2;sda _ out _ r"=db _ r[7-num];endendelsecurent _ state"=add 2;end ack 2:if(sclk _ pos edge _ middle)////begin//if(!sda)beginbeginif(!sw1_r)开始
db _ r"=` write _ DATAcurrent _ state"=DATAendelseif(!sw2 _ r)begin current _ state"=start 2;sda _ out _ r"=1;endendelsecurent _ state"=ack 2;DATA:begin sda _ link"=1;if(sclk _ neg edge _ middle)begin if(num==4 ' D8)begin num"=4 ' d0;current _ state"=ack 3;sda _ out _ r"=1;sda _ link"=0;endelsbeginnum"=num 1;current _ state"=DATAsda _ out _ r"=db _ r[7-num];endendelsecurent _ state"=DATAend ack 3:if(sclk _ pos edge _ 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_r7-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_reg7-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
仿真结果如下:
以上知识分享希望能够帮助到大家!
声明本站所有作品图文均由用户自行上传分享,仅供网友学习交流。若您的权利被侵害,请联系我们