使用的port I/O方向是否修改 检测应当前,应将date pin 改为 input
clk date delay 时间是否足够
I2C总线是各种总线中使用信号线最少,并具有自动寻址、多主机时钟同步和仲裁等功能的总线。因此,使用I2C总线设计计算机系统十分方便灵活,体积也小,因而在各类实际应用中得到广泛应用。下面举二个应用示例。
I2C的运用比如在铁电存储器中,用铁电存储数据就是用的I2C总线协议。 目前,51、96系列的单片机应用很广,但是由于它们都没有I2C总线接口,从而限制了在这些系统中使用具有I2C总线接口的器件。通过对I2C总线时序的分析,可以用51单片机的两根I/O线来实现I2C总线的功能。接I2C总线规定:SCL线和SDA线是各设备对应输出状态相“与”的结果,任一设备都可以用输出低电平的方法来延长SCL的低电平时间,以迫使高速设备进入等待状态,从而实现不同速度设备间的时钟同步。因此,即使时钟脉冲的高、低电平时间长短不一,也能实现数据的可靠传送,可以用软件控制I/O口做I2C接口。下面就是用GMS97C2051的通用I/O口来作为I2C总线接口,并由软件控制实现数据传送的例子,图6为其连线图。
在单主控器的系统中,时钟线仅由主控器驱动,因此可以用51系列的一根I/O线作为SCL的信号线,将其设置为输出方式,并由软件控制来产生串行时钟信号。在实际系统中使用了P1.3。另一根I/O线P1.2作为I2C总线的串行数据线,可在软件控制下在时钟的低电平期间读取或输出数据。系统传输数据的过程如下:先由单片机发出一个启始数据信号,接着送出要访问器件的7位地址数据,并等待被控器件的应答信号。当收到应答信号后,根据访问要求进行相应的 *** 作。如果是读入数据,则数据线可一直设为输入方式,中间不需要改变SDA线的工作方式,每读入一个字节均应依次检测应答信号;如果是输出数据,则首先将SDA设置为输出方式,当发送完一个字节后,需要改变SDA线为输入方式,此时读入被控器件的应答信号就完成了一个字节的传送。当所有数据传输完毕后,应向SDA发出一个停止信号,以结束该次数据传输。 下面给出51系列用汇编语言实现启始、停止、读、写、应答的程序,读者也可以根据I2C总线时序在96系列或其它单片机上实现I2C总线接口。
a.启动位程序
ACK:CLR P1.3
NOP
NOP
SETB P1.2
NOP
NOP
NOP
CPL P1.3 ;P1.3=1
NOP
NOP
NOP
DENGDAI:JB P1.2,DENGDAI
RET
b.读数据程序
读字节可以在当前地址读(CURRENT
READ),也可以随机读(RANDOM READ),读出数据的最后一个字节后不用加应答信号。
READ:PUSH 0EH
CLR P1.4
LCALL BSTART ;START
MOV A,#0A0H ;SEND THE CNOTROL BYTE
LCALL SENDBYTE
LCALL ACK
MOV A,R1 ;SEND THE ADDRESS
LCALL SENDBYTE
LCALL ACK
LCALL BSTART ;START
MOV A,#0A1H ;SEND THE CNOTROL BYTE
LCALL SENDBYTE
LCALL ACK
LCALL READBYTE
LCALL BSTOP
POP 0EH
RET
送字节程序:
SENDBYTE:PUSH 0EH
PUSH 00H
MOV R0,#08H
LOOP1:CLR P1.3
NOP
NOP
RLC A
MOV P1.2,C
CPL P1.3 P1.3=1
NOP
NOP
DJNZ R0,LOOP1
POP 00H
POP 0EH
RET
读字节子程序:
READBYTE:PUSH 0EH
PUSH 00H
MOV R0,#08H;READ THE CONTENT
CLR A
LOOP4:CLR P1.3
NOP
NOP
NOP
SETB P1.3 ;P1.3=1
MOV C,P1.2
RLC A
DJNZ R0,LOOP4
MOV R2,A
POP 00H
POP 0EH
RET
c.写数据程序:
WRITE:PUSH 0EH
CLR P1.4
LCALL BSTART
MOV A,#0A0H
CLALL SENDBYTE ;SEND THE CONTROL BYTE
LCALL ACK
MOV A,R1 ;SEND THE ADDRESS
LCALL SENDBYTE
LCALL ACK
MOV A,R2 ;WRITE THE CONTENT
LCALL SENDBYTE
LCALL ACK
LCALL BSTOP
POP 0EH
RET
连续写的两个字节之间最好是有10ms的延时。当然,也可以进行页写(PAGE
WRITE),即一次性连续写8个字节,但采用页写方式时每个字节后要有一个应答信号。
d.停止位程序:
BSTOP:CLR P1.3
NOP
NOP
CLR P1.2
NOP
NOP
NOP
SETB P1.3
NOP
NOP
NOP
SETB P1.2
RET // IIC开始
void Start()
{
SDA=1SCL=1NOP4()SDA=0NOP4()SCL=0
}
// IIC 结束
void Stop()
{
SDA=0SCL=0NOP4()SCL=1NOP4()SDA=1
}
// IIC 读取应答
void RACK()
{
SDA=1NOP4()SCL=1NOP4()SCL=0
}
// IIC 发送非应答
void NO_ACK()
{
SDA=1SCL=1NOP4()SCL=0SDA=0
}
// IIC向从设备写入一字节数据
void Write_A_Byte(uchar b)
{
uchar i
for(i=0i<8i++)
{
b<<=1SDA=CY_nop_()SCL=1NOP4()SCL=0
}
RACK()
}
// IIC 向从设备的指定地址写入数据
void Write_IIC(uchar addr,uchar dat)
{
Start()
Write_A_Byte(0xa0)
Write_A_Byte(addr)
Write_A_Byte(dat)
Stop()
DelayMS(10)
}
// IIC 从从设备读取数据
uchar Read_A_Byte()
{
uchar i,b
for(i=0i<8i++)
{
SCL=1b<<=1B|=SDASCL=0
}
return b
}
// IIC 从从设备的当前地址读取数据
uchar Read_Current()
{
uchar d
Start()
Write_A_Byte(0xa1)
d=Read_A_Byte()
NO_ACK()
Stop()
return d
}
// IIC 从从设备的任意地址读取数据
uchar Random_Read(uchar addr)
{
Start()
Write_A_Byte(0xa0)
Write_A_Byte(addr)
Stop()
return Read_Current()
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)