
I2C总线编程
2个回答
展开全部
没有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_();
}
下面是汇编的:
;;-----启动-----;;
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_();
}
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询