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

📄 i2c_module.c

📁 一个电表的程序
💻 C
字号:
/*===========================================================================
* 			 2006年。三星仪表SOC芯片开发项目
*
*
* 文件名称:Show_Module.c
* 文件标识:
* 摘    要:
*
*
* 当前版本:Ver 1.0
* 作    者:罗冬生
* 修改内容:
* 修改日期:
* 完成日期:

===============================================================================================*/
#ifndef   _I2C_Module_
#define   _I2C_Module_

//===============================================================================================

#include "includes.h"

//===============================================================================================


#define I2CRead  0x01
#define I2CWrite 0x00

//===============================================================================================

void DelayMs(unsigned char delay)
{
  unsigned char i;
  while (delay--)
  {
    for (i=0;i<255;i++)
     {
      asm(" NOP ");
      asm(" NOP ");
      asm(" NOP ");
     }
  }
}

//------------------------------------------------------------------------------------------------


#define E2promSlv_Adr	0xA8	

#define I2C_SDA   	P0_bit.D4
#define I2C_SCL		P0_bit.D6

#define NOP2	{asm(" NOP "); asm(" NOP ");}
#define NOP1	{asm(" NOP ");}

__code const unsigned char Byte_Bit[8] = {
	0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
	};		//add


//------------------------------------------------------------------------------------------------

/***** 启动I2C 工作 ****/

void I2C_Start(void)
{
	I2C_SDA = 1;    //I2c_Sda_High
	NOP2;
	NOP1;
	I2C_SCL = 1;   //I2c_Scl_High
	NOP2;
	NOP2;
   I2C_SDA = 0;	//I2c_Sda_Low
 	NOP2;
	NOP1;
	I2C_SCL = 0;   //I2c_Scl_Low
}


/********* 结束I2C 工作 *********/

void I2C_Stop(void)
{
	I2C_SCL = 0;   //I2c_Scl_Low
	NOP2;
   I2C_SDA = 0;	//I2c_Sda_Low
	NOP2;
	NOP1;
	I2C_SCL = 1;   //I2c_Scl_High
	NOP2;
	NOP2;
	I2C_SDA = 1;   //I2c_Sda_High
}



/******* 测试从器件应答 ***************/
//return non-zero if ACK received

unsigned char Test_ACk(void)
{
   register	unsigned char ack;

   I2C_SCL = 0;            //I2c_Scl_Low
   I2C_SDA = 1;            //I2c_Sda_High
	NOP2;
	ack = ErrorFalse;
	I2C_SCL = 1;            //I2c_Scl_High
	NOP2;
	if(I2C_SDA)
		ack = ErrorTrue;
   I2C_SCL = 0;            //I2c_Scl_Low
//   I2C_SDA = 0;	         //I2c_Sda_Low
	return ack;
}



/********* 正常应答 *********/

void I2C_ACK(void)
{
   I2C_SCL = 0;            //I2c_Scl_Low
	NOP2;
   I2C_SDA = 0;	         //I2c_Sda_Low
	NOP2;
	I2C_SCL = 1;            //I2c_Scl_High
   NOP2;
//   I2C_SCL = 0;            //I2c_Scl_Low
}


/************* 不应答 *************/

void I2C_NACK(void)
{
   I2C_SCL = 0;            //I2c_Scl_Low
	NOP2;
	I2C_SDA = 1;            //I2c_Sda_High
	NOP2;
	I2C_SCL = 1;            //I2c_Scl_High
   NOP2;
//   I2C_SCL = 0;            //I2c_Scl_Low
}




/********  通过I2C总线发送一个字节  *********/

void I2C_SendByte(unsigned char data)
{
	register	unsigned char k=8;

	for(k=0; k<8; k++)
   {
      I2C_SCL = 0;            //I2c_Scl_Low
		if(data & Byte_Bit[k])  // output bit of data
	      I2C_SDA = 1;         //I2c_Sda_High
		else
         I2C_SDA = 0;	      //I2c_Sda_Low
		NOP2;
	   I2C_SCL = 1;            //I2c_Scl_High
      NOP1;
	}
   NOP1;
   I2C_SCL = 0;            //I2c_Scl_Low
}

/********  通过I2C总线接收一个字节  *********/

unsigned char I2C_RcvByte(void)
{
	register	unsigned char data, i;

   I2C_SCL = 0;         //I2c_Scl_Low
	I2C_SDA = 1;         //I2c_Sda_High

	data = 0;
	for(i=0;i<8;i++)
   {
	   I2C_SCL = 1;            //I2c_Scl_High
      if(I2C_SDA)
			data |= Byte_Bit[i];
		NOP2;
      I2C_SCL = 0;            //I2c_Scl_Low
      NOP1;
	}
	return data;
}




/********  通过I2C总线接收一个字节  *********/

unsigned char I2C_SendHand(unsigned int e2Adr)
{
  unsigned char err;
  err =  ErrorFalse;
  I2C_Start();
  I2C_SendByte(E2promSlv_Adr | ((unsigned char)(e2Adr>>7) & 0x06));
  err = Test_ACk();
  I2C_SendByte ((unsigned char)e2Adr);
  err |= Test_ACk();
  return err;
}


 void PutData_Api(unsigned char data,unsigned int DataAdr,unsigned char DaAtt)
 {
     unsigned char __idata *iCp;
     unsigned char *xCp;

     DataAdr &= 0x3fff;
     if (DaAtt == iRAM)
     {
        iCp = (unsigned char __idata *)((unsigned char )DataAdr);         //iRAM指针
        *iCp = data;
     }
     else if (DaAtt == xRAM)
     {
        xCp = (unsigned char *)DataAdr;                          //xRAM指针
        *xCp = data;
     }
  }






 unsigned char GetData_Api(unsigned int DataAdr,unsigned char DaAtt)
 {
     unsigned char __idata *iCp;
     unsigned char __xdata *xCp;
     const unsigned char __code  *oCp;

     if (DaAtt == iRAM)
     {
        iCp = (unsigned char __idata *)((unsigned char )DataAdr);         //iRAM指针
        return (*iCp);
     }
     else if (DaAtt == xRAM)
     {
        xCp = (unsigned char __xdata *)DataAdr;                           //xRAM指针
        return (*xCp);
     }
     else if (DaAtt == pROM)
     {
       oCp = (const unsigned char __code  *)DataAdr;                      //pROM指针
       return (*oCp);
     }
     return  0xEE;
  }
//------------------------------------------------------------------------------------------------
unsigned char  CompareE2prom(unsigned int e2Adr,unsigned char DataAdr,unsigned char Len)
{

	register	unsigned char k,temp,i,err;


   k =DataAdrCheck(DataAdr);                 //判断数据源是在iRAM、xRAM、pROM中
   DataAdr &= 0x3fff;
	if (Len==0)
		return ErrorFalse;
	
   err = I2C_SendHand(e2Adr);
   I2C_Start();
   I2C_SendByte((E2promSlv_Adr | 0x01) | ((unsigned char)(e2Adr>>7) & 0x06));     //准备读
   err |= Test_ACk();

   for (i=0;i<Len;i++)
   {
      temp = I2C_RcvByte();
      if (i==(Len-1))
        I2C_NACK();
      else
        I2C_ACK();
      if (GetData_Api(DataAdr+i,k)!=temp)
        err = ErrorTrue;

   }
	I2C_Stop();
	return err;
}


unsigned char  E2prom_Read(unsigned int e2Adr,unsigned int DataBuf,unsigned char Len)
{
	register	unsigned char k,temp,i,err;


   k =DataAdrCheck(DataBuf);                 //判断数据源是在iRAM、xRAM、pROM中
   DataBuf &= 0x3fff;
	if (Len==0)
		return ErrorFalse;
	
      err = I2C_SendHand(e2Adr);
      I2C_Start();
      I2C_SendByte((E2promSlv_Adr | 0x01) | ((unsigned char)(e2Adr>>7) & 0x06));     //准备读
      err |= Test_ACk();

      for (i=0;i<Len;i++)
      {
        temp = I2C_RcvByte();
        if (i==(Len-1))
          I2C_NACK();
        else
          I2C_ACK();
        PutData_Api(temp,DataBuf+i,k);
       }
	I2C_Stop();
	return err;
}


unsigned char  E2prom_Write(unsigned int e2Adr,unsigned int DataBuf,unsigned char Len)
{
	register	unsigned char k,i,err;

   k = DataAdrCheck(DataBuf);                 //判断数据源是在iRAM、xRAM、pROM中
   DataBuf &= 0x3fff;

   err = ErrorFalse;
   while (Len)
   {
     i = 16-(((unsigned char)e2Adr) & 0x0F);        //AT24C08存储器写缓冲区为16Byte,并且地址对齐。
     if (Len < i)
        i = Len;

     err |= I2C_SendHand(e2Adr);

     Len -=i;                  //修改长度
     e2Adr +=i;                //修改eeprom地址

     while (i--)
     {
       I2C_SendByte ( GetData_Api(DataBuf,k));       //取数据并写e2prom
       err |= Test_ACk();
       DataBuf++;
     }
     I2C_Stop();
     DelayMs(15);                 //延时10ms
   }
   return err;
}


unsigned char  SetE2prom(unsigned int e2Adr,unsigned char DataVal,unsigned int Len)
{
	register	unsigned char i,err;


   err = ErrorFalse;
   while (Len)
   {
     i = 16-(((unsigned char)e2Adr) & 0x0F);        //AT24C08存储器写缓冲区为16Byte,并且地址对齐。
     if (Len < i)
        i = Len;

     err |= I2C_SendHand(e2Adr);

     Len -=i;                  //修改长度
     e2Adr +=i;                //修改eeprom地址

     while (i--)
     {
       I2C_SendByte ( DataVal);       //设数据到e2prom
       err |= Test_ACk();
     }
     I2C_Stop();
     DelayMs(15);                 //延时10ms
   }
   return err;
}

unsigned char  WriteE2prom_Api(unsigned int e2Adr,unsigned int DataBuf,unsigned char Len)
{
  unsigned char loop;
  loop=3;
  while (loop--)
  {
    if (E2prom_Write(e2Adr, DataBuf,Len)==ErrorFalse)
    {
       if (CompareE2prom(e2Adr, DataBuf,Len)==ErrorFalse)
          return  ErrorFalse;
    }
  }
  return ErrorTrue;
}


//------------------------------------------------------------------------------------------------


//      i2c初始化

void I2C_Init(void)
{
  CFG_bit.SCPS       = 0;            //Config the port as I2C  (I2C and SPI)
  I2CMOD_bit.I2CEN   = 1;            //Enable I2C port
  I2CMOD_bit.I2CRATE = I2C_clk;      //I2CRATE=00, the serial frequency is 256KHz
  IEIP2_bit.ESI = 0;                 //I2C中断不使能
}

//------------------------------------------------------------------------------------------------

//      读字节
/*
unsigned char I2C_ReadByte(unsigned char Slv,unsigned char addr)
{
    I2CADR  = Slv | I2CWrite;
    SPI2CTx = addr; //sends the address
    while(I2CSTAT_bit.I2CTxIRQ == 0);
    I2CMOD = I2CMOD & 0xE0;
    I2CADR = (Slv | I2CRead);
    while(I2CSTAT_bit.I2CRxIRQ == 0);
    return(SPI2CRx);
}

*/


//===============================================================================================

//        写I2C函数:1、器件地址,2、器件内部存储器地址,3、数据在Data的指针,4、数据长度

unsigned char I2C_Write(unsigned char Slv,unsigned int Addr,unsigned  int buf,unsigned char Len)
{
  unsigned char i,j,LenBak,k;
  unsigned char __idata *iCp;
  unsigned char *xCp;
  const unsigned char __code  *oCp;

  j=DataAdrCheck(buf);
  if ((j!=iRAM) && (j!=xRAM) && (j!=pROM))         //判断数据源是否在iRAM、xRAM、pROM中
    {return ErrorTrue;}                            //数据区设置不对

               /*------  向e2prom写入数据 -----*/

  iCp = (unsigned char __idata *)((unsigned char )buf);          //iRAM指针
  xCp = (unsigned char  *)(buf & All_RAM);                       //xRAM指针
  oCp = (const unsigned char __code  *)(buf & All_RAM) ;         //porm指针



  E2_Op_Flg =1;               //置E2PROM正在操作标志
  LenBak = Len;
  while (Len)
  {

    while(I2CSTAT_bit.I2CRxIRQ )
      { k = SPI2CRx; }

    k =  Addr;
    i = 16-(k & 0x0F);        //AT24C08存储器写缓冲区为16Byte,并且地址对齐。
    if (Len < i)
      { i = Len; }

    k =  Addr>>8;
    I2CADR = (Slv | I2CWrite |(k<<1)) ;    //sends the SlvAdr+ r/w  at24c08(10位地址)
    SPI2CTx = Addr;             //sends the address
    Len -=i;                    //修改长度
    Addr +=i;                   //修改地址
    while (i--)
      {
        while(I2CSTAT_bit.I2CTxIRQ == 0);
        switch (j)
        {
          case  iRAM:
            SPI2CTx = *iCp;          //数据源在iRAM中,iRAM-->e2prom
            iCp++;
            break;

          case xRAM:
            SPI2CTx = *xCp;          //数据源在iRAM中,xRAM-->e2prom
            xCp++;
            break;

          case pROM:
            SPI2CTx = *oCp;          //数据源在PROM中,pROM-->e2prom
            oCp++;
            break;

         default :
           return ErrorTrue;
         }
      }
    DelayMs(15);                 //延时10ms
   }



     /*------  验证写入数据是否正确 -----*/

  Addr -=LenBak;                                                         //复位入口数据
  iCp = (unsigned char __idata *)((unsigned char )buf);
  oCp = (const unsigned char __code *)(buf & All_RAM) ;
  xCp = (unsigned char *)(buf & All_RAM);



  Len = ErrorFalse;               //清E2PROM写出错标志
  while (LenBak)
  {

    while(I2CSTAT_bit.I2CRxIRQ )
      { k = SPI2CRx; }

    if (LenBak < 32)               //ADE7169连续读最大为32字节。
      { i = LenBak; }
    k = Addr>>8;
    I2CADR = Slv | I2CWrite | (k<<1);         //sends the SlvAdr + w
    SPI2CTx = Addr;                  //sends the address
    while(I2CSTAT_bit.I2CTxIRQ == 0);
    I2CMOD = (I2CMOD | (i-1));       //设定(读I2C数据)长度
    I2CADR = (Slv | I2CRead);        //sends the SlvAdr + R
    LenBak -=i;                        //修改长度
    Addr +=i;                       //修改地址
    while (i--)
    {
       while(I2CSTAT_bit.I2CRxIRQ == 0);
       k = SPI2CRx;
       switch (j)
       {
         case xRAM:
           if (*xCp != k)
             { Len = ErrorTrue;}
           xCp++;
           break;

        case iRAM:
          if (*iCp != k)
             { Len =ErrorTrue;}
           iCp++;
           break;

        case pROM:
          if (*oCp != k)
            { Len =ErrorTrue;}
          oCp++;
          break;

        default :
          { Len =ErrorTrue;}
       }
     }
  }

  E2_Op_Flg = 0;           //清E2PROM操作标志

  return Len;              //返回写E2PROM信息标志
}

//===============================================================================================

//        读I2C函数:1、器件地址,2、器件内部存储器地址,3、数据要存放在Data的指针,4、数据长度

void I2C_Read(unsigned char Slv,unsigned int Addr,unsigned  int buf,unsigned char Len)
{
  unsigned char k,i,j;
  unsigned char __idata *iCp;
  unsigned char *xCp;



  j=DataAdrCheck(buf);
  if ((j!=iRAM) && (j!=xRAM))
    { return ;}                    //数据区设置不对

  iCp = (unsigned char __idata *)((unsigned char)buf);                            //iRAM中传送数据
  xCp = (unsigned char  *)(buf & (All_RAM));                   //xRAM中传送数据



  E2_Op_Flg =1;                  //置E2PROM正在操作标志
  while (Len)
   {
    while(I2CSTAT_bit.I2CRxIRQ )
      { k = SPI2CRx; }

    if (Len < 32)               //ADE7169连续读最大为32字节。
      { i = Len; }
    k = Addr>>8;
    I2CADR = Slv | I2CWrite | (k<<1);         //sends the SlvAdr + w
    SPI2CTx = Addr;                           //sends the address
    while(I2CSTAT_bit.I2CTxIRQ == 0);
    I2CMOD = (I2CMOD | (i-1));       //设定(读I2C数据)长度
    I2CADR = (Slv | I2CRead);        //sends the SlvAdr + R
    Len -=i;                        //修改长度
    Addr +=i;                       //修改地址
    while (i--)
     {
       while(I2CSTAT_bit.I2CRxIRQ == 0);
       if (j==xRAM)
         {                               //xRAM
          *xCp = SPI2CRx;
          xCp++;
         }
       else
        {                                 //iRAM
          *iCp = SPI2CRx;
          iCp++;
        }
     }
   }
  E2_Op_Flg = 0;                  //清E2PROM操作标志
}


//===============================================================================================
#endif

⌨️ 快捷键说明

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