-
除了(le)電(diàn)源和(hé)地(dì)線(xiàn)外(wài),只(zhī)使用(yòng)两(liǎng)根(gēn)電(diàn)線(xiàn)(命名为(wèi)“sda”和(hé)“scl”)。 -
可(kě)以(yǐ)在(zài)同(tóng)一(yī)總(zǒng)線(xiàn)上(shàng)支持(chí)100多(duō)个(gè)設備(總(zǒng)線(xiàn)上(shàng)的(de)每个(gè)設備都有(yǒu)一(yī)个(gè)可(kě)單独訪問(wèn)的(de)地(dì)址) -
多(duō)主(zhǔ)機(jī)(例如(rú),两(liǎng)个(gè)CPU可(kě)以(yǐ)輕(qīng)松地(dì)共(gòng)享相同(tóng)的(de)I2C設備) -
行業标(biāo)準(由(yóu) 飛利浦,为(wèi)许多(duō)其他(tā)制造商所(suǒ)采用(yòng)) -
到(dào)处使用(yòng)(電(diàn)視,个(gè)人(rén)電(diàn)腦.)
-
相对(duì)較慢(màn)(100 Kbps基本(běn)速度(dù),擴展(zhǎn)可(kě)达(dá)3.4Mbps) -
不(bù)是(shì)即插即用(yòng)
它(tā)是(shì)如(rú)何工作的(de)
I2C波(bō)形
-
在(zài)您的(de)FPGA/CPLD中(zhōng)直(zhí)接使用(yòng)SCL線(xiàn)作为(wèi)时(shí)鐘(zhōng)信(xìn)号(hào) -
使用(yòng)快(kuài)速时(shí)鐘(zhōng)对(duì)SDA和(hé)SCL信(xìn)号(hào)進(jìn)行过(guò)采樣(yàng)
I2C從站:Io擴展(zhǎn)程序,使用(yòng)方(fāng)法1(SCL作为(wèi)FPGA/CPLD中(zhōng)的(de)时(shí)鐘(zhōng))
module I2CslaveWith8bitsIO(SDA, SCL, IOout); inout SDA; input SCL; output [7:0] IOout;
parameter I2C_ADR = 7'h27;
// We use two wires with a combinatorial loop to detect the start and stop conditions // ... making sure these two wires don't get optimized away wire SDA_shadow /* synthesis keep = 1 */; wire start_or_stop /* synthesis keep = 1 */; assign SDA_shadow = (~SCL | start_or_stop) ? SDA : SDA_shadow; assign start_or_stop = ~SCL ? 1'b0 : (SDA ^ SDA_shadow); reg incycle; always @(negedge SCL or posedge start_or_stop) if(start_or_stop) incycle <= 1'b0; else if(~SDA) incycle <= 1'b1;
reg [3:0] bitcnt; // counts the I2C bits from 7 downto 0, plus an ACK bit wire bit_DATA = ~bitcnt[3]; // the DATA bits are the first 8 bits sent wire bit_ACK = bitcnt[3]; // the ACK bit is the 9th bit sent reg data_phase; always @(negedge SCL or negedge incycle) if(~incycle) begin bitcnt <= 4'h7; // the bit 7 is received first data_phase <= 0; end else begin if(bit_ACK) begin bitcnt <= 4'h7; data_phase <= 1; end else bitcnt <= bitcnt - 4'h1; end
wire adr_phase = ~data_phase; reg adr_match, op_read, got_ACK; // sample SDA on posedge since the I2C spec specifies as low as 0µs hold-time on negedge reg SDAr; always @(posedge SCL) SDAr<=SDA; reg [7:0] mem; wire op_write = ~op_read; always @(negedge SCL or negedge incycle) if(~incycle) begin got_ACK <= 0; adr_match <= 1; op_read <= 0; end else begin if(adr_phase & bitcnt==7 & SDAr!=I2C_ADR[6]) adr_match<=0; if(adr_phase & bitcnt==6 & SDAr!=I2C_ADR[5]) adr_match<=0; if(adr_phase & bitcnt==5 & SDAr!=I2C_ADR[4]) adr_match<=0; if(adr_phase & bitcnt==4 & SDAr!=I2C_ADR[3]) adr_match<=0; if(adr_phase & bitcnt==3 & SDAr!=I2C_ADR[2]) adr_match<=0; if(adr_phase & bitcnt==2 & SDAr!=I2C_ADR[1]) adr_match<=0; if(adr_phase & bitcnt==1 & SDAr!=I2C_ADR[0]) adr_match<=0; if(adr_phase & bitcnt==0) op_read <= SDAr; // we monitor the ACK to be able to free the bus when the master doesn't ACK during a read operation if(bit_ACK) got_ACK <= ~SDAr; if(adr_match & bit_DATA & data_phase & op_write) mem[bitcnt] <= SDAr; // memory write end
wire mem_bit_low = ~mem[bitcnt[2:0]]; wire SDA_assert_low = adr_match & bit_DATA & data_phase & op_read & mem_bit_low & got_ACK; wire SDA_assert_ACK = adr_match & bit_ACK & (adr_phase | op_write); wire SDA_low = SDA_assert_low | SDA_assert_ACK; assign SDA = SDA_low ? 1'b0 : 1'bz; assign IOout = mem; endmodule
結果(guǒ)是(shì)什麼(me)?
-
FPGA/CPLD采用(yòng)SCL信(xìn)号(hào)作为(wèi)时(shí)鐘(zhōng)。使用(yòng)a 施密特(tè)觸發(fà)器強(qiáng)烈建議在(zài)SCL輸入(rù)引脚上(shàng)避免异(yì)常行为(wèi)(如(rú)果(guǒ)沒(méi)有(yǒu)Schmitt觸發(fà)器,SCL線(xiàn)路(lù)上(shàng)的(de)任何噪聲或(huò)振鈴都会(huì)引入(rù)額外(wài)的(de)时(shí)鐘(zhōng)周期(qī),從而(ér)破壞功能(néng))。 -
開(kāi)始和(hé)停止条(tiáo)件(jiàn)檢测邏輯使用(yòng)組合反(fǎn)饋循环(huán),这(zhè)不(bù)是(shì)推薦的(de)做法。在(zài)“InCycle”信(xìn)号(hào)上(shàng)也(yě)是(shì)一(yī)樣(yàng)的(de),它(tā)被(bèi)邏輯的(de)其餘部(bù)分(fēn)用(yòng)作异(yì)步重(zhòng)置。这(zhè)是(shì)为(wèi)了(le)避免使用(yòng)过(guò)采樣(yàng)时(shí)鐘(zhōng)而(ér)付出(chū)的(de)代(dài)價。















