这是我第一次写,希望能够开个好头,以后能够坚持记录自己工作中遇到的问题及解决方法。也希望能够帮助到有需要的人。
程序测试OK,可以直接用。
i2c之汇编程序
;================================================================
F_Load_EEPRstAddrID:
MOVIA 0x00
MOVAR R_Temp0
MOVIA 0x25
MOVAR P_DPTR_IPR
MOVIA 2
MOVAR R_Temp1
RET
F_Load_EEPRstAddr:
MOVIA 0x08
MOVAR R_Temp0
MOVIA 0x28
MOVAR P_DPTR_IPR
MOVIA 2
MOVAR R_Temp1
RET
;================================================================
;Input : Addr=R_Temp0 Read_Data=R_Temp1
;Output : P_DPTR_IPR
;================================================================
F_ReadEPP_ToRam:
MOVIA D_EEPDevAddr_WR ;Device Addr
LCALL F_I2C_Start
MOVR R_Temp0,A
LCALL F_I2C_WByte
MOVIA D_EEPDevAddr_RD ;Device Addr
LCALL F_I2C_Start
LGOTO L_LoadEEP_RLpB
L_LoadEEP_RLpA:
LCALL F_I2CSend_ACK
L_LoadEEP_RLpB:
LCALL F_I2C_RByte
MOVAR P_Index_IPR
INCR P_DPTR_IPR,R
BCR P_DPTR_IPR,Bit6
DECRSZ R_Temp1,R
LGOTO L_LoadEEP_RLpA
LCALL F_I2CSend_NACK
LGOTO F_I2C_Stop
;****************************************************************
;Input: Addr=R_Temp0 Write_Data=R_Temp1
;================================================================
F_WriteEPP_Ram:
MOVIA D_EEPDevAddr_WR ;Device Addr
LCALL F_I2C_Start
MOVR R_Temp0,A
LCALL F_I2C_WByte
L_LoadRam_WLp:
MOVR P_Index_IPR,A
LCALL F_I2C_WByte
INCR P_DPTR_IPR,R
BCR P_DPTR_IPR,Bit6
DECRSZ R_Temp1,R
LGOTO L_LoadRam_WLp
F_I2C_Stop:
BCR P_PortA,IO_I2C_SDA
LCALL F_Delay_5us
BSR P_PortA,IO_I2C_SCK
LCALL F_Delay_5us
BSR P_PortA,IO_I2C_SDA
RET
;****************************************************************
;****************************************************************
F_I2C_Start:
BSR P_PortA,IO_I2C_SDA
LCALL F_Delay_5us
BSR P_PortA,IO_I2C_SCK
LCALL F_Delay_5us
BCR P_PortA,IO_I2C_SDA
LCALL F_Delay_5us
BCR P_PortA,IO_I2C_SCK
F_I2C_WByte:
MOVAR R_TempAcc
MOVIA 248
L_I2CWBit_Lp:
BCR P_PortA,IO_I2C_SDA
BTRSC R_TempAcc,Bit7
BSR P_PortA,IO_I2C_SDA
; LCALL F_Delay_5us
BCR P_Status,B_PSW_C
RLR R_TempAcc,R
BSR P_PortA,IO_I2C_SCK
LCALL F_Delay_5us
ADDIA 1
BCR P_PortA,IO_I2C_SCK
; LCALL F_Delay_5us
BTRSS P_Status,B_PSW_Z
LGOTO L_I2CWBit_Lp
L_I2CWBit_Ack:
BCR P_PortA,IO_I2C_SDA
MOVIA 01111111B
IOST P_APHCON
MOVIA D_I2C_SDA /*开启上拉,设为输入*/
IOST P_PortA_Ctrl
BSR P_PortA,IO_I2C_SCK
MOVIA 245
L_I2CWBit_AckLp: /*等待slave 发ACK*/
LCALL F_Delay_5us
BTRSS P_PortA,IO_I2C_SDA
LGOTO L_I2CWBit_AckOK
ADDIA 1
BTRSS P_Status,B_PSW_Z
LGOTO L_I2CWBit_AckLp
L_I2CWBit_AckOK:
BCR P_PortA,IO_I2C_SCK
LCALL F_Delay_5us
MOVIA 11111111B /*关闭上拉,设为输出*/
IOST P_APHCON
MOVIA 00000000B
IOST P_PortA_Ctrl
LGOTO L_RstI2C_Out
;****************************************************************
F_I2C_RByte:
MOVIA 01111111B /*开启上拉,设为输入*/
IOST P_APHCON
MOVIA D_I2C_SDA
IOST P_PortA_Ctrl
LCALL F_Delay_5us
MOVIA 248
L_I2CRBit_Lp:
LCALL F_Delay_5us
BSR P_PortA,IO_I2C_SCK
LCALL F_Delay_5us
RLR R_TempAcc,R
BCR R_TempAcc,Bit0
BTRSC P_PortA,IO_I2C_SDA
BSR R_TempAcc,Bit0
BCR P_PortA,IO_I2C_SCK
ADDIA 1
BTRSS P_Status,B_PSW_Z
LGOTO L_I2CRBit_Lp
MOVIA 11111111B /*关闭上拉,设为输出*/
IOST P_APHCON
MOVIA 00000000B
IOST P_PortA_Ctrl
MOVR R_TempAcc,A
RET
;================================================================
F_I2CSend_ACK:
BCR P_PortA,IO_I2C_SDA
LCALL F_Delay_5us
LGOTO L_I2CSend_XAck
F_I2CSend_NACK:
BSR P_PortA,IO_I2C_SDA
LCALL F_Delay_5us
L_I2CSend_XAck:
BSR P_PortA,IO_I2C_SCK
LCALL F_Delay_5us
L_RstI2C_Out:
BCR P_PortA,IO_I2C_SCK
LCALL F_Delay_5us
BCR P_PortA,IO_I2C_SDA
RET
;================================================================
;================================================================
i2c之C程序
/* ************************************************************ */
void F_I2C_SCKH(void)
{
IO_I2C_SCK = 1;
F_Delay_Xus(3);
}
/* ************************************************************ */
void F_I2C_SCKL(void)
{
IO_I2C_SCK = 0;
F_Delay_Xus(3);
}
/* ************************************************************ */
void F_I2C_SDAH(void)
{
IO_I2C_SDA = 1;
F_Delay_Xus(3);
}
/* ************************************************************ */
void F_I2C_SDAL(void)
{
IO_I2C_SDA = 0;
F_Delay_Xus(3);
}
/* ************************************************************ */
Bit F_I2C_Start(Byte D_I2C_DevAddr)
{
Byte R_TempAcc;
R_TempAcc=D_I2C_DevAddr;
F_I2C_SDAH();
F_I2C_SCKH();
F_I2C_SDAL();
F_I2C_SCKL();
return(F_I2C_WByte(R_TempAcc));
}
/* ************************************************************ */
void F_I2C_Stop(void)
{
F_I2C_SDAL();
F_I2C_SCKH();
F_I2C_SDAH();
}
/* ************************************************************ */
Bit F_I2C_WACK(void)
{
Byte i;
Bit j=0;
F_I2C_SDAH();
//空 //开启上拉,设为输入
F_I2C_SCKH();
for(i=0;i<40;i++)
{
// _nop_();
if(IO_I2C_SDA == 0)
{
j = 1;
break;
}
}
//空 //关闭上拉,设为输出
IO_I2C_SCK = LOW;
F_I2C_SDAL();
return(j);
}
/* ************************************************************ */
Bit F_I2C_WByte(Byte R_WD_Data)
{
Byte i;
for(i=0;i<8;i++)
{
if(R_WD_Data&0x80) F_I2C_SDAH();
else F_I2C_SDAL();
F_I2C_SCKH();
R_WD_Data = R_WD_Data<<1;
F_I2C_SCKL();
}
return(F_I2C_WACK());
}
/* ************************************************************ */
Byte F_I2C_RByte(void)
{
Byte i,R_RD_Data=0;
//空 //开启上拉,设为输入
F_Delay_Xus(2);
for(i=0;i<8;i++)
{
F_I2C_SCKH();
// _nop_();
R_RD_Data = R_RD_Data<<1;
if(IO_I2C_SDA == HIGH) R_RD_Data |= 0x01;
else R_RD_Data &= 0xFE;
F_I2C_SCKL();
}
//空 //关闭上拉,设为输出
return(R_RD_Data);
}
/* ************************************************************ */
void F_I2C_RACK(void)
{
F_I2C_SDAL();
F_I2C_SCKH();
F_I2C_SCKL();
}
/* ************************************************************ */
void F_I2C_RNACK(void)
{
F_I2C_SDAH();
F_I2C_SCKH();
F_I2C_SCKL();
F_I2C_SDAL();
}
/* ************************************************************ */
void F_EEP_Write(Byte D_EEP_Addr, Byte D_WD_Num, Byte DATA *R_WDBuf_Addr)
{
Byte R_TempAcc;
Byte i;
F_I2C_Start(D_EEPDevAddr_WR);
R_TempAcc=D_EEP_Addr;
F_I2C_WByte(R_TempAcc);
for(i=0;i<D_WD_Num;i++)
{
R_TempAcc = *R_WDBuf_Addr;
F_I2C_WByte(R_TempAcc);
++R_WDBuf_Addr;
}
F_I2C_Stop();
}
/* ************************************************************ */
void F_EEP_Read(Byte D_EEP_Addr, Byte D_RD_Num, Byte DATA *R_RDBuf_Addr)
{
Byte R_TempAcc;
Byte i;
F_I2C_Start(D_EEPDevAddr_WR);
R_TempAcc=D_EEP_Addr;
F_I2C_WByte(R_TempAcc);
F_I2C_Start(D_EEPDevAddr_RD);
for(i=0;i<D_RD_Num;i++)
{
*R_RDBuf_Addr = F_I2C_RByte();
++R_RDBuf_Addr;
if(i==D_RD_Num-1) F_I2C_RNACK();
else F_I2C_RACK();
}
F_I2C_Stop();
}
/* ************************************************************ */
注意:在写启动信号的时候,先SDA-->HIGH,再SCL-->HIGH。这样避免了停止信号的出现。