UKHAS Wiki

UK High Altitude Society

User Tools

Site Tools


code:i2c_eeprom

This is an old revision of the document!


I2Cmem.c

#include "i2cmem.h"
#ifdef EEPROM
 
//----------General I2C functions-------------------------------------------------------------------------
 
volatile u08 I2Cerr;
 
void init_i2c()
{
	TWBR=(u08)((float)F_CPU/(2*SCL)-8.0);	//sets the correct clock rate defined as SCL
}											//we dont need to enable the hardware - its done in write
 
void i2cstart()
{
	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);	//send start
	while (!(TWCR & (1<<TWINT)));			//wait for a start to be transmitted
	if (((TWSR & 0xF8) != TW_START)&&((TWSR & 0xF8) != TW_REP_START))
		I2Cerr|=1;							//error
}
 
void i2cstop()
{
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
	while (!(TWCR & (1<<TWSTO)));			//wait for stop to be sent
}
 
void i2cwrite(u08 c)
{
	TWDR = c;								//load the data
	TWCR = (1<<TWINT)|(1<<TWEN);
	while (!(TWCR & (1<<TWINT)));			//wait for it to be sent
	if ( ((TWSR & 0xF8) !=TW_MT_SLA_ACK) & ((TWSR & 0xF8) !=TW_MR_SLA_ACK) )
		I2Cerr|=2;							//error
}
 
u08 i2cread(u08 AK)
{
	u16 timeout=1;
	TWCR=AK;
	while (!(TWCR & (1<<TWINT)) & timeout)
		timeout++;							//wait for it to be recieved
	if(!timeout)
		I2Cerr|=8;							//timeout out waiting for data error
	if((TWSR & 0xF8) !=TW_MR_DATA_ACK)
		I2Cerr|=4;
	return TWDR;
}
 
//----------EEPROM specific stuff-------------------------------------------------------------------------
//Designed for 12 byte records atm
 
void set_address(u32 * address)					//Sets an address from a paointer - cannot switch between physical devices
{
	i2cstart();
	i2cwrite(SLA_W|(((*address)>>13)&0x08));	//the block
	i2cwrite((u08)((*address)>>8));				//address write MSB
	i2cwrite((u08)(*address));					//address write LSB
}	
 
void write_data(u08 * c, u08 datasize, u32 * address)//The address will be incremented as the data is written
{
	u08 n;										//up to 256 bytes can be written at once
	for(n=0;n<datasize;n++,(*address)++)
	{
		if(!((u08)*address)&0xEF)				//check the address for overflow for the 7 LSB
		{
			i2cstop();							//triggers a page write
			_delay_loop_2( (u16) ( (float)F_CPU*0.003/4.0 ) );//delay 3 ms for page write
			set_address(address);				//set the new address
		}
		i2cwrite(c[n]);							//write the data
	}
}
 
void read_data(u08 * destination, u08 datasize, u32 * address)//Reads a block of data from some address
{
	u08 n;
	datasize--;
	i2cstart();
	i2cwrite(SLA_R|(((*address)>>13)&0x08));	//set read to the correct block
	for(n=0;n<datasize;n++)
	{
		destination[n]=i2cread(_AK_);
		(*address)++;							//increment our pointer
		if(!(u16)*address)						//we reached the end of the block
		{
			i2cstop(); 
			set_address(address);
		}
	}
	destination[datasize+1]=i2cread(_NAK_);		//send NAK for the last byte recieved
}
 
u32 findtop()									//Find the address of record number where we enter painted eeprom
{
	u32 top=0;									//half way through rounded to nearest 12
	u08 n;
	for(n=17;n;)								//start by probing half way through
	{
		n--;
		top+=1<<n;								//trial setting of bit
		top = 12*( (u32) (top/12) );			//round down to nearest 12
		set_address(&top);						//the probe address
		if(i2cread(_NAK_)==MAGIC_NUMBER)		//see if its painted
			top-=1<<n;							//clear the nth bit
	}
	top =12*( (u32) (top/12) );					//make sure our answer is rounded correctly
	return top;
}
 
void painteeprom()								//Paints every 12th location with the magic number
{
	u08 magic=MAGIC_NUMBER;						//magic is our painting value
	u32 n=0;
	for(n=0;n<131072;n+=11)						//need to skip 11 bytes between each write location
	{
		set_address(&n);						//set the eeproms internal address register
		write_data(&magic,1,&n);				//write the data
	}
}
#endif

I2Cmem.h

#include <util/twi.h>						//I2C registers
#include <util/delay_basic.h>					//wait delay loop for page write
#include "avrlibtypes.h"
 
#define SLA_W 0b10100000					//microchip 24LC515  
#define SLA_R 0b10100001
#define SCL 100000
#define _AK_ (1<<TWINT)|(1<<TWEN)|(1<<TWEA)	//for setting up I2C read with AK and NAK from master
#define _NAK_ (1<<TWINT)|(1<<TWEN)
 
#define MAGIC_NUMBER 255					//painting value
 
void init_i2c();
void i2cstart();
void i2cwrite(u08 c);
u08 i2cread(u08 AK);
void set_address(u32* address);
void write_data(u08 * c, u08 datasize, u32*address);
void read_data(u08 * destination, u08 datasize, u32*address);
u32 findtop();
void painteeprom();
code/i2c_eeprom.1225956262.txt.gz · Last modified: 2008/11/06 07:24 by laurenceb

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki