通过IIC控制EP936E
IIC读写代码
//
// I2c Byte Write Mode
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// SCL: __| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_
// ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ______________
// SDA: |_|___|___|___|___|___|___|___|_______|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|_____|
// 0 1 1 1 S3 S2 S1 W=0 ACK A7 A6 A5 A4 A3 A2 A1 A0 ACK D7 D6 D5 D4 D3 D2 D1 D0 ACK STOP
// [START] [STOP]
// |<---SLAVE ADDRESS---------->| |<-----REGISTER ADDRESS--------->| |<------------DATA------------->|
//
// I2c Byte Read Mode
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// SCL: __| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_
// ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ _ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ______
// SDA: |_|___|___|___|___|___|___|___|_______|___|___|___|___|___|___|___|___|___| |_|___|___|___|___|___|___|___| |___|___|___|___|___|___|___|___|___| |_|
// 0 1 1 1 S3 S2 S1 W=0 ACK A7 A6 A5 A4 A3 A2 A1 A0 ACK 0 1 1 1 S3 S2 S1 R=1 ACK D7 D6 D5 D4 D3 D2 D1 D0 ACK
// [START] [START] [STOP]
// |<---SLAVE ADDRESS------- --->| |<-----REGISTER ADDRESS--------->| |<-------SLAVE ADDRESS------>| |<------------DATA------------->|
//
//
//
//
//
// CLK: 50MHz
module iic_com
(
input CLK,
input RSTn,
input [1:0] Start_Sig, //read or write command
input [7:0] Addr_Sig, //eeprom words address
input [7:0] Addr_offset, //Offset Address
input [7:0] WrData, //eeprom write data
output [7:0] RdData, //eeprom read data
output Done_Sig, //eeprom read/write finish
output SCL,
inout SDA
);
parameter FPXS = 12'd500; //100Khz的时钟分频系数
parameter C1_1= FPXS[11:2]; //C1_1=FPXS/4
parameter C1_2= FPXS[11:1]; // C1_2=FPXS/2
parameter C1_3= FPXS[11:2]+FPXS[11:1]; //C1_3=(FPXS/4)*3
parameter C1_4= FPXS;
parameter C1_5= FPXS+FPXS[11:2]; //C1_3=(FPXS/4)*5
reg [4:0]i;
reg [4:0]Go;
reg [11:0]C1;
reg [7:0]rData;
reg rSCL;
reg rSDA;
reg isAck;
reg isDone;
reg isOut;
assign Done_Sig = isDone;
assign RdData = rData;
assign SCL = rSCL;
assign SDA = isOut ? rSDA : 1'bz; //SDA数据输出选择
//****************************************//
//* I2C读写处理程序 *//
//****************************************//
always @ ( posedge CLK or negedge RSTn )
if( !RSTn ) begin
i <= 5'd0;
Go <= 5'd0;
C1 <= 10'd0;
rData <= 8'd0;
rSCL <= 1'b1;
rSDA <= 1'b1;
isAck <= 1'b1;
isDone <= 1'b0;
isOut <= 1'b1;
end
else if( Start_Sig[0] ) //I2C 数据写
case( i )
0: //发送IIC开始信号
begin
isOut <= 1; //SDA端口输出
if( C1 == 0 ) rSCL <= 1'b1;
else if( C1==C1_4 ) rSCL <= 1'b0; //SCL由高变低
if( C1 == 0 ) rSDA <= 1'b1;
else if( C1==C1_2 ) rSDA <= 1'b0; //SDA先由高变低
if( C1==C1_5 -1) begin C1 <= 10'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
1: // Write Device Addr 写设备地址
begin rData <= {8'h76}; i <= 5'd8; Go <= i + 1'b1; end
2: // Wirte Word Addr 写寄存器地址
begin rData <= Addr_Sig; i <= 5'd8; Go <= i + 1'b1; end
3: // Wirte Offset Address 写页地址
begin rData <= Addr_offset; i <= 5'd8; Go <= i + 1'b1; end
4: // Write Data 写数据
begin rData <= WrData; i <= 5'd8; Go <= i + 1'b1; end
5: //发送IIC停止信号
begin
isOut <= 1'b1;
if( C1 == 0 ) rSCL <= 1'b0;
else if( C1==C1_1 ) rSCL <= 1'b1; //SCL先由低变高
if( C1 == 0 ) rSDA <= 1'b0;
else if( C1==C1_3 ) rSDA <= 1'b1; //SDA由低变高
if( C1==C1_5 -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
6:
begin isDone <= 1'b1; i <= i + 1'b1; end //写I2C 结束
7:
begin isDone <= 1'b0; i <= 5'd0; end
8,9,10,11,12,13,14,15: //发送Device Addr/Word Addr/Write Data
begin
isOut <= 1'b1;
rSDA <= rData[15-i]; //高位先发送
if( C1 == 0 ) rSCL <= 1'b0;
else if( C1==C1_1 ) rSCL <= 1'b1; //SCL高电平100个时钟周期,低电平100个时钟周期
else if( C1==C1_3 ) rSCL <= 1'b0;
if( C1==C1_4 -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end //产生250Khz的IIC时钟
else C1 <= C1 + 1'b1;
end
16: // waiting for acknowledge
begin
isOut <= 1'b0; //SDA端口改为输入
if( C1==C1_2 ) isAck <= SDA; //读取IIC 从设备的应答信号
if( C1 == 0 ) rSCL <= 1'b0;
else if( C1==C1_1 ) rSCL <= 1'b1; //SCL高电平100个时钟周期,低电平100个时钟周期
else if( C1==C1_3 ) rSCL <= 1'b0;
if( C1==C1_4 -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end //产生250Khz的IIC时钟
else C1 <= C1 + 1'b1;
end
16:
if( isAck != 0 ) i <= 5'd0;
else i <= 5'd0;
// else i <= Go;
endcase
else if( Start_Sig[1] ) //I2C 数据读
case( i )
0: // Start
begin
isOut <= 1; //SDA端口输出
if( C1 == 0 ) rSCL <= 1'b1;
else if( C1==C1_4 ) rSCL <= 1'b0; //SCL由高变低
if( C1 == 0 ) rSDA <= 1'b1;
else if( C1==C1_2 ) rSDA <= 1'b0; //SDA先由高变低
if( C1==C1_5 -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
1: // Write Device Addr(设备地址)
begin rData <= 8'h76; i <= 5'd10; Go <= i + 1'b1; end
2: // Wirte Word Addr(EEPROM的写地址)
begin rData <= Addr_Sig; i <= 5'd10; Go <= i + 1'b1; end
3: // Wirte Offset Address 写页地址
begin rData <= Addr_offset; i <= 5'd10; Go <= i + 1'b1; end
4: // Start again
begin
isOut <= 1'b1;
if( C1 == 0 ) rSCL <= 1'b0;
else if( C1==C1_1 ) rSCL <= 1'b1;
else if( C1==C1_5 ) rSCL <= 1'b0;
if( C1 == 0 ) rSDA <= 1'b0;
else if( C1==C1_1 ) rSDA <= 1'b1;
else if( C1==C1_3 ) rSDA <= 1'b0;
if( C1 == 300 -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
5: // Write Device Addr ( Read )
begin rData <= 8'h77; i <= 5'd10; Go <= i + 1'b1; end
6: // Read Data
begin rData <= 8'd0; i <= 5'd20; Go <= i + 1'b1; end
7: // Stop
begin
isOut <= 1'b1;
if( C1 == 0 ) rSCL <= 1'b0;
else if( C1==C1_1 ) rSCL <= 1'b1;
if( C1 == 0 ) rSDA <= 1'b0;
else if( C1==C1_3 ) rSDA <= 1'b1;
if( C1==C1_5 -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
8: //写I2C 结束
begin isDone <= 1'b1; i <= i + 1'b1; end
9:
begin isDone <= 1'b0; i <= 5'd0; end
10,11,12,13,14,15,16,17: //发送Device Addr(write)/Word Addr/Device Addr(read)
begin
isOut <= 1'b1;
rSDA <= rData[16-i]; //高位先发送
if( C1 == 0 ) rSCL <= 1'b0;
else if( C1==C1_1 ) rSCL <= 1'b1; //SCL高电平100个时钟周期,低电平100个时钟周期
else if( C1==C1_3 ) rSCL <= 1'b0;
if( C1==C1_4 -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end //产生250Khz的IIC时钟
else C1 <= C1 + 1'b1;
end
18: // waiting for acknowledge
begin
isOut <= 1'b0; //SDA端口改为输入
if( C1==C1_2 ) isAck <= SDA; //读取IIC 的应答信号
if( C1 == 0 ) rSCL <= 1'b0;
else if( C1==C1_1 ) rSCL <= 1'b1; //SCL高电平100个时钟周期,低电平100个时钟周期
else if( C1==C1_3 ) rSCL <= 1'b0;
if( C1==C1_4 -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end //产生250Khz的IIC时钟
else C1 <= C1 + 1'b1;
end
19:
if( isAck != 0 ) i <= 5'd0; // if( isAck != 0 ) i <= 5'd0;
else i <= Go;
20,21,22,23,24,25,26,27: // Read data
begin
isOut <= 1'b0;
if( C1==C1_2 ) rData[26-i] <= SDA; //高位先接收
if( C1 == 0 ) rSCL <= 1'b0;
else if( C1==C1_1 ) rSCL <= 1'b1; //SCL高电平100个时钟周期,低电平100个时钟周期
else if( C1==C1_3 ) rSCL <= 1'b0;
if( C1==C1_4 -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end //产生250Khz的IIC时钟
else C1 <= C1 + 1'b1;
end
28: // no acknowledge
begin
isOut <= 1'b1;
if( C1 == 0 ) rSCL <= 1'b0;
else if( C1==C1_1 ) rSCL <= 1'b1;
else if( C1==C1_3 ) rSCL <= 1'b0;
if( C1==C1_4 -1 ) begin C1 <= 10'd0; i <= Go; end
else C1 <= C1 + 1'b1;
end
endcase
endmodule