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

📄 at24c64.c

📁 ATMEL的24C04-512的通用应用程序
💻 C
字号:


/* --------------------------------------------------------

下面是24C64的读写代码,端口已在BA_C_Port.h里定义

sbit  SCK_24   =P3^6;			//24C64的 时钟端口,静态0
sbit  SDA_24   =P3^7;			//24C64的 数据端口,静态0
 
---------------------------------------------------------*/

#include <reg52.h>
#include <intrins.h>            //此头可以使用_nop_() 或一些循环左移;循环右移函数
#include <stdio.h>              //此头用于printf
#include <stdlib.h>
#include <time_delay_12M.h>

#include <BA_D_Port.h>

void  I2C_Start(void);			//开始信号
void  I2C_Stop(void);	        //停止信号
void  I2C_Ack(void);			//主机应答=0
void  I2C_Nack(void);			//主机反应答=1
unsigned char   I2C_Test(void)reentrant ;			//测试芯片的应答,返回应为=0
void  I2C_Init(void);			//I2C初始化

bit   I2C_Send_Byte( unsigned char);	//发送1个字节,返回应答位
unsigned char I2C_Get_Byte(void);		//接受1个字节,返回接收的数据
void AT24_W_1Byte(unsigned int , unsigned char );                //向某一个地址写入1个字节
void AT24_W_2Byte(unsigned int , unsigned char,unsigned char );  //向某一个地址写入2个字节
void AT24_W_2Byte_2(unsigned int , unsigned char *);			 //向某一个地址写入2个字节另一种方式

unsigned char AT24_R_1Byte(unsigned int);		     //从芯片的某地址读出1个字节数据,
void AT24_R_2Byte(unsigned int , unsigned char * );	 //从芯片的某地址读出2个字节数据并存入数组中
void AT24_R_NByte(unsigned int , unsigned char , unsigned char * ); //从芯片的某地址读出n个字节数据并存入数组中


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

void I2C_Start(void)				//开始信号
{
 SDA_24 =1;
 _nop_();
 SCK_24 =1;

 _nop_();
 _nop_();
 _nop_();
 _nop_();

 SDA_24 = 0;

 _nop_();
 _nop_();
 _nop_();
 _nop_();

 SCK_24 = 0;
 _nop_();

}

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

void  I2C_Stop(void)				//停止信号
{
 SDA_24 = 0;
 _nop_();
 SCK_24 = 1;

 _nop_();
 _nop_();
 _nop_();
 _nop_();
 _nop_();
 _nop_();

 SDA_24 = 1;

 _nop_();
 _nop_();
 _nop_();
 _nop_();
 _nop_();
 _nop_();

 SCK_24 = 0;
 _nop_();

}

//-----------------------------------------------
void  I2C_Init(void)				//I2C初始化
{
 SCK_24 = 0;
 _nop_();

 SDA_24 = 0;
 _nop_();
 SCK_24 = 1;

 _nop_();
 _nop_();
 _nop_();
 _nop_();
 _nop_();
 _nop_();

 SDA_24 = 1;

 _nop_();
 _nop_();
 _nop_();
 _nop_();
 _nop_();
 _nop_();

 SCK_24 = 0;						//时钟为0
 SDA_24 = 0;						//数据为0

}


//------------------------------------------------
void I2C_Ack(void)					//主机应答信号为0
{
 SDA_24=0;
 _nop_();
 SCK_24=1;

 _nop_();
 _nop_();
 _nop_();
 _nop_();

 SCK_24=0;
 _nop_();

}

//------------------------------------------------
void I2C_Nack(void)					//主机反应答信号为1
{
 SDA_24=1;
 _nop_();
 SCK_24=1;

 _nop_();
 _nop_();
 _nop_();
 _nop_();

 SCK_24=0;
 _nop_();
}


//----------------- 检测芯片的应答信号,有效信号应为0 (此处应用了超时处理)----------
unsigned char  I2C_Test(void) reentrant  	//注意:再入函数不可用于 bit			

{
 unsigned char errtime=250;			// 超时检测定位250次
 unsigned char bit_test;

 SDA_24=1;							// 置数据线为输入方式
 _nop_();
 SCK_24=1;

  while(SDA_24)						// 等待应答为0
  { errtime-- ;
   	if( ! errtime)				    // ! errtime  等价与  errtime==0 
	{ I2C_Stop();
	  bit_test = 1;
	  return bit_test ;				//retuen 即时中止本函数的运行,退出本函数并返回1
	 }
   }
 bit_test = 0;					    //把“SDA_24”线上的信号传给bit_test,也可用F0,CY
 SCK_24 =0;

 return bit_test;					//CY是位累加器,也可以用F0,在PSW里面有定义,

}


//----------------------------------------------------------------------
//------------- 发送一个字节,并且检测芯片的应答信号 --------------------
bit I2C_Send_Byte( unsigned char d)	
{
 unsigned char i = 8;
  SCK_24 = 0;						//时钟信号为0

 while( i-- )						//发送8次
 {
  if ( d & 0x80 )   				//0x80=1000 0000
     SDA_24 =1;
  else             
     SDA_24 =0;

  SCK_24 = 1;						//时钟信号为1
  _nop_();
  _nop_();
  _nop_();
  SCK_24 = 0;						//时钟信号为0

  d = d << 1;						//非循环左移一位
 }

 return (I2C_Test());			   //返回检测信号为0正常,如果为1不对
}


//----------------------------------------------------------------------------
//--------- 接收一个字节,这里不能产生应答信号,应答信号有可能是0或1 ----------
unsigned char I2C_Get_Byte(void)
{
 unsigned char i = 8;
 unsigned char d = 0;
 SCK_24 = 0;						//时钟信号为0
 
 SDA_24 = 1;						//置数据线为输入方式
 while ( i-- )						//接收8次信号
 {
  d = d << 1;
  _nop_();

  SCK_24 =1;						//时钟=1
  _nop_();
  _nop_();

  if ( SDA_24 ) 
  { d++; }
  SCK_24 =0;						//时钟=0
  }

 return d;							//返回1个字节数据
}

//---------------------------------------------------------------------------
//------------------向AT24C64的地址 写入1个字节数据 -------------------------
void AT24_W_1Byte(unsigned int AT24_addr, unsigned char AT24_data)
{
  I2C_Start();									   // 启动信号
  I2C_Send_Byte( 0xa0 );                           // A0=1010,0000 高4位是芯片时序,次3位是芯片地址,末位0=写,1=读 

  I2C_Send_Byte( AT24_addr / 256 );                // 发送高字节地址 (注意/的使用=整数,余数去掉)	 
  I2C_Send_Byte( AT24_addr % 256 );				   // 发送低字节地址 (注意%的使用=余数,)
  I2C_Send_Byte( AT24_data );                      // 发送数据

  I2C_Stop();									   // 停止信号

  T_2ms();									       // 延迟2ms

}

//---------------------------------------------------------------------------
//--------------- 向AT24C64的地址 写入1个字节数据 ---------------------------
//--------------- 本函数仅供串口调用 ----------------------------------------
void COM_AT24_W_1Byte(unsigned int AT24_addr, unsigned char AT24_data)
{
  I2C_Start();									   // 启动信号
  I2C_Send_Byte( 0xa0 );                           // A0=1010,0000 高4位是芯片时序,次3位是芯片地址,末位0=写,1=读 

  I2C_Send_Byte( AT24_addr / 256 );                // 发送高字节地址 (注意/的使用=整数,余数去掉)	 
  I2C_Send_Byte( AT24_addr % 256 );				   // 发送低字节地址 (注意%的使用=余数,)
  I2C_Send_Byte( AT24_data );                      // 发送数据

  I2C_Stop();									   // 停止信号

  T_2ms();									       // 延迟2ms

}


//------------------------------------------------------------------------------------
//------------------向AT24C64的地址 写入2个字节数据 “第一种方式” -------------------
void AT24_W_2Byte(unsigned int AT24_addr, unsigned char AT24_data1,unsigned char AT24_data2 )
{
  I2C_Start();									   // 启动信号
  I2C_Send_Byte( 0xa0 );                           // A0=1010,0000 高4位是芯片时序,次3位是芯片地址,末位0=写,1=读 

  I2C_Send_Byte( AT24_addr / 256 );                // 发送高字节地址 (注意/的使用=整数,余数去掉)	 
  I2C_Send_Byte( AT24_addr % 256 );				   // 发送低字节地址 (注意%的使用=余数,)
  I2C_Send_Byte( AT24_data1 );                     // 发送数据1
  I2C_Send_Byte( AT24_data2 );                     // 发送数据2

  I2C_Stop();									   // 停止信号

  T_2ms();
												   // 延迟2ms
}




//--------------------------------------------------------------------------------------
//----------------- 向AT24C64的地址 写入N个字节数据 ------------------------------------
//-------------	 *AT24_d 为指针变量 (指向“ 数组 ”) ----------------------------------
void AT24_W_NByte(unsigned int AT24_addr, unsigned char Count, unsigned char *char_d)
{
  unsigned char i;
  I2C_Start();
  I2C_Send_Byte( 0xa0 );		//0xa0 向芯片写数据
 					   
  I2C_Send_Byte( AT24_addr / 256 );			   //高字节地址
  I2C_Send_Byte( AT24_addr % 256 );			   //低字节地址

  for(i=0; i<Count ;i++)					   //循环 Count次 
  {
    I2C_Send_Byte( char_d[i] );				   //“指针变量带下标” == “数组带下标”
   }
  
  I2C_Stop(); 								   //停止信号

  T_2ms();								       // 延迟2ms

 } 


//--------------------------------------------------------------------------------------
//----------------- 向AT24C64的地址 写入N个字节数据 ------------------------------------
//-------------	 *AT24_d 为指针变量 (指向“ 数组 ”) ----------------------------------
//-------------  本函数仅供串口调用 ----------------------------------------------------
void COM_AT24_W_NByte(unsigned int AT24_addr, unsigned char Count, unsigned char *char_d)
{
  unsigned char i;
  I2C_Start();
  I2C_Send_Byte( 0xa0 );		//0xa0 向芯片写数据
 					   
  I2C_Send_Byte( AT24_addr / 256 );			   //高字节地址
  I2C_Send_Byte( AT24_addr % 256 );			   //低字节地址

  for(i=0; i<Count ;i++)					   //循环 Count次 
  {
    I2C_Send_Byte( char_d[i] );				   //“指针变量带下标” == “数组带下标”
   }
  
  I2C_Stop(); 								   //停止信号

  T_2ms();								       // 延迟2ms

 } 




//----------------------------------------------------------------------------------------
//--------------------------从AT24C64的地址 读出1个字节数据,并返回 ----------------------
unsigned char AT24_R_1Byte(unsigned int AT24_addr)
{
  unsigned char i;
  I2C_Start();
  I2C_Send_Byte( 0xa0 );					   //0xa0 向芯片写数据
  I2C_Send_Byte( AT24_addr / 256 );			   //高字节地址
  I2C_Send_Byte( AT24_addr % 256 );			   //低字节地址

  I2C_Start();
  I2C_Send_Byte( 0xa1 );					   //0xa1 从芯片读数据
  i = I2C_Get_Byte();						   //接受一个数据

  I2C_Nack();
  I2C_Stop();


  return i;

}



/*
//-----------------------------------------------------------------------------------------
//-----------------从AT24C64的地址 读出2个字节数据 并存入定义的“ 数组”中 ----------------
void AT24_R_2Byte(unsigned int AT24_addr, unsigned char *char_d  )
{
  I2C_Start();
  I2C_Send_Byte( 0xa0 );					 //0xa0 向芯片写数据
  I2C_Send_Byte( AT24_addr / 256 );		 //高字节地址
  I2C_Send_Byte( AT24_addr % 256 );		 //低字节地址

  I2C_Start();
  I2C_Send_Byte( 0xa1 );					 //0xa0 从芯片读数据
  char_d[0] = I2C_Get_Byte();				 //读取数据“指针变量的下标” 等价 “数组的下标”
  
  I2C_Ack();						    	 //主机产生一个应答信号0
  char_d[1] = I2C_Get_Byte();				 //读取数据“指针变量的下标” 等价 “数组的下标”

  I2C_Nack();								 //主机产生一个非应答信号1
  I2C_Stop();


}
*/




//-----------------------------------------------------------------------------------------
//-----------------从AT24C64的地址 读出n个字节数据 并存入定义的“ 数组”中 ----------------
void AT24_R_NByte(unsigned int AT24_addr, unsigned char Count, unsigned char *char_d  )
{
  unsigned char i;

  I2C_Start();
  I2C_Send_Byte( 0xa0 );					 //0xa0 向芯片写数据
  I2C_Send_Byte( AT24_addr / 256 );		     //高字节地址
  I2C_Send_Byte( AT24_addr % 256 );		     //低字节地址

  I2C_Start();
  I2C_Send_Byte( 0xa1 );					 //0xa0 从芯片读数据

  for(i=0; i< Count ; i++)
  {
    char_d[i] = I2C_Get_Byte();				 //读取数据“指针变量的下标” 等价 “数组的下标”
    if (i != (Count-1))						 //最后一个数据不产生应答信号
	{ I2C_Ack(); }						     //主机产生一个应答信号0
   }

  /*----------------上面的程序段也可以用下面的语句 --------------------------------------
  i=0;
  while(Count--)
  {
   char_d[i] = I2C_Get_Byte();
   if(Count != 1)							 //最后一个数据不产生应答信号
   { I2C_Ack(); }
   i++;
  }
  */ //----------------------------------------------------------------------------------

  I2C_Nack();								 //主机产生一个非应答信号1
  I2C_Stop();


 }


  
   
 














⌨️ 快捷键说明

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