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

📄 function.c

📁 基于EEPROM AT24C64的数据存储
💻 C
字号:
#include <./Atmel/at89x52.h>
#include <stdio.h>
#include "source.h"
#include <intrins.h>
#include  <absacc.h>
//_nop_();0.65us fosc=18.432
void delay_macnine_ncircle(unsigned char cnt){//11+6*cnt machin circle. /*延时ns*/
	while(cnt--);
}
void delay_10us(unsigned char tus){//fosc=18.432 /*延时10us的整数倍,其中tus为10us的整数倍*/
	tus--;
	while(tus--){
		_nop_();_nop_();_nop_();
		_nop_();_nop_();_nop_();
		_nop_();_nop_();_nop_();
	}
}
/*i2c max rate: 100k, so delay is needed*/
/*定义宏,把I2C的函数进行抽象*/
#define	DELAY	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_()
	#define	I2CDATA			SDA	/*for read data from bit port*/
	#define	I2CSETDATA		SDA=1	/*sda=1 macro*/
	#define	I2CCLRDATA		SDA=0	/*sda=0 macro*/
	#define	I2CSETCLK		SCL=1	/*scl=1	macro*/
	#define	I2CCLRCLK		SCL=0	/*scl=0	macro*/

	#define	i2c_start		AT24C64_start
	#define	i2c_stop		AT24C64_stop
	#define i2c_write_byte 	AT24C64_write_byte
	#define	i2c_read_byte   AT24C64_read_byte 
	#define	i2c_wait_ack    AT24C64_wait_ack 
	#define	i2c_send_ack    AT24C64_send_ack 
	#define	i2c_send_notack AT24C64_send_notack
void	i2c_start(){/*I2C的开始函数*/
	I2CSETDATA;
	I2CSETCLK;
	DELAY;
	I2CCLRDATA;
	DELAY;
	I2CCLRCLK;
}
void	i2c_stop(){/*I2C的停止函数*/
	I2CCLRCLK;
	I2CCLRDATA;
	DELAY;
	I2CSETCLK;
	DELAY;
	I2CSETDATA;
}
void	i2c_write_byte(unsigned char  ch)/*I2C的写一个字节*/
{
	unsigned char	i=8;
	while(i--){
		I2CCLRCLK;_nop_();
		if(ch&0x80)
			I2CSETDATA;
		else
			I2CCLRDATA;
		ch<<=1;DELAY;
		I2CSETCLK;DELAY;
	}
	I2CCLRCLK;
}

unsigned char i2c_read_byte(void)/*I2C读一个字节*/
{
	unsigned char	i=8;
	unsigned char	ddata=0;
	I2CSETDATA ;
	while (i--){
		ddata<<=1 ;
		I2CCLRCLK;DELAY;
		I2CSETCLK;DELAY;	
		ddata|=I2CDATA;
	}
	I2CCLRCLK;
	return ddata;
}
bit	i2c_wait_ack(void)/*I2C等待芯片的ACK*/
{
	unsigned char	errtime=255;//因故障接收方无ACK 超时值为255
	I2CSETDATA;DELAY;
	I2CSETCLK ;DELAY;
	while(I2CDATA){
		errtime--; 
		if (!errtime){
			i2c_stop();
			return 0;
		}
	}
	I2CCLRCLK;
	return 1;
}
void	i2c_send_ack(void)/*对I2C芯片发送ACK*/
{
	I2CCLRDATA; DELAY;
	I2CSETCLK; DELAY;
	I2CCLRCLK;
}

void	i2c_send_notack(void)/*对I2C芯片发送NO ACK*/
{
	I2CSETDATA ; DELAY;
	I2CSETCLK ; DELAY;
	I2CCLRCLK;
}

#define DEVICEAW 0Xa0
#define DEVICEAR 0Xa1
/*下面是把以上的I2C操作转换为对AT24C64的EEPROM的操作以上介绍,可以得出以下函数*/
void AT24C64_wbytes(unsigned char *add,unsigned char len,unsigned char *buf){//max 32 bytes
					/*为对EEPROM写多个字节,由于地址回转的问题,最多写32个字节*/
	unsigned char hadd,ladd;
	unsigned char i;
	hadd=add[0];
	ladd=add[1];
	AT24C64_start();
	AT24C64_write_byte(DEVICEAW);
	AT24C64_wait_ack();
	AT24C64_write_byte(hadd);
	AT24C64_wait_ack();
	AT24C64_write_byte(ladd);
	AT24C64_wait_ack();
	for(i=0;i<len;i++){
		AT24C64_write_byte(buf[i]);
		AT24C64_wait_ack();
	}
	AT24C64_stop();	
	delay_10us(100);//delay 1 ms for write byte.
	delay_10us(100);
	delay_10us(100);
	delay_10us(100);
	delay_10us(100);/*延时5毫秒,因为在两次写操作之间必须有5ms的延时才能进行下一次写*/
}
void AT24C64_rbytes(unsigned char *add,unsigned char len,unsigned char *buf){
		/*对EEPROM进行多个字节的读操作,同样由于地址回转的问题,最多只能读32个字节*/
	unsigned char hadd,ladd;
	unsigned char i;
	hadd=add[0];
	ladd=add[1];
	AT24C64_start();
	AT24C64_write_byte(DEVICEAW);
	AT24C64_wait_ack();
	AT24C64_write_byte(hadd);
	AT24C64_wait_ack();
	AT24C64_write_byte(ladd);
	AT24C64_wait_ack();
	for(i=0;i<len;i++){
		AT24C64_start();
		AT24C64_write_byte(DEVICEAR);
		AT24C64_wait_ack();
		buf[i]=AT24C64_read_byte();
	}
	AT24C64_stop();	
}
void init_eeprom(void){/*开始时,对EEPROM进行初始化,把EEPROM的存储单元都设置为0*/
	unsigned char temp;
	unsigned int add;
	temp=0;
	for(add=0;add<EEPROM_MAX_SPACE;add++){
		AT24C64_wbytes((unsigned char *)&add,1,&temp);
	}

}
unsigned char  eeprom_write(unsigned int adr, unsigned int len, unsigned char *src){
	/*为写EEPROM的进一步封装,这个函数的写的字节数可以任意长的*/
	unsigned int temp;
	unsigned int eeprom_grid;/*为取EEPROM一个页面64字节的整数地址*/
	unsigned int eeprom_last;/*写EEPROM的最后存储单元的地址*/
	unsigned char i;
	eeprom_last=adr+len;	
	temp=adr/EEPROM_PAGE_LEN;
	eeprom_grid=(temp+1)*EEPROM_PAGE_LEN;
	temp=eeprom_last>eeprom_grid?eeprom_grid:eeprom_last;
	AT24C64_wbytes((unsigned char *)&adr,temp-adr,src);
	while(1){
		if(eeprom_grid<eeprom_last){
			adr=eeprom_grid;
			eeprom_grid +=EEPROM_PAGE_LEN;
			temp=eeprom_last>eeprom_grid?eeprom_grid:eeprom_last;
			AT24C64_wbytes((unsigned char *)&adr,temp-adr,src);
		}
		else
			break;//jump out the while
	}
}

unsigned char eeprom_read(unsigned int adr, unsigned int len, unsigned char *src){
	/**为对EEPROM的读函数的进一步封装,可以读任意个字节数*/
	unsigned int i=0;
	unsigned int rest;
	while(1){
		rest=len;
		if(rest<=EEPROM_PAGE_LEN){/*如果剩下的字节数小于EEPROM_PAGE_LEN就把剩下的字节数读出来*/
			AT24C64_rbytes((unsigned char *)&adr,(unsigned char)rest,src+i*EEPROM_PAGE_LEN);
			break;
		}
		else{/*如果剩下的字节数大于EEPROM_PAGE_LEN就读EEPROM_PAGE_LEN个字节*/
			AT24C64_rbytes((unsigned char *)&adr,EEPROM_PAGE_LEN,src+i*EEPROM_PAGE_LEN);
			rest -=EEPROM_PAGE_LEN;
		}
		i++;
	}
}


⌨️ 快捷键说明

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