i2c之汇编和C程序

这是我第一次写,希望能够开个好头,以后能够坚持记录自己工作中遇到的问题及解决方法。也希望能够帮助到有需要的人。

程序测试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。这样避免了停止信号的出现。

 

上一篇:Master RenderMan Procedural Primitive DSO


下一篇:Hbase