IIC总线C语言编程问题

IIC总线C语言编程问题,第1张

你这个例程应该是用io口模仿i2c,这里你没有给出sda的定义。我理解还有程序对其进行判断if(sda==1)输出编码‘1’else 输出编码‘0’。经过for循环8次就输出了一个完整的8bit二进制数。比如temp=num=0x25sda=0x25&0x80就等于‘0x00’,这时io口输出‘0’,temp=temp<<1数据左移1位temp此时等于0x4a,再&0x80,经过8次移位io口输出的数据应该是00100101=0x25,这个数据传输结束

首先,看看你发的器件地址是否正确

使用的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()

}


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

原文地址: http://outofmemory.cn/yw/11324765.html

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

发表评论

登录后才能评论

评论列表(0条)

保存