UKHAS Wiki

UK High Altitude Society

User Tools

Site Tools


code:i2c_eeprom

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
code:i2c_eeprom [2008/10/27 00:56] laurencebcode:i2c_eeprom [2009/03/20 04:50] (current) laurenceb
Line 2: Line 2:
  
  
-<code c> +<code c>#include "i2cmem.h" 
-#include "i2cmem.h" +#ifdef EEPROM 
-//note that with microchip EEPROM at least, the internal buffer is only 64 bytes in size, so write_data can only accept a maximum of 64 as the size+ 
 +//----------General I2C functions------------------------------------------------------------------------- 
 + 
 +volatile u08 I2Cerr;
  
 void init_i2c() void init_i2c()
 { {
- TWBR=(u08)((float)F_CPU/(2*SCL)-8.0); //sets the correct clock rate defined as SCL+ TWBR=(u08)(((float)F_CPU/(2.0*(float)SCL))-8.0);//sets the correct clock rate defined as SCL
 } //we dont need to enable the hardware - its done in write } //we dont need to enable the hardware - its done in write
  
-u08 i2cstart()+void i2cstart()
 { {
 + u16 timeout=1;
  TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); //send start  TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); //send start
- while (!(TWCR & (1<<TWINT))); //wait for a start to be transmitted+ while (!(TWCR & (1<<TWINT)) && timeout) 
 + timeout++; //wait for a start to be transmitted 
 + if(!timeout) 
 + I2Cerr|=16; //timeout out waiting for start error 
 + TWCR = (1<<TWEN ); //clear the start condition
  if (((TWSR & 0xF8) != TW_START)&&((TWSR & 0xF8) != TW_REP_START))  if (((TWSR & 0xF8) != TW_START)&&((TWSR & 0xF8) != TW_REP_START))
- return 1; //error + I2Cerr|=1; //error
- return 0; //worked ok+
 } }
  
-#define i2cstop TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO)+void i2cstop() 
 +
 + u16 timeout=1; 
 + TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO)
 + while (!(TWCR & (1<<TWSTO)) && timeout) //wait for stop to be sent 
 + timeout++; 
 + if(!timeout) 
 + I2Cerr|=64; //timeout waiting for stop error 
 +}
  
-u08 i2cwrite(char c)+void i2cwrite(u08 c)
 { {
 + u16 timeout=1;
  TWDR = c; //load the data  TWDR = c; //load the data
  TWCR = (1<<TWINT)|(1<<TWEN);  TWCR = (1<<TWINT)|(1<<TWEN);
- while (!(TWCR & (1<<TWINT))); //wait for it to be sent + while (!(TWCR & (1<<TWINT)) && timeout) //wait for it to be sent 
- if ((TWSR & 0xF8) !=TW_MT_SLA_ACK) + timeout++; 
- return 2; //error + if(!timeout) 
- return 0; + I2Cerr|=32; //timeout out waiting for write complete error 
 + if ( ((TWSR&0xF8)!=TW_MT_SLA_ACK)&&((TWSR&0xF8)!=TW_MR_SLA_ACK)&&((TWSR&0xF8)!=TW_MT_DATA_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 response error
 + if(((TWSR & 0xF8) !=TW_MR_DATA_ACK) && ((TWSR & 0xF8) !=TW_MR_DATA_NACK))
 + I2Cerr|=4;
 + return TWDR;
 +}
 +
 +//----------EEPROM specific stuff-------------------------------------------------------------------------
 +//Designed for 12 byte records atm
 +
 +void set_address(u32 * address) //Sets an address from a pointer - can select the correct physical device but reqires idle bus
 +{
 + i2cstart();
 + i2cwrite(SLA_W|(((*address)>>15)&0x02)); //the block
 + i2cwrite((u08)((*address)>>8)); //address write MSB
 + i2cwrite((u08)(*address)); //address write LSB
 +}
  
-u08 write_data(char * c, u16 address, u08 datasize)+void write_data(u08 * c, u08 datasize, u32 * address)//The address will be incremented as the data is written
 { {
- u08 n,err; + u08 n; //up to 256 bytes can be written at once 
- err|=i2cstart(); + for(n=0;n<datasize;n++,(*address)++)
- err|=i2cwrite(SLA_W); +
- err|=i2cwrite((u08)(address>>8)); //address write MSB +
- err|=i2cwrite((u08)address); //address write LSB +
- for(n=0;n<datasize;n++)+
  {  {
- err|=i2cwrite(c[n]); //the data+ if(!((u08)*address)) //check the address for overflow for the 8 LSB (Atmel) 
 +
 + i2cstop(); //triggers a page write 
 + _delay_loop_2( (u16) ( (float)F_CPU*0.006/4.0 ) );//delay 6 ms for page write 
 + set_address(address); //set the new address 
 +
 + i2cwrite(c[n]); //write the data
  }  }
- i2cstop; //send stop 
- return err; //worked ok, no error 
 } }
  
-u08 read_data(char * destination, u16 address, u08 datasize)+void read_data(u08 * destination, u08 datasize, u32 * address)//Reads a block of data from some address
 { {
- u08 n,err;+ u08 n;
  datasize--;  datasize--;
- err|=i2cstart(); + i2cstart(); 
- err|=i2cwrite(SLA_W); + i2cwrite(SLA_R|((u08)((*address)>>15)&0x02)); //set read to the correct block 
- err|=i2cwrite((u08)(address>>8)); //address write MSB + for(n=0;n<datasize;n++) //the eeproms address pointer should have been setup already
- err|=i2cwrite((u08)address); //address write LSB +
- err|=i2cstart(); //repeated start +
- TWDR=SLA_R; //slave read mode +
- TWCR = (1<<TWINT)|(1<<TWEN); +
- while (!(TWCR & (1<<TWINT))); //wait for it to be sent +
- if ((TWSR & 0xF8) !=TW_MR_SLA_ACK) +
- err|=4; //error +
- for(n=0;n<datasize;n++)+
  {  {
- TWCR=((1<<TWINT)|(1<<TWEN)|(1<<TWEA)); + destination[n]=i2cread(_AK_)
- while (!(TWCR & (1<<TWINT))); //wait for it to be recieved - NOTE there is no error handling + (*address)++; //increment our pointer 
- destination[n]=TWDR; //get the data with AK returned + /*if(!(u16)(*address)) //we reached the end of the block 
- if((TWSR & 0xF8) !=TW_MR_DATA_ACK+
- err|=8;+ i2cstop();  
 + set_address(address); 
 + }This isn't needed on the Atmel chips*/
  }  }
- TWCR=((1<<TWINT)|(1<<TWEN)); + destination[datasize]=i2cread(_NAK_); //send NAK for the last byte recieved 
- while (!(TWCR & (1<<TWINT))); //wait for it to be recieved - NOTE there is no error handling + i2cstop(); 
- destination[datasize+1]=TWDR; //send NAK for the last byte recieved + (*address)++;
- if((TWSR & 0xF8!=TW_MR_DATA_NACK) +
- err|=16+
- i2cstop; //send stop +
- return err;+
 } }
  
 +
 +u32 findtop() //Find the address of record number where we enter painted eeprom
 +{
 + u32 top=12*((u32)1<<13); //half way through rounded down to 12
 + u08 n,endcond=TRUE;
 + u16 place=1<<13;
 + for(n=14;endcond;) //start by probing half way through - place is in records
 + {
 + set_address(&top); //the probe address
 + if(n)
 + n--; //need to decr here to get 1 byte resolution
 + else
 + endcond=FALSE; //terminate the loop after completion //need to decr here to get 1 byte resolution
 + i2cstart(); //read the slave
 + i2cwrite(SLA_R);
 + if(i2cread(_NAK_)==MAGIC_NUMBER) //see if its painted
 + place&=~(1<<n); //clear the nth bit in the place holder
 + if(n)
 + place|=(1<<(n-1)); //set the next bit
 + i2cstop();
 + if(place>10922)
 + place=10922;
 + top = 12*( (u32)place ); //place is in units of 12
 + }
 + set_address(&top);
 + i2cstart();
 + i2cwrite(SLA_R);
 + if(i2cread(_NAK_)!=MAGIC_NUMBER) //check the location to make sure its blank
 + place++;
 + top = 12*( (u32)place );
 + 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<131072;n++/*n+=12*/) //this writes every (12th) byte
 + {
 + /*
 + set_address(&n);
 + i2cwrite(magic); //write the data
 + if((u08)n>243) //our next n will be across a page boundary
 + {
 + i2cstop();
 + _delay_loop_2( (u16) ( (float)F_CPU*0.006/4.0 ) );//delay 6 ms for page write
 + }*/
 + if(!((u08)n)) //this code is for writing every byte
 + {
 + i2cstop();
 + _delay_loop_2( (u16) ( (float)F_CPU*0.006/4.0 ) );//delay 6 ms for page write
 + set_address(&n);
 + }
 + i2cwrite(magic);
 + wdt_reset();
 + }
 + i2cstop();
 +}
 +#endif
 </code> </code>
 +
 ===== I2Cmem.h ===== ===== I2Cmem.h =====
-<code c> +<code c>#include <util/twi.h> //I2C registers 
-#include <util/twi.h> //I2C registers+#include <util/delay_basic.h> //wait delay loop for page write
 #include "avrlibtypes.h" #include "avrlibtypes.h"
  
Line 88: Line 179:
 #define SLA_R 0b10100001 #define SLA_R 0b10100001
 #define SCL 100000 #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 init_i2c();
-u08 i2cstart(); +void i2cstart(); 
-u08 i2cwrite(char c); +void i2cstop(); 
-u08 write_data(char * c, u16 address, u08 datasize); +void i2cwrite(u08 c); 
-u08 read_data(char * destination, u16 address, u08 datasize);+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> </code>
- 
- 
code/i2c_eeprom.1225068991.txt.gz · Last modified: 2008/10/27 00:56 by laurenceb

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki