24c02.c

来自「基于iic总线的eeprom at24c02的读写程序」· C语言 代码 · 共 306 行

C
306
字号
/*====================================
下为此程序的说明
功能:I2C总线驱动 
版本:Ver 1.0
日期:2007年
说明:由杨德富编写,在硬件(24C04)上通过。但是在PROTEUS中不通过。
====================================*/

#define uint unsigned int
#define uchar unsigned char
#include<reg52.h>
#include<intrins.h>
#include<absacc.h>
#define uchar unsigned char 
#define uint unsigned int

#define NOP _nop_(); _nop_(); _nop_()
//定义数码管的段选
uchar code tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//全局变量的定义

//uchar Step = 50;
bit ack;  //应答信号检测
//位操作定义
sbit SDA = P1^0;  
sbit SCL = P1^1;   //24C04的操作线


/*====================================
非关键函数申明
====================================*/
void Initial(void);                     //系统初始化
void Delay(uint n);          //普通延时
void Disp(uchar num);    //显示数据


/*====================================
24C04函数申明
====================================*/void Start_I2C(void);                      
void Stop_I2C(void);
void  SendByte(uchar fdata);             /*24C04子函数*/
uchar  RecByte(void);
void Ack_I2C(bit a);
bit SendStr(uchar Slave, uchar SubAddress, uchar *Source, uchar Num);
bit RecStr(uchar Slave, uchar SubAddress, uchar *Source, uchar Num);

/*====================================
函数功能:主函数
入口参数:
 说  明 :
=====================================*/
main()
{
 uchar Rec_data[2];
 uchar Sen_data[2]={1,4};
 uchar *ptr;
 ptr = Sen_data;
 Initial();    //初始化
 SendStr(0xa0, 0x20,ptr,2);   /*24C04的20H*/
 Delay(100);
 Delay(100);
 ptr=Rec_data;
 RecStr(0xa1,0x20,ptr,2);
 while(1)
	{
		P2=tab[Rec_data[0]];
	}
}

//初始化
void initial(void)
{
 P1=0xff;
 P0=0xff;
 P2=0xff;
 P3=0xff;
}
//////////////////////////////////////
void Delay(uint n) //延时主函数
{
 uchar i,k;
 for(k=0;k<n;k++)
   {
	 for(i=0;i<200;i++);
	}
}

/*************************************************************************************

                          对24C04进行读写操作子函数                   

*************************************************************************************/
/*******************************************************************
void  Start_I2C();  
启动I2C总线,即发送I2C起始条件。
********************************************************************/
void Start_I2C()
{
	SDA = 1;   /*发送起始条件的数据信号*/
	_nop_();
	SCL = 1;
	_nop_();		/*	起始条件建立时间大于4us,延时	*/
	_nop_();
	_nop_();
	_nop_();
	_nop_();    
	SDA = 0;		/*	发送起始信号	*/
	_nop_();		/*	起始条件锁定时间大于4 us	*/
	_nop_();
	_nop_();
	_nop_();
	_nop_();       
	SCL = 0;		/*	准备发送或接收数据	*/
	_nop_();
	_nop_();
}

/*******************************************************************
void  Stop_I2C();  
结束I2C总线,即发送I2C结束条件。
********************************************************************/
void Stop_I2C()
{
	SDA = 0;		/*	发送结束条件的数据信号	*/
	_nop_();		/*	发送结束条件的时钟信号	*/
	SCL = 1;		/*	结束条件建立时间大于4 us	*/
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	SDA = 1;		/*	发送I2C总线结束信号	*/
	_nop_();
	_nop_();
	_nop_();
	_nop_();
}

/*******************************************************************
void  SendByte(uchar data);
将数据data发送出去,可以是地址,也可以是数据,发完后等待应答,并对此状态
位进行操作。(不应答或非应答都使ack = 0) 发送数据正常,ack=1;ack=0
表示接收器无应答或损坏。
********************************************************************/
void  SendByte(uchar fdata)
{
	uchar BitCount;
	ack=0;
	for(BitCount = 0; BitCount < 8; BitCount ++)  /*	要传送的数据长度为8位	*/
	{
		if((fdata << BitCount) & 0x80) SDA = 1;   /*	判断发送位	*/
		else  SDA = 0;                
		_nop_();
		SCL = 1;					/*	置时钟线为高,通知被控器开始接收数据位	*/
		_nop_(); 
		_nop_();					/*	保证时钟高电平周期大于4 us	*/
		_nop_();
		_nop_();
		_nop_();
		SCL = 0; 
	}
	_nop_();
	_nop_();
	SDA = 0;					/*	8位发送完后释放数据线,准备接收应答位*/
	SCL=0;
	_nop_();
	_nop_();   
	SCL=1;
	_nop_();
	_nop_();
	_nop_();
	NOP;
	if(SDA == 1) ack = 0;     		/* 无应答信号 */
	else ack = 1;					/*	判断是否接收到应答信号*/
	ack=1;
	SCL=0;
	_nop_();
	_nop_();
}

/*******************************************************************
uchar  RecByte();
功能:
用来接收从器件传来的数据,并判断总线错误(不发应答信号),发完后请用
应答函数。  
********************************************************************/	
uchar  RecByte()
{
	uchar RecData;
	uchar BitCount;

	RecData = 0; 
	SDA = 1;				/*	置数据线为输入方式	*/
	for(BitCount = 0; BitCount < 8; BitCount ++)
	{
		_nop_(); 
		SCL=0;			/*	置时钟线为低,准备接收数据位	*/
		_nop_();
		_nop_();			/*	时钟低电平周期大于4.7us	*/
		_nop_();
		_nop_();
		_nop_();
		SCL= 1;			/*	置时钟线为高使数据线上数据有效	*/
		_nop_();
		_nop_();

		if(SDA==1) RecData = RecData +1;	/*	读数据位,接收的数据位放入retc中	*/
		RecData = RecData << 1;
		_nop_();
		_nop_(); 
	}
	SCL= 0;    
	_nop_();
	_nop_();
	return(RecData);
}

/********************************************************************
void Ack_I2C(bit a);
主控器进行应答信号,,(可以是应答或非应答信号)
/********************************************************************/
void Ack_I2C(bit a)
{
	if(a == 0) SDA = 0;		/*	在此发出应答或非应答信号	*/
	else SDA=1;
	_nop_();
	_nop_();
	_nop_();      
	SCL = 1;
	_nop_();
	_nop_();				/*	时钟低电平周期大于4us	*/
	_nop_();
	_nop_();
	_nop_();  
	SCL = 0;				/*	清除时钟线,以便继续接收	*/
	_nop_();
	_nop_();    
}
/*******************************************************************
bit  SendStr(uchar Slave, uchar SubAddress, uchar *Source, uchar Num);  
从启动总线到发送地址,子地址,数据,结束总线的过程。
Slave--从器件地址
SubAddress--子地址
Source--指向发送内容的指针
Num--发送字节个数
返回值:
如果返回1表示操作成功,否则操作有误。
********************************************************************/
bit SendStr(uchar Slave, uchar SubAddress, uchar *Source, uchar Num)
{
	uchar i;
	Start_I2C();			/*	启动总线	*/
	SendByte(Slave);		/*	发送器件地址	*/
	if(ack == 0) return(0);
	SendByte(SubAddress);			/*	发送器件子地址	*/
	if(ack == 0) return(0);

	for(i = 0; i < Num; i++)
	{   
		SendByte(*Source);			/*	发送数据	*/
		if(ack == 0) return(0);
		Source ++;
	} 
	Stop_I2C();					/*	结束总线	*/ 
	return(1);
}
/*******************************************************************
bit  RecStr(BYTE Slave, BYTE SubAddress, BYTE *Source, BYTE Num);  
从启动总线到发送地址,子地址,读数据,结束总线的过程。
参数:
Slave--从器件地址。
SubAddress--子地址
Source--指向读出的内容放入的存储区的指针
Num--读字节个数。
返回值:	
如果返回1表示操作成功,否则操作有误。
********************************************************************/
bit RecStr(uchar Slave, uchar SubAddress, uchar *Source, uchar Num)
{
	uchar i;
	Start_I2C();					/*	启动总线	*/
	SendByte(Slave-1);				/*	发送器件地址	*/
	if(ack == 0) return(0);
	SendByte(SubAddress);			/*	发送器件子地址	*/
	if(ack == 0) return(0);

	Start_I2C();
	SendByte(Slave);
	if(ack == 0) return(0);

	for(i = 0; i < Num-1; i++)
	{   
		*Source = RecByte();			/*	接收数据	*/
		Ack_I2C(0);				/*	发送就答位	*/  
		Source++;
	} 
	*Source =RecByte();
	Ack_I2C(1);					/*	发送非应位	*/
	Stop_I2C();					/*	结束总线	*/ 
	return(1);
}
/*****************************************************************************
--------------------------------程序结束-------------------------------------
*****************************************************************************/

⌨️ 快捷键说明

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