01
IIC基礎知識
集成電路總線 (Inter-Intergrated Circuit),通常稱作IICBUS,簡稱為IIC,是一種采用多主從結構的串行通信總線。
IIC由PHILIPS公司于1980年推出,利用該總線可實現多主機系統所需的裁決和高低速設備同步等功能。
IIC串行總線一般有兩根信號線,分別是時鐘線SCL和數據線SDA,所有IIC總線各設備的串行數據SDA接到總線SDA上,時鐘線SLC接到總線SCL上。
雙向串行數據SDA:輸出電路用于向總線發送數據,輸入電路用于接收總線上的數據;
雙向時鐘數據SCL:輸出電路用于向總線發送時鐘信號,輸入電路用于檢測總線時鐘電平以決定下次時鐘脈沖電平時間。
各設備與總線相連的輸出端采用高阻態以避免總線信號的混亂,通常采用漏極開路輸出或集電極開路輸出。總線空閑時,各設備都是開漏輸出,通常可采用上拉電阻使總線保持高電平,而任一設備輸出低電平都將拉低相應的總線信號。
IIC總線上的設備可分為主設備和從設備兩種:主設備有權利主動發起/結束一次通信;從設備只能被動響應。
所有連接在IIC總線上的設備都有各自唯一的地址(原地址位寬為7bits,改進后采用10bits位寬),每個設備都可以作為主設備或從設備,但是同一時刻只能有一個主設備控制。
如果總線上有多個設備同時啟用總線,IIC通過檢測和仲裁機制解決傳輸沖突。IIC允許連接的設備傳輸速率不同,多臺設備之間時鐘信號的同步過程稱為同步化。
02
IIC傳輸協議
2.1 IIC協議模式
IIC協議為半雙工模式,同一條數據線上完成讀/寫操作,不同操作時的數據幀格式可分為寫操作、讀操作、讀寫操作。
2.1.1 寫操作數據幀格式
主機向從機寫數據的數據幀格式如下:
白色為主機發送數據,灰色為從機發送數據。
- 主機發送開始信號S;
- 主機發送地址數據ADDR;
- 主機發送寫信號0;
- 從機響應主機寫信號ACK;
- 主機發送數據信息DATA;
- 從機響應主機發送數據ACK;
- 循環5 6步驟可完成主機向從機連續寫數據過程;
- 主機發送結束信號P.
2.1.2 讀操作數據幀格式
主機從從機讀數據的數據幀格式如下:
白色為主機發送數據,灰色為從機發送數據。
- 主機發送開始信號S;
- 主機發送地址數據ADDR;
- 主機發送讀信號1;
- 從機響應主機讀信號ACK;
- 從機發送數據信息DATA;
- 主機響應從機發送數據ACK;
- 循環5 6步驟可完成主機向從機連續讀數據過程;
- 主機發送結束信號P.
2.1.3 讀寫同時操作數據幀格式
主機先向從機寫數據后從從機讀數據的數據幀格式如下:
白色為主機發送數據,灰色為從機發送數據。
主機可以在完成寫操作后不發送結束信號P,直接進行讀操作。該過程主機不可變,而從機可以通過發送不同地址選擇不同的從機。
2.2 IIC寫時序
IIC協議寫時序可分為單字節寫時序和連續寫時序:
2.2.1 單字節寫時序
單字節地址寫時序過程:
- 主機發送開始信號S;
- 主機發送控制字節CONTROL BYTE(7bits設備地址dev addr和1bit讀寫信號),最低位為0表示主機向從機寫數據;
- 從機響應主機控制字節ACK;
- 主機發送單字節寄存器地址信息WORD ADDRESS;
- 從機響應主機發送寄存器地址ACK;
- 主機發送單字節數據信息DATA;
- 從機響應主機發送數據信息ACK;
- 主機發送結束信號P.
雙字節地址寫時序過程:
- 主機發送開始信號S;
- 主機發送控制字節CONTROL BYTE(7bits設備地址dev addr和1bit讀寫信號),最低位為0表示主機向從機寫數據;
- 從機響應主機控制字節ACK;
- 主機發送寄存器地址信息高字節ADDRESS HIGH BYTE;
- 從機響應主機發送寄存器地址高字節ACK;
- 主機發送寄存器地址信息低字節ADDRESS LOW BYTE;
- 從機響應主機發送寄存器地址低字節ACK;
- 主機發送單字節數據信息DATA;
- 從機響應主機發送數據信息ACK;
- 主機發送結束信號P.
2.2.2 連續寫時序
單字節地址寫時序過程:
- 主機發送開始信號S;
- 主機發送控制字節CONTROL BYTE(7bits設備地址dev addr和1bit讀寫信號),最低位為0表示主機向從機寫數據;
- 從機響應主機控制字節ACK;
- 主機發送單字節寄存器地址信息WORD ADDRESS;
- 從機響應主機發送寄存器地址ACK;
- 主機發送單字節數據信息DATA;
- 從機響應主機發送數據信息ACK;
- 循環6 7步驟可以連續向從機寫數據DATA(D+n);
- 主機發送結束信號P.
雙字節地址寫時序過程:
- 主機發送開始信號S;
- 主機發送控制字節CONTROL BYTE(7bits設備地址dev addr和1bit讀寫信號),最低位為0表示主機向從機寫數據;
- 從機響應主機控制字節ACK;
- 主機發送寄存器地址信息高字節ADDRESS HIGH BYTE;
- 從機響應主機發送寄存器地址高字節ACK;
- 主機發送寄存器地址信息低字節ADDRESS LOW BYTE;
- 從機響應主機發送寄存器地址低字節ACK;
- 主機發送單字節數據信息DATA;
- 從機響應主機發送數據信息ACK;
- 循環8 9步驟可以連續向從機寫數據DATA(D+n);
- 主機發送結束信號P.
2.3 IIC讀時序
IIC協議讀時序可分為單字節讀時序和連續讀時序:
2.3.1 單字節讀時序
單字節地址讀時序過程:
- 主機發送開始信號S;
- 主機發送控制字節CONTROL BYTE(7bits設備地址dev addr和1bit讀寫信號),最低位為0表示主機向從機寫數據;
- 從機響應主機控制字節ACK;
- 主機發送單字節寄存器地址信息WORD ADDRESS;
- 從機響應主機發送寄存器地址ACK;
- 主機發送開始信號S;
- 主機發送控制字節CONTROL BYTE(7bits設備地址dev addr和1bit讀寫信號),最低位為1表示主機從從機讀數據;
- 從機響應主機控制字節ACK;
- 從機發送單字節數據信息DATA;
- 主機響應從機發送數據信息NACK(非應答位: 接收器是主機時,在接收到最后一個字節后發送NACK已通知被控發送從機結束數據發送,并釋放SDA數據線以便主機發送停止信號P);
- 主機發送結束信號P.
雙字節地址讀時序過程:
- 主機發送開始信號S;
- 主機發送控制字節CONTROL BYTE(7bits設備地址dev addr和1bit讀寫信號),最低位為0表示主機向從機寫數據;
- 從機響應主機控制字節ACK;
- 主機發送寄存器地址信息高字節ADDRESS HIGH BYTE;
- 從機響應主機發送寄存器地址高字節ACK;
- 主機發送寄存器地址信息低字節ADDRESS LOW BYTE;
- 從機響應主機發送寄存器地址低字節ACK;
- 主機發送開始信號S;
- 主機發送控制字節CONTROL BYTE(7bits設備地址dev addr和1bit讀寫信號),最低位為1表示主機從從機讀數據;
- 從機響應主機控制字節ACK;
- 從機發送單字節數據信息DATA;
- 主機響應從機發送數據信息NACK(非應答位: 接收器是主機時,在接收到最后一個字節后發送NACK已通知被控發送從機結束數據發送,并釋放SDA數據線以便主機發送停止信號P);
- 主機發送結束信號P.
2.3.2 連續讀時序
單字節地址讀時序過程:
- 主機發送開始信號S;
- 主機發送控制字節CONTROL BYTE(7bits設備地址dev addr和1bit讀寫信號),最低位為0表示主機向從機寫數據;
- 從機響應主機控制字節ACK;
- 主機發送單字節寄存器地址信息WORD ADDRESS;
- 從機響應主機發送寄存器地址ACK;
- 主機發送開始信號S;
- 主機發送控制字節CONTROL BYTE(7bits設備地址dev addr和1bit讀寫信號),最低位為1表示主機從從機讀數據;
- 從機響應主機控制字節ACK;
- 從機發送單字節數據信息DATA;
- 主機響應從機發送數據信息ACK;
- 循環9 10步驟可完成主機向從機連續讀數據過程,讀取最后一個字節數據時主機應響應NACK(非應答位: 接收器是主機時,在接收到最后一個字節后發送NACK已通知被控發送從機結束數據發送,并釋放SDA數據線以便主機發送停止信號P);
- 主機發送結束信號P.
雙字節地址讀時序過程:
- 主機發送開始信號S;
- 主機發送控制字節CONTROL BYTE(7bits設備地址dev addr和1bit讀寫信號),最低位為0表示主機向從機寫數據;
- 從機響應主機控制字節ACK;
- 主機發送寄存器地址信息高字節ADDRESS HIGH BYTE;
- 從機響應主機發送寄存器地址高字節ACK;
- 主機發送寄存器地址信息低字節ADDRESS LOW BYTE;
- 從機響應主機發送寄存器地址低字節ACK;
- 主機發送開始信號S;
- 主機發送控制字節CONTROL BYTE(7bits設備地址dev addr和1bit讀寫信號),最低位為1表示主機從從機讀數據;
- 從機響應主機控制字節ACK;
- 從機發送單字節數據信息DATA;
- 主機響應從機發送數據信息ACK;
- 循環11 12步驟可完成主機向從機連續讀數據過程,讀取最后一個字節數據時主機應響應NACK(非應答位: 接收器是主機時,在接收到最后一個字節后發送NACK已通知被控發送從機結束數據發送,并釋放SDA數據線以便主機發送停止信號P);
- 主機發送結束信號P.
03
IIC代碼實現
3.1 IIC目標實現功能
設計一個IIC模塊,具體要求如下:
設計一個IIC協議提供給主設備,通過查找表實現對從設備寄存器進行配置。按查找表順序lut_index依次對設備地址為lut_dev_addr的從設備寄存器進行配置,為lut_reg_addr配置寄存器數據lut_reg_data,同時將傳輸異常和傳輸結束信號引出以對傳輸過程進行監控。模塊的定義如下:
module i2c(
input rst, //復位信號
input clk, //時鐘信號
input[15:0] clk_div_cnt, //時鐘計數器
input i2c_addr_2byte, //雙字節地址
output reg[9:0] lut_index, //查找表順序號
input[7:0] lut_dev_addr, //從設備地址
input[15:0] lut_reg_addr, //寄存器地址
input[7:0] lut_reg_data, //寄存器數據
output reg error, //傳輸異常信號
output done, //傳輸結束信號
inout i2c_scl, //IIC時鐘信號
inout i2c_sda //IIC數據信號
);
3.2 Verilog代碼
1. 頂層模塊 (i2c):
module i2c(
input rst,
input clk,
input[15:0] clk_div_cnt,
input i2c_addr_2byte,
output reg[9:0] lut_index,
input[7:0] lut_dev_addr,
input[15:0] lut_reg_addr,
input[7:0] lut_reg_data,
output reg error,
output done,
inout i2c_scl,
inout i2c_sda
);
wire scl_pad_i;
wire scl_pad_o;
wire scl_padoen_o;
wire sda_pad_i;
wire sda_pad_o;
wire sda_padoen_o;
assign sda_pad_i = i2c_sda;
assign i2c_sda = ~sda_padoen_o ? sda_pad_o : 1'bz;
assign scl_pad_i = i2c_scl;
assign i2c_scl = ~scl_padoen_o ? scl_pad_o : 1'bz;
reg i2c_read_req;
wire i2c_read_req_ack;
reg i2c_write_req;
wire i2c_write_req_ack;
wire[7:0] i2c_slave_dev_addr;
wire[15:0] i2c_slave_reg_addr;
wire[7:0] i2c_write_data;
wire[7:0] i2c_read_data;
wire err;
reg[2:0] state;
localparam S_IDLE = 0;
localparam S_WR_I2C_CHECK = 1;
localparam S_WR_I2C = 2;
localparam S_WR_I2C_DONE = 3;
assign done = (state == S_WR_I2C_DONE);
assign i2c_slave_dev_addr = lut_dev_addr;
assign i2c_slave_reg_addr = lut_reg_addr;
assign i2c_write_data = lut_reg_data;
//cascatrix carson
always@(posedge clk or posedge rst)
begin
if(rst)
begin
state <= S_IDLE;
error <= 1'b0;
lut_index <= 8'd0;
end
else
case(state)
S_IDLE:
begin
state <= S_WR_I2C_CHECK;
error <= 1'b0;
lut_index <= 8'd0;
end
S_WR_I2C_CHECK:
begin
if(i2c_slave_dev_addr != 8'hff)
begin
i2c_write_req <= 1'b1;
state <= S_WR_I2C;
end
else
begin
state <= S_WR_I2C_DONE;
end
end
S_WR_I2C:
begin
if(i2c_write_req_ack)
begin
error <= err ? 1'b1 : error;
lut_index <= lut_index + 8'd1;
i2c_write_req <= 1'b0;
state <= S_WR_I2C_CHECK;
end
end
S_WR_I2C_DONE:
begin
state <= S_WR_I2C_DONE;
end
default:
state <= S_IDLE;
endcase
end
i2c_ctrl i2c_ctrl
(
.rst(rst),
.clk(clk),
.clk_div_cnt(clk_div_cnt),
// I2C signals
// i2c clock line
.scl_pad_i(scl_pad_i), // SCL-line input
.scl_pad_o(scl_pad_o), // SCL-line output (always 1'b0)
.scl_padoen_o(scl_padoen_o), // SCL-line output enable (active low)
// i2c data line
.sda_pad_i(sda_pad_i), // SDA-line input
.sda_pad_o(sda_pad_o), // SDA-line output (always 1'b0)
.sda_padoen_o(sda_padoen_o), // SDA-line output enable (active low)
.i2c_read_req(i2c_read_req),
.i2c_addr_2byte(i2c_addr_2byte),
.i2c_read_req_ack(i2c_read_req_ack),
.i2c_write_req(i2c_write_req),
.i2c_write_req_ack(i2c_write_req_ack),
.i2c_slave_dev_addr(i2c_slave_dev_addr),
.i2c_slave_reg_addr(i2c_slave_reg_addr),
.i2c_write_data(i2c_write_data),
.i2c_read_data(i2c_read_data),
.error(err)
);
endmodule
-
IIC
+關注
關注
11文章
300瀏覽量
38277 -
通信總線
+關注
關注
0文章
44瀏覽量
9844 -
SDA
+關注
關注
0文章
124瀏覽量
28118
發布評論請先 登錄
相關推薦
評論