在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

一文帶你迅速了解常用串行總線之IIC協(xié)議3

jf_78858299 ? 來源:Cascatrix ? 作者:Carson ? 2023-01-21 17:20 ? 次閱讀

4. bit控制模塊(i2c_bit_ctrl):

`define I2C_CMD_NOP 4'b0000

`define I2C_CMD_START 4'b0001

`define I2C_CMD_STOP 4'b0010

`define I2C_CMD_WRITE 4'b0100

`define I2C_CMD_READ 4'b1000

module i2c_bit_ctrl (

input             clk,      // system clock

input             rst,      // synchronous active high reset

input             nReset,   // asynchronous active low reset

input             ena,      // core enable signal



input      [15:0] clk_cnt,  // clock prescale value



input      [ 3:0] cmd,      // command (from byte controller)

output reg        cmd_ack,  // command complete acknowledge

output reg        busy,     // i2c bus busy

output reg        al,       // i2c bus arbitration lost



input             din,

output reg        dout,



input             scl_i,    // i2c clock line input

output            scl_o,    // i2c clock line output

output reg        scl_oen,  // i2c clock line output enable (active low)

input             sda_i,    // i2c data line input

output            sda_o,    // i2c data line output

output reg        sda_oen   // i2c data line output enable (active low)

);

//

// variable declarations

//



reg [ 1:0] cSCL, cSDA;      // capture SCL and SDA

reg [ 2:0] fSCL, fSDA;      // SCL and SDA filter inputs

reg        sSCL, sSDA;      // filtered and synchronized SCL and SDA inputs

reg        dSCL, dSDA;      // delayed versions of sSCL and sSDA

reg        dscl_oen;        // delayed scl_oen

reg        sda_chk;         // check SDA output (Multi-master arbitration)

reg        clk_en;          // clock generation signals

reg        slave_wait;      // slave inserts wait states

reg [15:0] cnt;             // clock divider counter (synthesis)

reg [13:0] filter_cnt;      // clock divider for filter





// state machine variable

reg [17:0] c_state; // synopsys enum_state



//

// module body

//



// whenever the slave is not ready it can delay the cycle by pulling SCL low

// delay scl_oen

always @(posedge clk)

  dscl_oen <= #1 scl_oen;



// slave_wait is asserted when master wants to drive SCL high, but the slave pulls it low

// slave_wait remains asserted until the slave releases SCL

always @(posedge clk or negedge nReset)

  if (!nReset) slave_wait <= 1'b0;

  else         slave_wait <= (scl_oen & ~dscl_oen & ~sSCL) | (slave_wait & ~sSCL);



// master drives SCL high, but another master pulls it low

// master start counting down its low cycle now (clock synchronization)

wire scl_sync   = dSCL & ~sSCL & scl_oen;



// generate clk enable signal

always @(posedge clk or negedge nReset)

  if (~nReset)

  begin

      cnt    <= #1 16'h0;

      clk_en <= #1 1'b1;

  end

  else if (rst || ~|cnt || !ena || scl_sync)

  begin

      cnt    <= #1 clk_cnt;

      clk_en <= #1 1'b1;

  end

  else if (slave_wait)

  begin

      cnt    <= #1 cnt;

      clk_en <= #1 1'b0;    

  end

  else

  begin

      cnt    <= #1 cnt - 16'h1;

      clk_en <= #1 1'b0;

  end



// generate bus status controller



// capture SDA and SCL

// reduce metastability risk

always @(posedge clk or negedge nReset)

  if (!nReset)

  begin

      cSCL <= #1 2'b00;

      cSDA <= #1 2'b00;

  end

  else if (rst)

  begin

      cSCL <= #1 2'b00;

      cSDA <= #1 2'b00;

  end

  else

  begin

      cSCL <= {cSCL[0],scl_i};

      cSDA <= {cSDA[0],sda_i};

  end



// filter SCL and SDA signals; (attempt to) remove glitches

always @(posedge clk or negedge nReset)

  if      (!nReset     ) filter_cnt <= 14'h0;

  else if (rst || !ena ) filter_cnt <= 14'h0;

  else if (~|filter_cnt) filter_cnt <= clk_cnt >> 2; //16x I2C bus frequency

  else                   filter_cnt <= filter_cnt -1;





always @(posedge clk or negedge nReset)

  if (!nReset)

  begin

      fSCL <= 3'b111;

      fSDA <= 3'b111;

  end

  else if (rst)

  begin

      fSCL <= 3'b111;

      fSDA <= 3'b111;

  end

  else if (~|filter_cnt)

  begin

      fSCL <= {fSCL[1:0],cSCL[1]};

      fSDA <= {fSDA[1:0],cSDA[1]};

  end



// generate filtered SCL and SDA signals

always @(posedge clk or negedge nReset)

  if (~nReset)

  begin

      sSCL <= #1 1'b1;

      sSDA <= #1 1'b1;



      dSCL <= #1 1'b1;

      dSDA <= #1 1'b1;

  end

  else if (rst)

  begin

      sSCL <= #1 1'b1;

      sSDA <= #1 1'b1;



      dSCL <= #1 1'b1;

      dSDA <= #1 1'b1;

  end

  else

  begin

      sSCL <= #1 &fSCL[2:1] | &fSCL[1:0] | (fSCL[2] & fSCL[0]);

      sSDA <= #1 &fSDA[2:1] | &fSDA[1:0] | (fSDA[2] & fSDA[0]);



      dSCL <= #1 sSCL;

      dSDA <= #1 sSDA;

  end



// detect start condition => detect falling edge on SDA while SCL is high

// detect stop condition => detect rising edge on SDA while SCL is high

reg sta_condition;

reg sto_condition;

always @(posedge clk or negedge nReset)

  if (~nReset)

  begin

      sta_condition <= #1 1'b0;

      sto_condition <= #1 1'b0;

  end

  else if (rst)

  begin

      sta_condition <= #1 1'b0;

      sto_condition <= #1 1'b0;

  end

  else

  begin

      sta_condition <= #1 ~sSDA &  dSDA & sSCL;

      sto_condition <= #1  sSDA & ~dSDA & sSCL;

  end





// generate i2c bus busy signal

always @(posedge clk or negedge nReset)

  if      (!nReset) busy <= #1 1'b0;

  else if (rst    ) busy <= #1 1'b0;

  else              busy <= #1 (sta_condition | busy) & ~sto_condition;





// generate arbitration lost signal cascatrix carson

// aribitration lost when:

// 1) master drives SDA high, but the i2c bus is low

// 2) stop detected while not requested

reg cmd_stop;

always @(posedge clk or negedge nReset)

  if (~nReset)

      cmd_stop <= #1 1'b0;

  else if (rst)

      cmd_stop <= #1 1'b0;

  else if (clk_en)

      cmd_stop <= #1 cmd == `I2C_CMD_STOP;



always @(posedge clk or negedge nReset)

  if (~nReset)

      al <= #1 1'b0;

  else if (rst)

      al <= #1 1'b0;

  else

      al <= #1 (sda_chk & ~sSDA & sda_oen) | (|c_state & sto_condition & ~cmd_stop);





// generate dout signal (store SDA on rising edge of SCL) cascatrix carson

always @(posedge clk)

  if (sSCL & ~dSCL) dout <= #1 sSDA;





// generate statemachine cascatrix carson



// nxt_state decoder

parameter [17:0] idle    = 18'b0_0000_0000_0000_0000;

parameter [17:0] start_a = 18'b0_0000_0000_0000_0001;

parameter [17:0] start_b = 18'b0_0000_0000_0000_0010;

parameter [17:0] start_c = 18'b0_0000_0000_0000_0100;

parameter [17:0] start_d = 18'b0_0000_0000_0000_1000;

parameter [17:0] start_e = 18'b0_0000_0000_0001_0000;

parameter [17:0] stop_a  = 18'b0_0000_0000_0010_0000;

parameter [17:0] stop_b  = 18'b0_0000_0000_0100_0000;

parameter [17:0] stop_c  = 18'b0_0000_0000_1000_0000;

parameter [17:0] stop_d  = 18'b0_0000_0001_0000_0000;

parameter [17:0] rd_a    = 18'b0_0000_0010_0000_0000;

parameter [17:0] rd_b    = 18'b0_0000_0100_0000_0000;

parameter [17:0] rd_c    = 18'b0_0000_1000_0000_0000;

parameter [17:0] rd_d    = 18'b0_0001_0000_0000_0000;

parameter [17:0] wr_a    = 18'b0_0010_0000_0000_0000;

parameter [17:0] wr_b    = 18'b0_0100_0000_0000_0000;

parameter [17:0] wr_c    = 18'b0_1000_0000_0000_0000;

parameter [17:0] wr_d    = 18'b1_0000_0000_0000_0000;



always @(posedge clk or negedge nReset)

  if (!nReset)

  begin

      c_state <= #1 idle;

      cmd_ack <= #1 1'b0;

      scl_oen <= #1 1'b1;

      sda_oen <= #1 1'b1;

      sda_chk <= #1 1'b0;

  end

  else if (rst | al)

  begin

      c_state <= #1 idle;

      cmd_ack <= #1 1'b0;

      scl_oen <= #1 1'b1;

      sda_oen <= #1 1'b1;

      sda_chk <= #1 1'b0;

  end

  else

  begin

// default no command acknowledge + assert cmd_ack only 1clk cycle

cmd_ack   <= #1 1'b0; 

      if (clk_en) // synopsys full_case parallel_case

          case (c_state) 

                // idle state

                idle:

                begin // synopsys full_case parallel_case

                    case (cmd) 

                     `I2C_CMD_START: c_state <= #1 start_a;

                     `I2C_CMD_STOP:  c_state <= #1 stop_a;

                     `I2C_CMD_WRITE: c_state <= #1 wr_a;

                     `I2C_CMD_READ:  c_state <= #1 rd_a;

                      default:        c_state <= #1 idle;

                    endcase

        // keep SCL in same state

                    scl_oen <= #1 scl_oen; 

         // keep SDA in same state

                    sda_oen <= #1 sda_oen;

        // don't check SDA output

                    sda_chk <= #1 1'b0;    

                end

                // start

                start_a:

                begin

                    c_state <= #1 start_b;

        // keep SCL in same state

                    scl_oen <= #1 scl_oen; 

                    sda_oen <= #1 1'b1;    // set SDA high

        // don't check SDA output

                    sda_chk <= #1 1'b0;    

                end



                start_b:

                begin

                    c_state <= #1 start_c;

                    scl_oen <= #1 1'b1; // set SCL high

                    sda_oen <= #1 1'b1; // keep SDA high

        // don't check SDA output

                    sda_chk <= #1 1'b0; 

                end



                start_c:

                begin

                    c_state <= #1 start_d;

                    scl_oen <= #1 1'b1; // keep SCL high

                    sda_oen <= #1 1'b0; // set SDA low

        // don't check SDA output

                    sda_chk <= #1 1'b0; 

                end



                start_d:

                begin

                    c_state <= #1 start_e;

                    scl_oen <= #1 1'b1; // keep SCL high

                    sda_oen <= #1 1'b0; // keep SDA low

        // don't check SDA output

                    sda_chk <= #1 1'b0; 

                end

                start_e:

                begin

                    c_state <= #1 idle;

                    cmd_ack <= #1 1'b1;

                    scl_oen <= #1 1'b0; // set SCL low

                    sda_oen <= #1 1'b0; // keep SDA low

        // don't check SDA output

                    sda_chk <= #1 1'b0; 

                end

                // stop

                stop_a:

                begin

                    c_state <= #1 stop_b;

                    scl_oen <= #1 1'b0; // keep SCL low

                    sda_oen <= #1 1'b0; // set SDA low

        // don't check SDA output

                    sda_chk <= #1 1'b0; 

                end

                stop_b:

                begin

                    c_state <= #1 stop_c;

                    scl_oen <= #1 1'b1; // set SCL high

                    sda_oen <= #1 1'b0; // keep SDA low

        // don't check SDA output

                    sda_chk <= #1 1'b0; 

                end

                stop_c:

                begin

                    c_state <= #1 stop_d;

                    scl_oen <= #1 1'b1; // keep SCL high

                    sda_oen <= #1 1'b0; // keep SDA low

        // don't check SDA output

                    sda_chk <= #1 1'b0; 

                end



                stop_d:

                begin

                    c_state <= #1 idle;

                    cmd_ack <= #1 1'b1;

                    scl_oen <= #1 1'b1; // keep SCL high

                    sda_oen <= #1 1'b1; // set SDA high

        // don't check SDA output

                    sda_chk <= #1 1'b0; 

                end

                // read

                rd_a:

                begin

                    c_state <= #1 rd_b;

                    scl_oen <= #1 1'b0; // keep SCL low

                    sda_oen <= #1 1'b1; // tri-state SDA

        // don't check SDA output

                    sda_chk <= #1 1'b0; 

                end

                rd_b:

                begin

                    c_state <= #1 rd_c;

                    scl_oen <= #1 1'b1; // set SCL high

                    sda_oen <= #1 1'b1; // keep SDA tri-stated

        // don't check SDA output

                    sda_chk <= #1 1'b0; 

                end

                rd_c:

                begin

                    c_state <= #1 rd_d;

                    scl_oen <= #1 1'b1; // keep SCL high

                    sda_oen <= #1 1'b1; // keep SDA tri-stated

        // don't check SDA output

                    sda_chk <= #1 1'b0;

                end

                rd_d:

                begin

                    c_state <= #1 idle;

                    cmd_ack <= #1 1'b1;

                    scl_oen <= #1 1'b0; // set SCL low

                    sda_oen <= #1 1'b1; // keep SDA tri-stated

        // don't check SDA output

                    sda_chk <= #1 1'b0; 

                end

                // write

                wr_a:

                begin

                    c_state <= #1 wr_b;

                    scl_oen <= #1 1'b0; // keep SCL low

                    sda_oen <= #1 din;  // set SDA

        // don't check SDA output (SCL low)

                    sda_chk <= #1 1'b0; 

                end

                wr_b:

                begin

                    c_state <= #1 wr_c;

                    scl_oen <= #1 1'b1; // set SCL high

                    sda_oen <= #1 din;  // keep SDA

        // don't check SDA output yet

                    sda_chk <= #1 1'b0; 

        // allow some time for SDA and SCL to settle

                end

                wr_c:

                begin

                    c_state <= #1 wr_d;

                    scl_oen <= #1 1'b1; // keep SCL high

                    sda_oen <= #1 din;

                    sda_chk <= #1 1'b1; // check SDA output

                end

                wr_d:

                begin

                    c_state <= #1 idle;

                    cmd_ack <= #1 1'b1;

                    scl_oen <= #1 1'b0; // set SCL low

                    sda_oen <= #1 din;

                    sda_chk <= #1 1'b0; // don't check SDA output (SCL low)

                end

          endcase

  end



// assign scl and sda output (always gnd)

assign scl_o = 1'b0;

assign sda_o = 1'b0;

endmodule

04

IIC的優(yōu)缺點

4.1 IIC協(xié)議優(yōu)點

  1. 通信只需要兩條信號線;
  2. 多主設備結構下,總線系統(tǒng)無需額外的邏輯與線路;
  3. 應答機制完善,通信傳輸穩(wěn)定。

4.2 IIC協(xié)議缺點

  1. 硬件結構復雜;
  2. 支持傳輸距離較短;
  3. 半雙工速率慢于全雙工,SPI全雙工一般可實現(xiàn)10Mbps以上的傳輸速率,IIC最高速度僅能達到3.4Mbps。
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • IIC
    IIC
    +關注

    關注

    11

    文章

    302

    瀏覽量

    38542
  • 通信總線
    +關注

    關注

    0

    文章

    45

    瀏覽量

    9893
  • SDA
    SDA
    +關注

    關注

    0

    文章

    124

    瀏覽量

    28282
收藏 人收藏

    評論

    相關推薦

    詳解IIC總線

    IIC(Inter-Integrated Circuit)集成電路總線,它是種兩線式串行通信總線,又叫I2C,使用多主從架構,由飛利浦公司
    發(fā)表于 06-07 15:38 ?1w次閱讀
    <b class='flag-5'>一</b><b class='flag-5'>文</b>詳解<b class='flag-5'>IIC</b><b class='flag-5'>總線</b>

    詳解IIC總線

    IIC(Inter-Integrated Circuit)是個多主從的串行總線,又叫I2C,是由飛利浦公司發(fā)明的通訊總線,屬于半雙工同步傳
    發(fā)表于 09-12 11:15 ?2393次閱讀
    <b class='flag-5'>一</b><b class='flag-5'>文</b>詳解<b class='flag-5'>IIC</b><b class='flag-5'>總線</b>

    IIC總線協(xié)議與SCCB協(xié)議的區(qū)別

    先簡單介紹IIC總線協(xié)議IIC總線是philips公司推出的新
    發(fā)表于 08-07 12:43

    常用串行總線協(xié)議有哪些

    常用串行總線協(xié)議目前常用的微機與外設之間進行數(shù)據傳輸?shù)?b class='flag-5'>
    發(fā)表于 11-03 07:14

    常用串行總線協(xié)議有哪些

    常用串行總線協(xié)議I2C總線、SPI總線、SCI總線
    發(fā)表于 11-19 06:46

    IIC總線協(xié)議的相關資料下載

    (串行數(shù)據線)和SCL(串行時鐘線)及上拉電阻組成。通信原理是通過對SCL和SDA線高低電平時序的控制,來 產生I2C總線協(xié)議所需要的信號進行數(shù)據的傳遞。在
    發(fā)表于 11-30 08:29

    串行通信中的IIC總線工作原理是什么

    串行通信中的IIC總線工作原理51本身不帶IIC總線 ,使用程序模擬IIC通信
    發(fā)表于 12-08 07:52

    IIC協(xié)議的相關資料推薦

    STM32 IIC實驗講解,從入門到放棄。文章目錄STM32 IIC實驗講解,從入門到放棄。前言、IICIIC是什么?IIC協(xié)議二、代碼部
    發(fā)表于 01-17 08:12

    IIC總線接口學習

    在多主設備IIC 總線模式下,多個S3C2440A 微處理器可以從從屬設備接收或發(fā)送串行數(shù)據。主設備S3C2440A 可以初始化和終止
    發(fā)表于 04-27 15:31 ?61次下載
    <b class='flag-5'>IIC</b><b class='flag-5'>總線</b>接口學習

    IIC總線協(xié)議

    IIC總線協(xié)議,感興趣的小伙伴們可以看看。
    發(fā)表于 07-26 16:29 ?59次下載

    FPGA基礎知識IIC協(xié)議讀寫解析

    很多數(shù)字傳感器、數(shù)字控制的芯片(DDS、串行ADC、串行DAC)都是通過IIC總線來和控制器通信的。不過IIC
    發(fā)表于 05-05 10:17 ?8311次閱讀
    FPGA基礎知識<b class='flag-5'>之</b><b class='flag-5'>IIC</b><b class='flag-5'>協(xié)議</b>讀寫解析

    IIC總線協(xié)議及應用

    (串行數(shù)據線)和SCL(串行時鐘線)及上拉電阻組成。通信原理是通過對SCL和SDA線高低電平時序的控制,來 產生I2C總線協(xié)議所需要的信號進行數(shù)據的傳遞。在
    發(fā)表于 11-20 15:21 ?10次下載
    <b class='flag-5'>IIC</b><b class='flag-5'>總線</b><b class='flag-5'>協(xié)議</b>及應用

    STC89C52的IIC總線寫EEPROM

    串行通信中的IIC總線工作原理51本身不帶IIC總線 ,使用程序模擬IIC通信
    發(fā)表于 11-25 15:51 ?11次下載
    STC89C52的<b class='flag-5'>IIC</b><b class='flag-5'>總線</b>寫EEPROM

    帶你迅速了解常用串行總線IIC協(xié)議1

    集成電路總線** (Inter-Intergrated Circuit),通常稱作IICBUS,簡稱為IIC,是種采用多主從結構的串行通信總線
    的頭像 發(fā)表于 01-21 17:19 ?1982次閱讀
    <b class='flag-5'>一</b><b class='flag-5'>文</b><b class='flag-5'>帶你</b><b class='flag-5'>迅速</b><b class='flag-5'>了解</b><b class='flag-5'>常用</b><b class='flag-5'>串行</b><b class='flag-5'>總線</b><b class='flag-5'>之</b><b class='flag-5'>IIC</b><b class='flag-5'>協(xié)議</b>1

    帶你迅速了解常用串行總線IIC協(xié)議2

    集成電路總線** (Inter-Intergrated Circuit),通常稱作IICBUS,簡稱為IIC,是種采用多主從結構的串行通信總線
    的頭像 發(fā)表于 01-21 17:20 ?1123次閱讀
    主站蜘蛛池模板: 美女黄18 | 手机看片久久 | 手机在线看片福利盒子 | 乱码一区二区三区完整视频 | 激情网页 | 午夜激情福利视频 | 亚洲经典一区二区三区 | 日韩精品视频免费在线观看 | 99草精品视频 | 天天操天天爽天天射 | 天天摸天天做天天爽天天弄 | 国产福利资源在线 | 国产精品一区二区三区四区五区 | 永久精品免费影院在线观看网站 | 午夜大片免费完整在线看 | 亚洲国产人久久久成人精品网站 | 中文字幕欧美日韩 | 欧美亚洲另类在线观看 | 4438全国最大成人免费高清 | 91日本在线观看亚洲精品 | 一本大道香蕉大vr在线吗视频 | 亚洲第一永久在线观看 | 日韩在线免费看网站 | 国内精品免费视频精选在线观看 | 日韩黄色录像 | 免费看的黄视频 | 亚洲国产成人久久99精品 | 一区在线免费观看 | 亚洲精品成人久久久影院 | 亚洲网站免费看 | 国产永久视频夜色资源网 | 人人看操 | 婷婷 综合网站 | 欧美艹逼视频 | 国产欧美在线一区二区三区 | 精品久久中文网址 | 男人的天堂免费视频 | 中文字幕一区二区三区在线不卡 | 天天躁日日躁狠狠躁中文字幕老牛 | 美女和帅哥在床上玩的不可描述 | 黄色视屏在线免费观看 |