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
}
 
#define i2cstop TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO)
 
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=65532;					//half way through rounded to nearest 12
	u08 n;
	u08 probe;
	for(n=17;n;n--)					//start by probing half way through
	{
		set_address(&top);			//the probe address
		probe=i2cread(_AK_);			//read some data from there
		if(probe!=MAGIC_NUMBER)			//see if its unpainted
		{
			top|=1<<(n-1);
			top = 12* ( (u32) ( (top | (1<<(n-1))) / 12) );//round down to nearest 12
		}
 
	}
	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 "avrlibtypes.h"
 
#define SLA_W 0b10100000					//microchip 24LC512  
#define SLA_R 0b10100001
#define SCL 100000
 
void init_i2c();
u08 i2cstart();
u08 i2cwrite(char c);
u08 write_data(char * c, u16 address, u08 datasize);
u08 read_data(char * destination, u16 address, u08 datasize);
code/i2c_eeprom.1225930940.txt.gz · Last modified: 2008/11/06 00:22 by laurenceb

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki