I2C总线编程

I2C总线编程,第1张

没有4位机制,有8位51单片机的汇编程序。还有一个C语言的,可以给你参考,这都是我项目中用到的程序。给你作个参考,在产品的实际工作中也很稳定。

下面是汇编的:

-----启动-----

START1:

LCALL DEL5US

SETB SDA1

LCALL DEL5US

SETB SCL1

LCALL DEL5US

CLR SDA1

LCALL DEL5US

CLR SCL1

LCALL DEL5US

RET

-----结束-----

STOP1:

LCALL DEL5US

SETB SCL1

LCALL DEL5US

SETB SDA1

LCALL DEL5US

RET

-----应答检查-----

CACK1:

SETB SDA1

LCALL DEL5US

SETB SCL1

LCALL DEL5US

MOV C,SDA1

JC CACK1

CLR SCL1

CLR SDA1

LCALL DEL1MS

RET

-----应答-----

MACK1:

CLR SDA1

LCALL DEL5US

SETB SCL1

LCALL DEL5US

CLR SCL1

LCALL DEL5US

SETB SDA1

RET

-----向从器件指定单元写N个字节数据-----

入口:传递的地址在POINTER,数据在WR_BUF中,发送字节数在N中

资源占用:ACC、R0、R1、R3、C

WR_NB1:

CLR EA

SETB SDA1

SETB SCL1

LCALL START1

MOV A,#0A2H

LCALL WR8BIT1

LCALL CACK1

MOV A,POINTER

LCALL WR8BIT1

LCALL CACK1

MOV R3,N

MOV R1,#WR_BUF

WRNB11:

MOV A,@R1

LCALL WR8BIT1

LCALL CACK1

INC R1

DJNZ R3,WRNB11

LCALL STOP1

LCALL DEL10MS

SETB EA

RET

-----从从器件指定单元读N个字节数据-----

入口:传递的地址在POINTER,接收数据缓冲区RD_BUF,接收字节数在N中

资源占用:ACC、R0、R1、R3、C

RD_NB1:

MOV R3,N

RDNB11:

LCALL START1

MOV A,#0A2H

LCALL WR8BIT1

LCALL CACK1

MOV A,POINTER

LCALL WR8BIT1

LCALL CACK1

LCALL START1

MOV A,#0A3H#0A1H

LCALL WR8BIT1

LCALL CACK1

MOV R1,#RD_BUF

RDB1: LCALL RD8BIT1

MOV @R1,A

DJNZ R3,SACK1

LCALL STOP1

RET

SACK1:INC R1

LCALL MACK1

SJMP RDB1

-----字节发送-----

入口:要发送的数据在ACC中

每发送完一个字节,要调用一次CACK,以判断是否有应答

WR8BIT1:

PUSH ACC

MOV R0,#08H

WR_BIT1:

RLC A

MOV SDA1,C

LCALL DEL5US

SETB SCL1

LCALL DEL5US

CLR SCL1

DJNZ R0,WR_BIT1

POP ACC

RET

-----字节接收-----

出口:接收到的数据在ACC中

每接收完一个字节,要调用一MCACK/MNACK

RD8BIT1:

MOV R0,#08H

RD_BIT1:

SETB SDA1

LCALL DEL5US

SETB SCL1

LCALL DEL5US

MOV C,SDA1

RLC A

LCALL DEL5US

CLR SCL1

DJNZ R0,RD_BIT1

CLR SDA1

RET

以下的程序是C语言的程序,用于读24C01存贮器,稍加修改可以用于所有的I2C总线驱动。

/******************************************************************

** 名 称:ReadIIC_24C01

** 功 能:读24c01指定的地址的数据

** 输 入: address 24c01的地址

** 输 出: ddata 读出的数据

** 全局变量: 无

** 调用模块: write_8bit()delay()

** 备注:

******************************************************************/

uint8 ReadIIC_24C01(uint8 data address)

{

uint8 data ddata=0

uint8 data i=8

_nop_()

_nop_()

_nop_()

EA=0

SCL=1

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_() //Tsu:STA

SDA=0

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()//Thd:STA

SCL=0//START

write_8bit( (address<<1) | 0x01) //写页地址和 *** 作方式

ACK_R()

while (i--)

{

SDA=1

ddata<<=1

SCL=0

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

SCL=1

if (SDA) ddata|=0x01

}

SCL=0

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

SCL=1

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

SDA=0

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

SCL=1

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

SDA=1 //STOP

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

EA=1

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

delay(50)

_nop_()

_nop_()

_nop_()

return ddata

}

/******************************************************************

** 名 称:WriteIIC_24C01

** 功 能:将数据写入24c01指定地址

** 输 入: address 24c01的地址

** ddata 待写入的数据

** 输 出: 无

** 全局变量: 无

** 调用模块: write_8bit()delay()

** 备注:

******************************************************************/

void WriteIIC_24C01(uint8 data address,uint8 data ddata)

{

_nop_()

_nop_()

_nop_()

EA=0

SCL=1

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_() //Tsu:STA

SDA=0

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()//Thd:STA

SCL=0//START

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

write_8bit( (address<<1) &0xfe) //写页地址和 *** 作方式,对于24C32-24C256,page不起作用

ACK_R()

write_8bit(ddata) //发送数据

ACK_R()

SDA=0

_nop_()

_nop_()

_nop_()

SCL=1

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

SDA=1 //STOP

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

EA=1

_nop_()

_nop_()

_nop_()

delay(50)

_nop_()

_nop_()

_nop_()

}

/******************************************************************

** 名 称:write_8bit

** 功 能:将一个字节数据写入24c01

** 输 入: 无

** 输 出: 无

** 全局变量: 无

** 调用模块: 无

** 备注:

******************************************************************/

void write_8bit(uint8 data ch)

{

uint8 data i=8

_nop_()

_nop_()

_nop_()

SCL=0

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

while (i--)

{

SDA=(bit)(ch&0x80)

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

ch<<=1

SCL=1

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

SCL=0

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

}

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

}

/******************************************************************

** 名 称:ACK_R

** 功 能:等待24c01ACK信号

** 输 入: 无

** 输 出: 无

** 全局变量: 无

** 调用模块: 无

** 备注:

******************************************************************/

void ACK_R(void)

{

_nop_()

_nop_()

_nop_()

SDA=1

SCL=0

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

SCL=1

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

while(SDA)

{

_nop_()

} //ACK

SCL=0

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

}

第二种写法是对的

I2C开始时序(START)的定义为,SCL为高的时候,SDA由高转为低。可以理解为,初始状态即为SDA、SCL均为高。故在SDA SCL的初始状态加delay没有意义

I2C总线协议规定:,在SCL保持高电平期间,SDA上的电平出现负跳变,定义为I2C总线的启动信号,它标志着一次数据传输的开始

for(i=0i<8i++) //传输8位数据

{

scl=1//串行时钟信号线高电平有效

delay() //延时

k=(k<<1)|sda;//每传输一位后,向左移1位,传输下一位数据。至于为什么或SDA,应该不会这么写吧,具体问题中是不同

}

以上只是个人观点


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

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

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

发表评论

登录后才能评论

评论列表(0条)

保存