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

📄 i2c_module1.c

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

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

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

#include "includes.h"


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

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;
}


//------------------------------------------------------------------------------------------------
/*
 摘    要: 比较e2prom中的数据
 输    入:1、 e2prom中的地址(实物地址)
           2、 比较数据存放的地址(idata+iRAM_Adr或xdata+xRAM_Adr或PROM+pROM_Adr),硬件统一编定地址
           3、 读取数据长度(char类型)
 输    出: 函数返回比较结果,比较正确返回"ErrorFalse",比较错误或I2C操作错误返回"ErrorTrue"
*/


unsigned char  CompareE2prom(unsigned int e2Adr,unsigned int 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;
}

//------------------------------------------------------------------------------------------------------------
/*
 摘    要: 从e2prom中读取数据
 输    入:1、 e2prom中的地址(实物地址)
           2、 数据存放的地址(idata+iRAM_Adr或xdata+xRAM_Adr),硬件统一编定地址
           3、 读取数据长度(char类型)
 输    出: 函数I2C操作结果,操作正确返回"ErrorFalse",I2C操作错误返回"ErrorTrue"
*/

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;
}

//------------------------------------------------------------------------------------------------
/*
 摘    要: 将数据写入e2prom中
 输    入:1、 e2prom中的地址(实物地址)
           2、 写入数据存放的地址(idata+iRAM_Adr或xdata+xRAM_Adr或PROM+pROM_Adr),硬件统一编定地址
           3、 写入数据长度(char类型)
 输    出: 函数返回I2C操作结果,操作正确返回"ErrorFalse",I2C操作错误返回"ErrorTrue"
*/

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;
}

//------------------------------------------------------------------------------------------------
/*
 摘    要: 将数据设置到e2prom中(对e2prom设置固定数据,用于清零等操作)
 输    入:1、 e2prom中的地址(实物地址)
           2、 被设置的数据(char类型)
           3、 写入数据长度(int类型)
 输    出: 函数返回I2C操作结果,操作正确返回"ErrorFalse",I2C操作错误返回"ErrorTrue"
*/

unsigned char  E2prom_Set(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;
}


//----------------------------------------------------------------------------------------------------
/*
 摘    要: 将数据写入e2prom中,同时判断操作正确性,操作错误时作3次同样的处理,3次都不正确,置错误标志。
 输    入:1、 e2prom中的地址(实物地址)
           2、 写入数据存放的地址(idata+iRAM_Adr或xdata+xRAM_Adr或PROM+pROM_Adr),硬件统一编定地址
           3、 写入数据长度(int类型)
 输    出: 函数返回I2C操作结果,操作正确返回"ErrorFalse",I2C操作错误返回"ErrorTrue"
*/

unsigned char  WriteE2prom_Api(unsigned int e2Adr,unsigned int DataBuf,unsigned char Len)
{
  unsigned char loop;
  loop=3;
  E2PROM_ERR=0;
  while (loop--)
  {
    if (E2prom_Write(e2Adr, DataBuf,Len)==ErrorFalse)
    {
       if (CompareE2prom(e2Adr, DataBuf,Len)==ErrorFalse)
         return  ErrorFalse;
       else
         E2PROM_ERR=1;
    }
  }
  if (E2PROM_ERR)
     SysErrNumb = SysErr_E2prom ;      // E2PROM 读写数据错误
  else
     SysErrNumb =  SysErr_I2C;         //I2C操作错误
  return ErrorTrue;
}

//----------------------------------------------------------------------------------------------------
/*
 摘    要: 从e2prom读取数据中,同时判断操作正确性,操作错误时作3次同样的处理,3次都不正确,置错误标志。
 输    入:1、 e2prom中的地址(实物地址)
           2、 读出的数据存放地址(idata+iRAM_Adr或xdata+xRAM_Adr),硬件统一编定地址
           3、 读取数据长度(char类型)
 输    出: 函数返回I2C操作结果,操作正确返回"ErrorFalse",I2C操作错误返回"ErrorTrue"
*/

unsigned char  ReadE2prom_Api(unsigned int e2Adr,unsigned int DataBuf,unsigned char Len)
{
  unsigned char loop;
  loop=3;
  while (loop--)
  {
    if (E2prom_Read(e2Adr, DataBuf,Len)==ErrorFalse)
       return  ErrorFalse;
  }
  SysErrNumb =  SysErr_I2C;         //I2C操作错误
  return ErrorTrue;
}

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

⌨️ 快捷键说明

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