通用24CXXX读写程序(GCC),兼容24C系列存储器(24C01到24C1024),支持跨器件跨页读写,支持连续

读写24CXXX的程序,兼容24C系列存储器(24C01到24C1024),支持多页读写,最多连续写32K字节。

修改了程序,使得其能运行所有24C系列存储器(24C01到24C1024),我使用Proteus仿真了24C512,没有发现问题,欢迎大家测试,并提出使用意见和程序BUG!
程序有注释应该可以比较容易的看懂!

使用说明:
建立工程后,只需要修改24CXXX.h和IIC.h中的宏
 

24CXXX.h
//接口定义及操作
#define _24CXXX_WP_DDR                DDRB
#define _24CXXX_WP_PORT                PORTB
#define _24CXXX_WP                5                //定义WP所处IO位置,如果>7 表示不使用该IO口

//*************************************************************************
//需要自定义修改区域
//设定芯片型号------
#define DEV_24CXX_MODLE        _24C512                        //定义器件类型
#define DEV_24CXX_NUM        2                        //定义器件数量
//*************************************************************************



IIC.h
//端口定义及操作
#define IIC_SCK_DDR                DDRB
#define IIC_SCK_PORT                PORTB
#define IIC_SCK                        7


#define IIC_SDA_DDR                DDRB
#define IIC_SDA_PORT                PORTB
#define IIC_SDA_PIN                PINB
#define IIC_SDA                        6

做完以上定义就可以直接使用函数读写了,包括单字节读写和多字节读写(最多可以连续写32K)!

=========================
连续读好像有问题

连续读好像有问题

void IIC_Start()
{
        IIC_SCK_OUT();
        IIC_SDA_OUT();
        IIC_SCK_HIGH();
        IIC_SDA_HIGH();

        DelayUs(4);
        IIC_SDA_LOW();
        DelayUs(4);
        IIC_SCK_LOW();
        DelayUs(4);
}
这个函数有点问题,在发Start信号前会先发STOP,所以连续读有些问题哈,可能我 说得不对,请指点

====================================

的确会发STOP,但没什么问题!已经调通,可以使用,移植性相当不错,赞!

这个函数有点问题,在发Start信号前会先发STOP,所以连续读有些问题哈,可能我 说得不对,请指点

====================================
 

的确,哑字节的功能我估计是移动指针,所以读写都没问题,呵呵,要解决也 很 容易,
void IIC_Start() 
{ 
        IIC_SCK_OUT(); 
        IIC_SDA_OUT(); 

        IIC_SDA_HIGH(); 
        IIC_SCK_HIGH();        //对调这2个语句就OK了
        

        DelayUs(4); 
        IIC_SDA_LOW(); 
        DelayUs(4); 
        IIC_SCK_LOW(); 
        DelayUs(4); 
} 

SDA线上一定要上拉,否则只能读出一个数,呵呵,上拉后一切OK,晚上回家上硬件试去

 

“void IIC_Start()  
{  
        IIC_SCK_OUT();  
        IIC_SDA_OUT();  

        IIC_SDA_HIGH();  
        IIC_SCK_HIGH();        //对调这2个语句就OK了
”
IIC_SCK_OUT();  
IIC_SDA_OUT(); 
和
IIC_SDA_HIGH();  
IIC_SCK_HIGH();
对调一下就不出现该问题开了!!

IIC_SCK_OUT();  
IIC_SDA_OUT();

IIC_SDA_HIGH();  
IIC_SCK_HIGH();
对调一下就不出现该问题开了!!

 

        最新消息,本代码已成功应用于一个项目当中,两片24C512!运行3个月了,还好,暂时没发现问题!!!

            下面是源程序

 

 

一、24CXXX.h

/******************************************************************************
程序设计:刘景春
设计时间:2009.07.08
修改时间:2009.07.09 10:12
版本信息:
          V0.1 2009.07.08 11:30
          测试版本,具备基本读写功能,已于该日上传ourAVR
          V0.2 2009.07.09 10:12
          测试版本,修改代码,使得程序可以不考虑芯片类型和数量,只需要在宏定义中修改即可,支持多片读写!

版权信息:本程序版权由刘景春所有,你可以随意使用、拷贝、修改;
          可用于商业目的的嵌入式项目当中;
          不管用于任何目的,必须保留本版权信息,并公开源代码;
          不可以销售本源代码!
******************************************************************************/

#ifndef __24CXXX_H__
#define __24CXXX_H__

#include <avr/io.h>
#include "IIC.h"
#ifdef __OPTIMIZE__
#include "Mydelay.h"
#endif


//接口定义及操作
#define _24CXXX_WP_DDR		DDRB
#define _24CXXX_WP_PORT		PORTB
#define _24CXXX_WP			5		//定义WP所处IO位置,如果>7 表示不使用WP

#if _24CXXX_WP < 8
#define _24CXXX_WP_OUT()	_24CXXX_WP_DDR |= (1<<_24CXXX_WP)
#define _24CXXX_WP_HIGH()	_24CXXX_WP_PORT	|= (1<<_24CXXX_WP)
#define _24CXXX_WP_LOW()	_24CXXX_WP_PORT	&= ~(1<<_24CXXX_WP)
#else
#define _24CXXX_WP_OUT()	asm("nop");
#define _24CXXX_WP_HIGH()	asm("nop");
#define _24CXXX_WP_LOW()	asm("nop");
#endif	//#if _24CXXX_WP < 8
#define _24CXXX_WR_EN()		_24CXXX_WP_LOW()
#define _24CXXX_WR_DIS()	_24CXXX_WP_HIGH()


//期间类型列表
#define _24C01	1
#define _24C02	2
#define _24C04	3
#define _24C08	4
#define _24C16	5
#define _24C32	6
#define _24C64	7
#define _24C128	8
#define _24C256	9
#define _24C512	10
#define _24C1024	11


//*************************************************************************
//需要自定义修改区域
//设定芯片型号------
#define DEV_24CXX_MODLE	_24C512		//定义器件类型
#define DEV_24CXX_NUM	2			//定义器件数量
//*************************************************************************


//芯片基本信息
#if DEV_24CXX_MODLE==_24C01
	#define PAGE_SIZE		8
	#define PAGE_SIZE_REM	0x07
	#define MEM_SIZE		0x007f
#elif DEV_24CXX_MODLE==_24C02
	#define PAGE_SIZE		8
	#define PAGE_SIZE_REM	0x07
	#define MEM_SIZE		0x00ff
#elif DEV_24CXX_MODLE==_24C04
	#define PAGE_SIZE		16
	#define PAGE_SIZE_REM	0x0F
	#define MEM_SIZE		0x01ff
#elif DEV_24CXX_MODLE==_24C08
	#define PAGE_SIZE		16
	#define PAGE_SIZE_REM	0x0F
	#define MEM_SIZE		0x03ff
#elif DEV_24CXX_MODLE==_24C16
	#define PAGE_SIZE		16
	#define PAGE_SIZE_REM	0x0F
	#define MEM_SIZE		0x07ff
#elif DEV_24CXX_MODLE==_24C32
	#define PAGE_SIZE		32
	#define PAGE_SIZE_REM	0x1F
	#define MEM_SIZE		0x0fff
#elif DEV_24CXX_MODLE==_24C64
	#define PAGE_SIZE		32
	#define PAGE_SIZE_REM	0x1F
	#define MEM_SIZE		0x1fff
#elif DEV_24CXX_MODLE==_24C128
	#define PAGE_SIZE		64
	#define PAGE_SIZE_REM	0x3F
	#define MEM_SIZE		0x3fff
#elif DEV_24CXX_MODLE==_24C256
	#define PAGE_SIZE		64
	#define PAGE_SIZE_REM	0x3F
	#define MEM_SIZE		0x7fffUL
#elif DEV_24CXX_MODLE==_24C512
	#define PAGE_SIZE		128
	#define PAGE_SIZE_REM	0x7F
	#define MEM_SIZE		0xffffUL
#elif DEV_24CXX_MODLE==_24C1024
	#define PAGE_SIZE		256
	#define PAGE_SIZE_REM	0xFF
	#define MEM_SIZE		0x1ffffUL
#endif


//最大寻址范围
#define MAX_ADDR	( (MEM_SIZE+1)*DEV_24CXX_NUM-1 )


//芯片常量
#define DEV_24CXX_MAIN_ADDR	0xA0


#define DEV_24CXX_READ	0x01
#define DEV_24CXX_WRITE	0x00


//变量声明
extern unsigned char HardAddr;

//函数声明
#define SetDevAddr(a)	HardAddr = (a)
#define GetDevAddr()	HardAddr
extern void _24CXXX_init();

#if MAX_ADDR > 0xFFFF	//如果地址大于65535
extern void _24CXXX_WriteByte(unsigned long Addr,unsigned char Data);
extern unsigned char _24CXXX_ReadByte(unsigned long Addr);
extern void _24CXXX_WriteBytes(unsigned long StartAddr,unsigned char *Data,int DataNum);
extern void _24CXXX_ReadBytes(unsigned long StartAddr,unsigned char *Data,int DataNum);
#else
extern void _24CXXX_WriteByte(unsigned int Addr,unsigned char Data);
extern unsigned char _24CXXX_ReadByte(unsigned int Addr);
extern void _24CXXX_WriteBytes(unsigned int StartAddr,unsigned char *Data,int DataNum);
extern void _24CXXX_ReadBytes(unsigned int StartAddr,unsigned char *Data,int DataNum);
#endif




#endif

二、IIC.h

/******************************************************************************
程序设计:刘景春
设计时间:2009.07.07
修改时间:2009.07.08 10:30
版本信息:
          V0.1 2009.07.07 15:30
          实现基本IO口方式IIC
          V0.2 2009.07.08 10:30
          加入读数据时的ACK是否发出

版权信息:本程序版权由刘景春所有,你可以随意使用、拷贝、修改;
          可用于商业目的的嵌入式项目当中;
          不管用于任何目的,必须保留本版权信息,并公开源代码;
          不可以销售本源代码!
******************************************************************************/
#ifndef __IIC_H__
#define __IIC_H__

#include <avr/io.h>

//功能控制
#define __IO_IIC 1



#if __IO_IIC == 1

//端口定义及操作
#define IIC_SCK_DDR		DDRB
#define IIC_SCK_PORT	PORTB
#define IIC_SCK			7
#define IIC_SCK_OUT()	IIC_SCK_DDR |= (1<<IIC_SCK)
#define IIC_SCK_HIGH()	IIC_SCK_PORT	|= (1<<IIC_SCK)
#define IIC_SCK_LOW()	IIC_SCK_PORT	&= ~(1<<IIC_SCK)

#define IIC_SDA_DDR		DDRB
#define IIC_SDA_PORT	PORTB
#define IIC_SDA_PIN		PINB
#define IIC_SDA			6
#define IIC_SDA_OUT()	IIC_SDA_DDR |= (1<<IIC_SDA)
#define IIC_SDA_IN()	IIC_SDA_DDR &= ~(1<<IIC_SDA)
#define IIC_SDA_HIGH()	IIC_SDA_PORT	|= (1<<IIC_SDA)
#define IIC_SDA_LOW()	IIC_SDA_PORT	&= ~(1<<IIC_SDA)
#define IIC_SDA_GET()	(IIC_SDA_PIN&(0x01<<IIC_SDA))

//常量定义
#define IIC_SEND_ACK	0x10
#define IIC_SEND_NOACK	0x11

#define IIC_STATE_NOACK	0x20
#define IIC_STATE_ACK	0x21

//变量声明
extern unsigned char IIC_State;


//函数声明
#define IIC_StateGet()	IIC_State
extern void IIC_Init();
extern void IIC_Start();
extern void IIC_Stop();
extern void IIC_WriteByte(unsigned char Data);
extern unsigned char IIC_ReadByte(unsigned char ACK);

#else





#endif	//#if __IO_IIC == 1

#endif	//#ifndef __IIC_H__

三、MyDelay.h



#ifndef __MYDELAY_H__
#define __MYDELAY_H__


//#include "config.h"

#ifndef F_CPU
/* prevent compiler error by supplying a default */
# warning "F_CPU is defined 8000000UL"
# define F_CPU 8000000UL
#endif

#include <inttypes.h>
#include <util/delay.h>








#ifdef __OPTIMIZE__
//如果编译器优化,则调用系统默认延时函数
	#define DelayMs(MS)	_delay_ms(MS)

	#define DelayUs(US) _delay_us(US)

#else
//inline __attribute__((__gnu_inline__)) 
	void DelayMs(uint16_t MS);
	void DelayMs(uint16_t MS)
	{
		uint16_t i;
		while(MS--)
			{
			for(i = 442*F_CPU/8000000UL;i!=0;i--);
			}
	}

//inline __attribute__((__gnu_inline__)) 
	void DelayUs(uint16_t US);
	void DelayUs(uint16_t US)
	{
		uint8_t i;
		uint16_t j;

		if(US<15)
			{
			i = 0;
			while(i--);
			}
		else
			{
			if(US<80)
				{
				i = US/4+5;
				while(i--);
				}
			else
				{
				j = US/4+10;//*F_CPU/8000000UL/12;
				while(j--);
				}
			}
	}
#endif




#endif /* _UTIL_DELAY_H_ */

 四、IO_IIC.c

/******************************************************************************
程序设计:刘景春
设计时间:2009.07.07
修改时间:2009.07.08 10:30
版本信息:
          V0.1 2009.07.07 15:30
          实现基本IO口方式IIC
          V0.2 2009.07.08 10:30
          加入读数据时的ACK是否发出

版权信息:本程序版权由刘景春所有,你可以随意使用、拷贝、修改;
          可用于商业目的的嵌入式项目当中;
          不管用于任何目的,必须保留本版权信息,并公开源代码;
          不可以销售本源代码!
******************************************************************************/


#include "IIC.h"
#ifdef __OPTIMIZE__
#include "Mydelay.h"
#endif


unsigned char IIC_State;


void IIC_Init()
{
	IIC_SCK_OUT();
	IIC_SDA_OUT();
	IIC_SCK_HIGH();
	IIC_SDA_HIGH();
}

void IIC_Start()
{
	IIC_SCK_OUT();
	IIC_SDA_OUT();
	IIC_SCK_HIGH();
	IIC_SDA_HIGH();

	DelayUs(4);
	IIC_SDA_LOW();
	DelayUs(4);
	IIC_SCK_LOW();
	DelayUs(4);
}


void IIC_Stop()
{
	IIC_SCK_OUT();
	IIC_SDA_OUT();

	IIC_SDA_LOW();
	DelayUs(4);
	IIC_SCK_HIGH();	
	DelayUs(4);
	IIC_SDA_HIGH();
	DelayUs(4);
}


void IIC_WriteByte(unsigned char Data)
{
	unsigned char i;
	IIC_SCK_OUT();
	IIC_SDA_OUT();
	for(i=0;i<8;i++)
	{
		if( (Data&0x80)==0x00 )
		{
			IIC_SDA_LOW();
		}
		else
		{
			IIC_SDA_HIGH();
		}
		IIC_SCK_HIGH();
		DelayUs(4);
		IIC_SCK_LOW();
		DelayUs(4);
		Data <<= 1;
	}

	IIC_SDA_IN();	//读取数据第九位-从机确认位
	IIC_SCK_HIGH();
	DelayUs(4);

	i = IIC_SDA_GET();
	if( i!=0x00 )
	{
		IIC_State = IIC_STATE_NOACK;
	}
	else
	{
		IIC_State = IIC_STATE_ACK;
	}

	IIC_SCK_LOW();
	DelayUs(4);
}



unsigned char IIC_ReadByte(unsigned char ACK)
{
	unsigned char i,Data,temp;
	IIC_SCK_OUT();
	IIC_SDA_IN();

	Data = 0x00;

	for(i=0;i<8;i++)
	{
		Data <<= 1;
		
		IIC_SCK_HIGH();
		DelayUs(4);
		
		
		temp = IIC_SDA_GET();

		if( temp!=0x00 )
		{
			Data |= 0x01;
		}
		else
		{
		}
		IIC_SCK_LOW();
		DelayUs(4);

	}

	IIC_SDA_OUT();	//主机读数据时,需要根据工作状况发送ACK
	
	if(ACK == IIC_SEND_ACK)
	{
		IIC_SDA_LOW();
	}
	else
	{
		IIC_SDA_HIGH();
	}
	IIC_SCK_HIGH();
	DelayUs(4);
	IIC_SCK_LOW();
	DelayUs(4);

	return Data;
}

五、24CXXX.c

/******************************************************************************
程序设计:刘景春
设计时间:2009.07.08
修改时间:2009.07.09 10:12
版本信息:
          V0.1 2009.07.08 11:30
          测试版本,具备基本读写功能,已于该日上传ourAVR
          V0.2 2009.07.09 10:12
          测试版本,修改代码,使得程序可以不考虑芯片类型和数量,只需要在宏定义中修改即可,支持多片读写!
版权信息:本程序版权由刘景春所有,你可以随意使用、拷贝、修改;
          可用于商业目的的嵌入式项目当中;
          不管用于任何目的,必须保留本版权信息,并公开源代码;
          不可以销售本源代码!
******************************************************************************/
#include "24CXXX.h"




//如果器件是_24C1024,通过HardAddr的BIT0=0,或者=1,来访问高64K和低64K;设置BIT1=0,=1,访问不同芯片
//对于其他器件,通过设置HardAddr,选择不同的芯片
unsigned char HardAddr;



void _24CXXX_init()
{
	IIC_Init();
	_24CXXX_WP_OUT();
	_24CXXX_WR_DIS();
	HardAddr = 0x0000;
}


//地址处理函数,主要处理多芯片时,对于地址的处理
#if DEV_24CXX_MODLE == _24C1024
	#if MAX_ADDR > 0xFFFF	//如果地址大于65535
	void _24CXXX_AddrProcess(unsigned long Addr)
	#else
	void _24CXXX_AddrProcess(unsigned int Addr)
	#endif	//#if MAX_ADDR > 0xFFFF
	{
		if( Addr>( (MEM_SIZE+1)/2-1 ) )	//如果地址大于65535
		{
			Addr /= (MEM_SIZE+1)/2;
		}
		else
		{
			Addr = 0x00;
		}

		HardAddr = Addr;
	}
#else
	#if DEV_24CXX_NUM > 1	//如果使用多个芯片
		#if MAX_ADDR > 0xFFFF		//如果地址大于65535
		void _24CXXX_AddrProcess(unsigned long Addr)
		#else
		void _24CXXX_AddrProcess(unsigned int Addr)
		#endif	//#if MAX_ADDR > 0xFFFF
		{
			if( Addr> MEM_SIZE )	//如果地址大于单芯片地址范围
			{
				Addr /= MEM_SIZE+1;
			}
			else
			{
				Addr = 0x00;
			}

			HardAddr = Addr;
		}
	#else	//如果使用单个芯片
		#if MAX_ADDR > 0xFFFF		//如果地址大于65535
		void _24CXXX_AddrProcess(unsigned long Addr)
		#else
		void _24CXXX_AddrProcess(unsigned int Addr)
		#endif	//#if MAX_ADDR > 0xFFFF
		{
			HardAddr = 0x00;
		}
	#endif	//#if DEV_24CXX_NUM > 1
#endif	//#if DEV_24CXX_MODLE==_24C1024


#if MAX_ADDR > 0xFFFF	//如果地址大于65535
void _24CXXX_WriteByte(unsigned long Addr,unsigned char Data)
#else
void _24CXXX_WriteByte(unsigned int Addr,unsigned char Data)
#endif	//#if MAX_ADDR > 0xFFFF
{
	_24CXXX_AddrProcess(Addr);
	Addr &= MEM_SIZE;	//注:如果是C1024,与后可能数据大于65535,但是写入地址时会被移位和强制转换消除
	_24CXXX_WR_EN();
	IIC_Start();
	IIC_WriteByte(DEV_24CXX_MAIN_ADDR|(HardAddr<<1)|DEV_24CXX_WRITE);
	IIC_WriteByte( ((unsigned char)(Addr>>8)) );
	IIC_WriteByte( ((unsigned char)Addr) );
	IIC_WriteByte( Data );
	IIC_Stop();
	_24CXXX_WR_DIS();
}

#if MAX_ADDR > 0xFFFF	//如果地址大于65535
unsigned char _24CXXX_ReadByte(unsigned long Addr)
#else
unsigned char _24CXXX_ReadByte(unsigned int Addr)
#endif	//#if MAX_ADDR > 0xFFFF
{
	unsigned char temp;
	_24CXXX_AddrProcess(Addr);
	Addr &= MEM_SIZE;
	
	IIC_Start();
	IIC_WriteByte(DEV_24CXX_MAIN_ADDR|(HardAddr<<1)|DEV_24CXX_WRITE);
	IIC_WriteByte( ((unsigned char)(Addr>>8)) );
	IIC_WriteByte( ((unsigned char)Addr) );
	IIC_Start();
	IIC_WriteByte(DEV_24CXX_MAIN_ADDR|(HardAddr<<1)|DEV_24CXX_READ);
	temp = IIC_ReadByte(IIC_SEND_NOACK);
	IIC_Stop();
	return temp;
}



//---------------------------------------------------------------------------
//输入参数:地址,数据指针,写入数据个数(<32768)
//---------------------------------------------------------------------------
#if MAX_ADDR > 0xFFFF	//如果地址大于65535
void _24CXXX_WriteBytes(unsigned long StartAddr,unsigned char *Data,int DataNum)
#else
void _24CXXX_WriteBytes(unsigned int StartAddr,unsigned char *Data,int DataNum)
#endif	//#if MAX_ADDR > 0xFFFF
{
	unsigned char Num;
	unsigned int i;
	unsigned int y;
#if MAX_ADDR > 0xFFFF	//如果地址大于65535
	unsigned long yy;
#else
	unsigned int yy;
#endif	//#if MAX_ADDR > 0xFFFF

	_24CXXX_AddrProcess(StartAddr);
	yy = StartAddr & MEM_SIZE;

	y = yy&PAGE_SIZE_REM;	//=StartAddr/PAGE_SIZE
	y = PAGE_SIZE - y;				//要写的第一页中有多少个数据

	_24CXXX_WR_EN();

	if( y <= PAGE_SIZE )	//写第一页(可能不到一页,以使页对齐)
	{
		IIC_Start();
		IIC_WriteByte( DEV_24CXX_MAIN_ADDR|(HardAddr<<1)|DEV_24CXX_WRITE );
		IIC_WriteByte( ((unsigned char)(yy>>8)) );
		IIC_WriteByte( ((unsigned char)yy) );
		for(i=0;i<y;i++)
		{
			if( i>=DataNum )
			{
				break;
			}
			IIC_WriteByte( *(Data++) );
			
		}
	}
	IIC_Stop();
	DelayMs(10);

	DataNum -= y;		//还有多少数据未写
	i = 0;
	Num = 0;			//用于记录已经写了多少页
	while( DataNum>0 )	//数据未写完
	{
		if( i == 0 )
		{
			yy = StartAddr+y+Num*PAGE_SIZE;
			_24CXXX_AddrProcess(yy);
			yy = yy & MEM_SIZE;
			IIC_Start();
			IIC_WriteByte( DEV_24CXX_MAIN_ADDR|(HardAddr<<1)|DEV_24CXX_WRITE );
			IIC_WriteByte( ((unsigned char)(yy>>8)) );
			IIC_WriteByte( ((unsigned char)(yy)) );
		}
		IIC_WriteByte( *(Data++) );
		
		i++;
		if(i>=PAGE_SIZE )	//如果一页写完
		{
			i = 0;
			Num++;
			IIC_Stop();
			DelayMs(10);
		}
		DataNum--;
	}
	if(i!=0x0000)	//如果写结束时,并未到达页的最后,则需要补上停止位
	{
		IIC_Stop();
		DelayMs(10);
	}
	
	_24CXXX_WR_DIS();
}



//---------------------------------------------------------------------------
//输入参数:地址,数据指针,读出数据个数(<32768)
//---------------------------------------------------------------------------
#if MAX_ADDR > 0xFFFF	//如果地址大于65535
void _24CXXX_ReadBytes(unsigned long StartAddr,unsigned char *Data,int DataNum)
#else
void _24CXXX_ReadBytes(unsigned int StartAddr,unsigned char *Data,int DataNum)
#endif	//#if MAX_ADDR > 0xFFFF
{
	unsigned char Num;
	unsigned int i;
	unsigned int y;
#if MAX_ADDR > 0xFFFF	//如果地址大于65535
	unsigned long yy;
#else
	unsigned int yy;
#endif	//#if MAX_ADDR > 0xFFFF

	_24CXXX_AddrProcess(StartAddr);
	yy = StartAddr & MEM_SIZE;

	y = yy&PAGE_SIZE_REM;	//=StartAddr/PAGE_SIZE
	y = PAGE_SIZE - y;				//要写的第一页中有多少个数据


	if( y <= PAGE_SIZE )	//写第一页(可能不到一页,以使页对齐)
	{
		IIC_Start();
		IIC_WriteByte( DEV_24CXX_MAIN_ADDR|(HardAddr<<1)|DEV_24CXX_WRITE );
		IIC_WriteByte( ((unsigned char)(StartAddr>>8)) );
		IIC_WriteByte( ((unsigned char)StartAddr) );
		IIC_Start();
		IIC_WriteByte(DEV_24CXX_MAIN_ADDR|(HardAddr<<1)|DEV_24CXX_READ);
		for(i=0;i<y;i++)
		{
			if( i>=DataNum )
			{
				break;
			}
			if( (i==DataNum-1)||(i==y-1) )	//如果是该页的最后一个数据,则NOACK
				*Data = IIC_ReadByte(IIC_SEND_NOACK);
			else
				*Data = IIC_ReadByte(IIC_SEND_ACK);
			Data++;
			
		}
	}
	IIC_Stop();
	//DelayUs(20);

	DataNum -= y;		//还有多少数据未写
	i = 0;
	Num = 0;			//用于记录已经写了多少页
	while( DataNum>0 )	//数据未写完
	{
		if( i == 0 )
		{
			yy = StartAddr+y+Num*PAGE_SIZE;
			_24CXXX_AddrProcess(yy);
			yy = yy & MEM_SIZE;
			IIC_Start();
			IIC_WriteByte( DEV_24CXX_MAIN_ADDR|(HardAddr<<1)|DEV_24CXX_WRITE );
			IIC_WriteByte( (unsigned char)(yy>>8) );
			IIC_WriteByte( (unsigned char)(yy) );
			IIC_Start();
			IIC_WriteByte(DEV_24CXX_MAIN_ADDR|(HardAddr<<1)|DEV_24CXX_READ);
		}
		if( (i==PAGE_SIZE-1)||(DataNum==1) )	//如果是该页或要读的最后一个数据,则NOACK
			*Data = IIC_ReadByte(IIC_SEND_NOACK);
		else
			*Data = IIC_ReadByte(IIC_SEND_ACK);
		Data++;
		
		i++;
		if(i>=PAGE_SIZE )	//如果一页写完
		{
			i = 0;
			Num++;
			IIC_Stop();
			//DelayUs(20);
		}
		DataNum--;
	}
	if(i!=0x0000)	//如果写结束时,并未到达页的最后,则需要补上停止位
	{
		IIC_Stop();
	}
	
}

 

https://www.amobbs.com/thread-3444492-1-1.html

  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux at24c512是一个在Linux操作系统上使用的EEPROM设备驱动程序,可以用于读写AT24C512系列芯片。AT24C512是一款串行EEPROM芯片,容量为512Kbit,可以存储大约64KB的数据。 在Linux系统中,驱动程序被用于管理和控制硬件设备。AT24C512驱动程序允许用户通过Linux内核提供的接口来读写AT24C512芯片中的数据。这样,用户就可以在Linux系统中方便地使用AT24C512芯片进行数据存储和读取操作。 通过使用AT24C512驱动程序,用户可以通过简单的Linux命令或编程接口来读写AT24C512芯片中的数据。这为用户提供了一个灵活的方式来进行数据存储和管理。用户可以选择使用命令行工具,如dd或i2c-tools,或编写自己的应用程序来与AT24C512芯片进行交互。 与其他Linux驱动程序类似,AT24C512驱动程序也需要与相关的硬件设备连接并配置正确的引脚连接。通过在Linux内核中加载AT24C512驱动程序,操作系统就可以正确地识别和控制该硬件设备。 总之,Linux at24c512是一个用于管理和控制AT24C512芯片的设备驱动程序。通过使用这个驱动程序,用户可以在Linux系统中方便地读写AT24C512芯片中的数据。这为用户提供了一种灵活的方式来进行数据存储和管理。 ### 回答2: AT24C512是一种EEPROM(Electrically Erasable Programmable Read-Only Memory)芯片,它具有512K位的存储容量。在Linux操作系统中,可以使用相应的驱动程序来读取和写入AT24C512芯片中的数据。 在使用AT24C512芯片之前,需要先加载相应的内核模块。Linux系统已经提供了at24驱动程序,可以通过modprobe命令加载该驱动模块。加载成功后,系统会自动创建一个与AT24C512芯片对应的设备节点,通常是/dev/at24。 通过该设备节点,可以使用工具或者编写相应的程序来访问和操作AT24C512芯片。常用的工具有i2cset和i2cget命令,可以通过这两个命令向指定地址写入数据或者读取数据。具体命令格式可以通过man命令查看。 在编写程序时,可以使用Linux提供的I2C接口库如libi2c-dev来实现对AT24C512芯片的读写操作。首先需要打开I2C总线,在打开设备的过程中需要指定设备地址和总线号。打开成功后,可以使用相应的读写函数来操作芯片的数据。 例如,在C语言中可以使用open函数打开设备,使用ioctl函数来设置设备地址和总线号。然后就可以使用read和write函数来读写芯片的数据。读取时需要指定读取的起始地址和读取的长度,写入时需要指定写入的起始地址和写入的数据。 总体来说,使用Linux操作系统可以方便地访问和操作AT24C512芯片。无论是使用工具还是编写程序,都可以通过相应的命令或者API来读取和写入芯片中的数据。 ### 回答3: Linux at24c512是指Linux操作系统中使用的一种支持at24c512芯片的驱动程序。at24c512是一款24CXXX系列的串行EEPROM芯片,容量为512K。在Linux中,通过at24c512驱动程序,可以通过I2C总线与at24c512芯片进行通信,实现对芯片的读取和写入操作。 在Linux系统中,我们可以使用命令`i2cdetect`来检测I2C总线上是否连接有at24c512设备。如果检测到设备的地址,就说明我们可以通过I2C总线与at24c512进行通信。 在Linux操作系统中,通常需要加载at24c512驱动模块,以便能够使用该芯片。加载驱动模块的命令是`modprobe at24`。加载成功后,系统会根据硬件信息自动识别和分配设备节点。 一旦驱动加载成功,并且设备节点创建完成,我们就可以在用户空间操作at24c512芯片了。通过查看文件系统的`/sys/class/i2c-dev`目录,我们可以找到at24c512设备节点的信息。 在用户空间,我们可以使用`i2cget`和`i2cset`命令来读取和写入at24c512芯片的数据。例如,使用`i2cget -y 1 0x50 0x00`命令可以读取at24c512芯片地址0x00处的数据。 除了通过命令行工具,还可以通过C或Python等编程语言编写程序,使用相应的库函数来进行at24c512芯片的操作。 总之,Linux at24c512是指Linux操作系统中使用的支持at24c512芯片的驱动程序,通过它可以实现对at24c512芯片的读取和写入操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值