问一个关于VHDL写的I2C协议的问题

问一个关于VHDL写的I2C协议的问题,第1张

这里有一个C语言版的,你可以自己改造一下。如果你的系统速度快的话滑启,可在SCL、SDA赋值指令后加一定的延时。

//******************启动IIC总线**************************

void IICStart(void)

{

SCL=0

SDA=1

SCL=1

SDA=0

SCL=0

SDA=1

}

//*************************停止IIC总线********************

void IICStop(void)

{

SCL=0

SDA=0

SCL=1

SDA=1

SCL=0

}

//************************检查应答位**********************

bit IICRecAck(void)

{

SCL=0

SDA=1

SCL=1

CY=SDA //返回值放在CY中

SCL=0

return(CY)

}

//***************************对IIC总线产生应答兆芹**********

void IICACK(void)

{

SDA=0

SCL=1

SCL=0

SDA=1

}

//****************************不对IIC总线产生应答************

void IICNoAck(void)

{

SDA=1

SCL=0

SCL=0

}

//*************************向IIC总线写数***********

void IICSendByte(uchar sendbyte)

{

uchar data j=8

for(j>0j--)

{

SCL=0

sendbyte<<=1 //会使CY=sendbyte^7

SDA=CY

SCL=1

}

SCL=0

}

//***********************从IIC总线读数据族让毕****************

uchar IICReceiveByte(void)

{

register receivebyte,i=8

SCL=0

while(i--)

{

SCL=1

receivebyte=(receivebyte<<1)|SDA

SCL=0

}

return(receivebyte)

}

你说的是IO模拟i2c吧,这个你参考下

#pragma ot(6,SIZE)

#define ERRORCOUNT 10

enum eepromtype {M2401,M2402,M2404,M2408,M2416,M2432,M2464,M24128,M24256}

enum eepromtype EepromType

/****************************** I2C总线 ******************************/

bit RW24XX(uchar *DataBuff,uchar ByteQuantity,uint Address,uchar ControlByte,enum eepromtype EepromType)

{

void Delay(uchar DelayCount)

void IICStart(void)

void IICStop(void)

bit IICRecAck(void)

void IICNoAck(void)

void IICAck(void)

uchar IICReceiveByte(void)

void IICSendByte(uchar sendbyte)

uchar data j,i = ERRORCOUNT

bit errorflag = 1

while (i--)

{

IICStart()

IICSendByte(ControlByte &0xfe)

if (IICRecAck())

continue

if (EepromType >M2416)

{

IICSendByte((uchar)(Address >>8))

if (IICRecAck())

continue

}

IICSendByte((uchar)Address)

if (IICRecAck())

continue

if (!(ControlByte &0x01))

{

j = ByteQuantity

errorflag = 0

while (j--)

{

IICSendByte(*DataBuff++)

if(!IICRecAck())

continue

errorflag = 1

break

}

if (errorflag==1)

continue

break

}

else

{

IICStart()

IICSendByte(ControlByte)

if (IICRecAck())

continue

while (--ByteQuantity)

{

*DataBuff++ = IICReceiveByte()

IICAck()

}

*DataBuff = IICReceiveByte() //read last byte data

IICNoAck()

errorflag = 0

break

}

}

IICStop()

if (!(ControlByte &0x01))

{

Delay(255)

Delay(255)

Delay(255)

Delay(255)

}

return(errorflag)

}

/***************** 启动总线 ********************/

void IICStart(void)

{

scl = 0

sda = 1

scl = 1

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

sda = 0

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

scl = 0

sda = 1

}

/***************** 停止IIC总线 ****************/

void IICStop(void)

{

scl = 0

sda = 0

scl = 1

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

sda = 1

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

scl = 0

}

/************** 检查应答位 *******************/

bit IICRecAck(void)

{

scl = 0

sda = 1

scl = 1

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

CY = sda//因为返回值总是放在CY中的

scl = 0

return(CY)

}

/*************** 对IIC总线产生应答 *******************/

void IICACK(void)

{

sda = 0

scl = 1

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

scl = 0

_nop_()

_nop_()

sda = 1

}

/***************** 不对IIC总线产生应答 ***************/

void IICNoAck(void)

{

sda = 1

scl = 1

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

scl = 0

}

/******************* 向IIC总线写数据 *********************/

void IICSendByte(uchar sendbyte)

{

uchar data j = 8

for (j >0j--)

{

scl = 0

sendbyte <<= 1 //无论C51怎样实现这个 *** 作,始终会使CY=sendbyte^7

sda = CY

scl = 1

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

}

scl = 0

}

/***************** 从IIC总线上读数据子程序 ******************/

uchar IICReceiveByte(void)

{

register receivebyte,i = 8

scl = 0

while (i--)

{

scl = 1

receivebyte = (receivebyte <<1) | sda

scl = 0

}

return(receivebyte)

}

/*************** 一个简单延时程序 ******************/

void Delay(uchar DelayCount)

{

while(DelayCount--)

}

void Delay_Msec(uchar t)

{

uchar i

while (t >0)

{

for (i = 0i <200i++)

{

WDT = 1

_nop_()

_nop_()

_nop_()

_nop_()

}

t--

}

}

/*************** 24C256读一个字节 *****************/

uchar Rd_24c256(uint beginbyte)

{

uchar data result

uchar i

EA = 0

i = RW24XX(&result,1,beginbyte,rd_24c256,M24256)

EA = 1

return(result)

}

/*************** 24C256写一个字节 ***************/

void Wr_24c256(uint address,uchar datum)

{

uchar i

EA = 0

i = RW24XX(&datum,1,address,wr_24c256,M24256)

Delay_Msec(10)

EA = 1

}

什么是单个数据?IIC总线就是把所需的数据经sda数据线串行传入芯片中,需敬陪手要多少传多少就是 了,我这有个以前写的IIC控制WM8731的乱雀例程,你可亮嫌以参考下

//`timescale 1ns / 1ps

module i2c_control(

clk,

i2c_sclk,

i2c_sdat,

i2c_data,

start,

tr_end,

ack,

rst,

counter,

sdo)

input clk

input [23:0]i2c_data

input start

input rst

// input w_r

inout i2c_sdat

output i2c_sclk

output tr_end

output ack

output [5:0]counter

output sdo

reg sdo

reg sclk

reg tr_end

reg [23:0]sd

reg [5:0]counter

assign i2c_sclk=sclk |(((counter>=4)&(counter<=30))?~clk:0)

assign i2c_sdat=sdo?1'bz:0

reg ack1,ack2,ack3

wire ack=ack1 |ack2 |ack3

always@(negedge rst or posedge clk)begin

if(!rst)counter<=6'b111111

else begin

if(start==0)

counter<=0

else

if(counter<6'b111111)counter<=counter+1

end

end

always@(negedge rst or posedge clk)begin

if(!rst)begin sclk<=1sdo<=1ack1<=0ack2<=0ack3<=0tr_end<=0end

else

case(counter)

6'd0 :begin ack1<=0ack2<=0ack3<=0tr_end<=0sdo<=1sclk<=1end

6'd1 :begin sd<=i2c_datasdo<=0end

6'd2 :sclk=0

6'd3 :sdo<=sd[23]

6'd4 :sdo<=sd[22]

6'd5 :sdo<=sd[21]

6'd6 :sdo<=sd[20]

6'd7 :sdo<=sd[19]

6'd8 :sdo<=sd[18]

6'd9 :sdo<=sd[17]

6'd10 :sdo<=sd[16]

6'd11 :sdo<=1'b1

6'd12 :begin sdo<=sd[15]ack1<=i2c_sdatend

6'd13 :sdo<=sd[14]

6'd14 :sdo<=sd[13]

6'd15 :sdo<=sd[12]

6'd16 :sdo<=sd[11]

6'd17 :sdo<=sd[10]

6'd18 :sdo<=sd[9]

6'd19 :sdo<=sd[8]

6'd20 :sdo<=1'b1

6'd21 :begin sdo<=sd[7]ack2<=i2c_sdatend

6'd22 :sdo<=sd[6]

6'd23 :sdo<=sd[5]

6'd24 :sdo<=sd[4]

6'd25 :sdo<=sd[3]

6'd26 :sdo<=sd[2]

6'd27 :sdo<=sd[1]

6'd28 :sdo<=sd[0]

6'd29 :sdo<=1'b1

6'd30 :begin sdo<=1'b0sclk<=1'b0ack3<=i2c_sdatend

6'd31 :sclk<=1'b1

6'd32 :begin sdo<=1'b1tr_end<=1end

endcase

end

endmodule


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/12283972.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-22
下一篇2023-05-22

发表评论

登录后才能评论

评论列表(0条)

    保存