⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c

📁 用于Slave I2C得读写,此代码针对特定得芯片,但对其他得芯片也有借鉴作用.
💻 C
字号:
/*
**********************************************************************************************
* Project:	T8Lib
* File:		i2c.c
* Contents:
*           The i2c module c file
*           use GPIO to control SDA and SCL, communicate with T8
* $Date: 10/13/05    Michal    T8R01LIB v0.1  initial
* $Date: 11/29/05    Michal    T8R01LIB v0.2  test finish  both 51 and MCF5249
* $Date: 11/30/05    Michal    T8R01LIB v0.3  make lib OK  on  MCF5249
* $Date: 12/01/05    Michal    T8R01LIB v0.4  Add HW_IIC ,HW_SPI macro
* $Date: 12/02/05    Michal    T8R01LIB v0.5  Add  function below
*                 static void DoXX(BYTE* out ,BYTE* in,BYTE len,BOOL mode)
*                 static BOOL DoComunication(BYTE* array, BYTE len,BOOL mode)
*

*
*                Moidfy some *Cmd Fuction and Reply() function
* $Date: 12/05/05    Michal    T8R02LIB v0.1  Add errcode1 to identify T8 off i2c bus state
* $Date: 12/29/05 Michal T8R02LIB v0.2
	             Modify InitezT8(BOOL mode ) to BOOL  InitezT8Lib(BOOL ComMod,BYTE I2cSlvAdr,BOOL I2cIsHigh,BYTE SpiCLkMod,WORD SpiRate,BYTE *key);
                        void I2c_Init( ); void I2c_Sel( BYTE  SlvAdr, BOOL isHigh)  to void I2c_Init(BYTE  SlvAdr, BOOL isHigh);
                        void  Spi_Init();BOOL  Spi_ClkSel(BYTE mode, WORD rate);  To void  Spi_Init(BYTE mode, WORD rate);
                 Delete void SpiClkSelOpr(BYTE mode, WORD rate) ;
                        void I2c_Sel( BYTE  SlvAdr, BOOL isHigh);
                        void SetXXKey(BYTE* key);
* $Date: 12/29/05 Michal T8R02LIB v0.5 test communiction at 400khz speed  is OK
* Copyright (c) 2005 Fameg, Inc. All rights reserved
***********************************************************************************************
*/

#include "ezT8.h"
#include "I2c.h"


#if  SW_IIC


static BOOL iHighMode;
BYTE  BusSlvAdr=0xEA;     //default I2c bus slave address for communiction

static void Stop_I2c();
static void Ack_I2c(BOOL a);
static BYTE  I2cRcvByte();


//Pin operation
#if 1
	void  WritePinSCL(){SCL=1;	}

	void ClearPinSCL(){SCL=0;}

	void  setSDAin(){}
	void  setSDAout(){}

	void WritePinSDA(){SDA=1;}
	void ClearPinSDA(){SDA=0;}

	BOOL ReadPinSDA(){return(SDA);}
	void InitReadAck(){SDA=1;}
//Delay
	void Delay_0_5us(unsigned char cnt)
   {
  //  unsigned char ct=1;
	while(cnt--)
	{
	//    	while(ct--);
	//	asm("nop");
	//	ct=1;
	}
   }

 #else
	#define   WritePinSCL() SCL=1

	#define   ClearPinSCL() SCL=0

	#define    setSDAin() /##/
	#define    setSDAout()/##/

	#define   WritePinSDA() SDA=1
	#define   ClearPinSDA() SDA=0

	#define   ReadPinSDA()  SDA
	#define   InitReadAck() SDA

//Delay
    BYTE delay;
//	#define Delay_0_5us(cnt)	//{/*delay =cnt ;while(delay--);*/} /##/
	void Delay_0_5us(unsigned char cnt)
   {
  //  unsigned char ct=1;
//	while(cnt--)
//	{
	//    	while(ct--);
	//	asm("nop");
	//	ct=1;
//	}
   }

#endif

void I2c_Init(BYTE  SlvAdr,BOOL isHigh)
{
    /* SDA */
	iHighMode=isHigh;
	BusSlvAdr=SlvAdr;
    Stop_I2c();
}


/*void I2c_Sel( BYTE  SlvAdr,BOOL isHigh)
{
  iHighMode=isHigh;
  BusSlvAdr=SlvAdr;
}*/

/*******************************************************************
                     起动总线函数
函数原型: void  Start_I2c();
功能:       启动I2C总线,即发送I2C起始条件.

********************************************************************/
void Start_I2c()
{
  setSDAout();
  WritePinSDA();
  Delay_0_5us(10)  ;   /*发送结束条件的时钟信号*/
  WritePinSCL();
  Delay_0_5us(10);    /*起始条件建立时间大于4.7us,延时*/

  ClearPinSDA();      /*发送起始信号*/
  Delay_0_5us(10);    /* 起始条件锁定时间大于4μs*/

  ClearPinSCL();   /*钳住I2C总线,准备发送或接收数据 */
//  Delay_0_5us(2);
}


/*******************************************************************
                      结束总线函数
函数原型: void  Stop_I2c();
功能:       结束I2C总线,即发送I2C结束条件.

********************************************************************/
static void Stop_I2c()
{
   setSDAout();
   ClearPinSDA();  /*发送结束条件的数据信号*/
   Delay_0_5us(10)  ;   /*发送结束条件的时钟信号*/
   WritePinSCL();  /*结束条件建立时间大于4μs*/
   Delay_0_5us(10);
   WritePinSDA();  /*发送I2C总线结束信号*/
   Delay_0_5us(10);
}




/*******************************************************************
                 字节数据传送函数
函数原型: void  I2cSendByte(BYTE c);
功能:  将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
     此状态位进行操作.(不应答或非应答都使ack=0 假)
     发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
********************************************************************/
BOOL  I2cSendByte(BYTE c)
{
 BYTE BitCnt;
 BOOL t,ack;

 setSDAout();
 for(BitCnt=0x80;BitCnt!=0;BitCnt=BitCnt>>1)  /*要传送的数据长度为8位*/
 {

	 if(iHighMode==true)
	     Delay_0_5us(1);
	 else
         Delay_0_5us(4);

     if(c&BitCnt)
     {
//        t=SDA;
         WritePinSDA();   /*判断发送位*/
      }
     else
         ClearPinSDA();

	 if(iHighMode)
         Delay_0_5us(1);
	 else
         Delay_0_5us(4);


//        t=SCL;
     WritePinSCL();/*置时钟线为高,通知被控器开始接收数据位*/

	 if(iHighMode)         /*保证时钟高电平周期大于4μs*/
	 {
        Delay_0_5us(1);
        Delay_0_5us(1);
		}
	 else
	 {
        Delay_0_5us(4);
        Delay_0_5us(4);
     }
     ClearPinSCL();
     // InitReadAck();          //11.22 add
   }      //9 clocks


/*       if(iHighMode)
	 {
        Delay_0_5us(1);
		}
	 else
	 {
        Delay_0_5us(4);
 	 	}*/
      //WritePinSDA
      InitReadAck();

     if(iHighMode)
	 {
        Delay_0_5us(1);
        Delay_0_5us(1);

 		}
	 else
	 {
        Delay_0_5us(4);
        Delay_0_5us(4);
      }

     WritePinSCL();   //9 clock

//     ReadPinSDA(t)    //first read

	 if(iHighMode)
	 	Delay_0_5us(1);
	 else
        Delay_0_5us(4);


     t=ReadPinSDA();     //second read

     if(t==1)
         ack=0;
     else
         ack=1;        /*判断是否接收到应答信号*/


	 if(iHighMode)
	 	Delay_0_5us(1);
	 else
        Delay_0_5us(4);
     ClearPinSCL();             //钳住总线 9 clock end



	 if(iHighMode)
	 	Delay_0_5us(1);
	 else
        Delay_0_5us(4);
	return ack;
}


/*******************************************************************
                 字节数据传送函数
函数原型: BYTE  I2cRcvByte();
功能:  用来接收从器件传来的数据,并判断总线错误(不发应答信号),
     发完后请用应答函数。
********************************************************************/
static BYTE  I2cRcvByte()
{
  BYTE retc;
  BYTE BitCnt;
  BOOL t;

    retc=0;

    WritePinSDA();             /*置数据线为输入方式*/
    setSDAin();
	for(BitCnt=0;BitCnt<8;BitCnt++)
      {
         ClearPinSCL();       /*置时钟线为低,准备接收数据位*/
    	 if(iHighMode)         /*保证时钟高电平周期大于4μs*/
           Delay_0_5us(2);
	     else
           Delay_0_5us(8);


         WritePinSCL();       /*置时钟线为高使数据线上数据有效*/

      	 if(iHighMode)
           Delay_0_5us(2);
	     else
           Delay_0_5us(8);

         retc=retc<<1;
	     t=ReadPinSDA();

         if(t==1)
		     retc=retc+1; /*读数据位,接收的数据位放入retc中 */

      }
  ClearPinSCL();
  Delay_0_5us(2);
  return(retc);
}



/********************************************************************
                     应答子函数
原型:  void Ack_I2c(BOOL a);

功能:主控器进行应答信号,(可以是应答或非应答信号)
********************************************************************/
static void Ack_I2c(BOOL a)
{
   setSDAout();
  if(a==0)
     ClearPinSDA();     /*在此发出应答或非应答信号 */
  else
     WritePinSDA();
  Delay_0_5us(3);

  WritePinSCL();
  Delay_0_5us(10);
	                         /*时钟低电平周期大于4μs*/
  ClearPinSCL();                /*清时钟线,钳住I2C总线以便继续接收*/
  Delay_0_5us(2);
}



/*******************************************************************
                    向有子地址器件发送多字节数据函数
函数原型: BOOL  I2c_SendStr(BYTE sla,BYTE *s,WORD no);
功能:     从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
          地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
           如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
********************************************************************/
BYTE I2c_SendStr(BYTE sla,BYTE *s,WORD no)
{
   BYTE i;
   BOOL ack;

   #if COMENINT==1
   vDisableIsrs();//add
   #endif
   Start_I2c();               /*启动总线*/
   sla = sla;// << 1;
   ack = I2cSendByte(sla);            /*发送器件地址*/
   if(ack==0)
    {
              Stop_I2c();
		#if COMENINT==1
	       vEnableIsrs();//add
	    #endif
              return 0xff;    //slave ack not exist
     }

    for(i=0;i<no;i++)
    {
     ack=I2cSendByte(*s);               /*发送数据*/
  /*    if(ack==0)
     {
            Stop_I2c();
		#if COMENINT==1
    	       vEnableIsrs();//add
	        #endif
             return(i+1);    //error byte index
      }     */
     s++;
    }
 Stop_I2c();                 /*结束总线*/
 #if COMENINT==1
 vEnableIsrs();//add
 #endif
  return(0);
}


/*******************************************************************
                    向有子地址器件读取多字节数据函数
函数原型: BOOL  I2c_RcvStr(BYTE sla,BYTE *s,WORD Len);
功能:     从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
          地址sla,子地址suba,读出的内容放入s指向的存储区,读Len个字节。
           如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
********************************************************************/
BYTE I2c_RcvStr(BYTE sla,BYTE *s,WORD Len)
{
   WORD i;
   BOOL ack;

   #if COMENINT==1
   vDisableIsrs();//add
   #endif
   Start_I2c();               /*启动总线*/
   sla=sla+1;
   ack=I2cSendByte(sla);
   if(ack==0)                //slave ack not exist
   {
             Stop_I2c();
	      #if COMENINT==1
   	      vEnableIsrs();//add
	      #endif
             return(0xff);
   }


   for(i=0;i<Len-1;i++)
   {
     *s=I2cRcvByte();            /*读取数据*/
      Ack_I2c(0);                /*发送就答位*/
      s++;
   }
   *s=I2cRcvByte();
    Ack_I2c(1);                 /*发送非应位*/
    Stop_I2c();                    /*结束总线*/

#if COMENINT==1
   vEnableIsrs();//add
    #endif
  return(0);
}

#elif (IIC_USED==0 )//!SW_IIC   both SW_IIC and HW_IIC are not needed, define dummy functions
BYTE  BusSlvAdr=0x62;     //default I2c bus slave address for communiction
void I2c_Init( )
{
}
void I2c_Sel( BYTE  SlvAdr,BOOL isHigh)
{
}

BYTE I2c_SendStr(BYTE sla,BYTE *s,WORD no)
{
}
BYTE I2c_RcvStr(BYTE sla,BYTE *s,WORD no)
{
}
#endif  //SW_IIC

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -