最近在弄I2C驱动,在网上找了一个《I2C协议说明及verilog实现读写I2C器件》文档,修改其中的代码。进过漫长的修改调试,终于可以单独驱动LM75A或者PCF8563了,但是两个一起驱动就出问题了,找了很久也没解决,望高手指导下呀
已解锁-I2C协议说明及verilog实现读写I2C器件.pdf
程序是本来想通过下面语句完成两个器件的切换读取:
case(code_ctl)
PCF8563T: begin
if(finish_bit==1'b0)begin //finish_bit是在50ms中有一个50MHz时钟周期为1,其他时刻都是0
//所以是50ms进行一次I2C操作
sda_data_addr<=8'ha2; //PCF8563器件地址,程序中一次读完秒,分和时三个字节数据
sda_data_word<=8'h02; //发送秒寄存器的地址
if(iic_sts == STOP)begin
sec<=data_read;
min<=data_read2;
hour<=data_read3;
end
else
code_ctl<=LM75A; //等待发送秒寄存器的地址
end
LM75A: begin
if(finish_bit==1'b0)begin
sda_data_addr<=8'h90; //LM75A器件地址,程序中只读两个字节数据,显示只要前8位
//程序中这个字节数据未转为BCD码,直接1602显示了……LEs不够用啊
sda_data_word<=8'h00; //发送温度寄存器的地址
if(iic_sts == STOP)
temp<=data_read4;
end
else
code_ctl<=PCF8563T;
end
endcase
但是不行,改为单独一个就能正常显示。
其中PCF8563T和LM75A的SLC和SDA输出是共用的(没有标名称的是PCF8563T的)
输入的时候用器件地址区分后,再读取SDA或者LM75A:
assign LM75A_SCL = scl_r;
assign LM75A_SDA = sda_io_flag?sda_r:1'bz;
assign SCL = scl_r;
assign SDA = sda_io_flag?sda_r:1'bz;
I2C的状态机中,SDA和LM75A_SDA的读取区分是器件地址,sda_data_addr==8'ha2是则从机应答
和读数据是PCF8563T的SDA,否则是LM75A的LM75A_SDA。
采用的I2C的时序是这样的,先启动I2C然后发送器件地址(写),从机应答,写寄存器地址,从机应答
重启I2C,发送器件地址(读),接收一个字节数据,主机应答,接收一个字节数据,主机应答
接收一个字节数据,主机非应答(非应答我理解的是SDA输出高电平),停止I2C。一直保持停止状态,等到50ms再启动I2C操作。
还有就是如果对PCF8563T进行两次I2C操作,然后对LM75A进行两次操作,如此循环就能勉强都驱动起来
但是1602的显示会抖动,怀疑读到的数据变动?!看着有点头昏了,望高手指导下~~