ATMEGA32 to at24c256

Thread Starter

wisnu

Joined Jan 18, 2009
2
Best regard
I'm making a circuit using ATMEGA32 that run in 11.0592 MHz crystal.
I want to add an at24c256 to the circuit

I have a code, But the data that I write to the eeprom didn't match the data I read from the eeporm.

Here is my code

=======

//#=============================================================================#
//#Nu revision September 9th 2008, Add init_eeprom, convert AT24C16 to AT24C256 #
//#=============================================================================#

#include <UTIL/DELAY.h>
#include <AVR/io.h>
#include <avr/interrupt.h>
#include "var_parameter.h"
#include "eeprom.h"


void init_eeprom(void)
{
SREG |= 0x80;//global interrupt enabled
EEPROM_DDR |= ((1 << SDA) | (1 << SCL));//SDA &SCL become output line
TWSR &= 0xFC;//no bit rate prescaler
TWBR = 10;//
}

//=====================================================================
// EEPROM Device ATMEL AT24C256, 32 Kilo Byte EEPROM
//=====================================================================
//-- Writing single address only
unsigned char eeprom_write(unsigned char type, unsigned char dev_addr, unsigned short int addr, unsigned char length)
{
unsigned char i;
unsigned char err = 1;
unsigned char hi_addr = addr >> 8;
unsigned char lo_addr = (unsigned char)addr;
unsigned char sla_w = dev_addr & 0xFE;

if (addr > MAX_ADDR)//exit if address invalid
return 1;

//----------Initiate Start Bit
TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
while (!(TWCR & (1 << TWINT)));//wait until TWI interrupt occured
if ((TWSR & STATUS_CHECK) == START) {//start have transmitted?
//-----------Send SLA_W
TWDR = sla_w;
TWCR = (1 << TWINT) | (1 << TWEN);
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) == SLA_W_ACK) {//sla+w have transmitted?
//-------------Send High Address
TWDR = hi_addr;
TWCR = (1 << TWINT) | (1 << TWEN);
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) == MT_DATA_ACK) {//High address have transmitted?
//---------------Send Lo Address
TWDR = lo_addr;
TWCR = (1 << TWINT) | (1 << TWEN);
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) == MT_DATA_ACK) {//Low address have transmitted?
//------------------Send Data
err = 0;
for (i = 0; i < length; i++) {
TWDR = eeprom_buffer;
TWCR = TWI_DATA;
while (!(TWCR & (1 << TWINT)));
if ((TWSR & 0xF8) != MT_DATA_ACK) {//data transmitted?
err = 1;
break;
}
}
}
}
}
}
//---------Initiate Communication Stop
TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN);
TWCR &= ~(1 << TWEN);//disable TWI function
PORTA = err;
return err;
}

unsigned char eeprom_read(unsigned char type, unsigned char dev_addr, unsigned short int addr, unsigned char length)
{
unsigned char sla_w = dev_addr & 0xFE;
unsigned char sla_r = dev_addr | 0x01;
unsigned char err = 1;
unsigned char i;
unsigned char mode = START;
unsigned char hi_addr = addr >> 8;
unsigned char lo_addr = (unsigned char)addr;

if (type == random) {//dummy write to make the pointer point the selected address
PORTA = 0x01;
mode = REPEATED_START;
TWCR = TWI_START;
while (!(TWCR & (1 << TWINT)));
PORTA = 0x02;
if ((TWSR & STATUS_CHECK) == mode) {//start transmitted?
PORTA = 0x03;
TWDR = sla_w;
TWCR = TWI_DATA;
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) == SLA_W_ACK) {//sla+w transmitted?
TWDR = hi_addr;
TWCR = TWI_DATA;
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) == SLA_W_ACK) {//High Address transmitted?
TWDR = lo_addr;
TWCR = TWI_DATA;
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) != MT_DATA_ACK) //Low Address transmitted?
return err;
}
}
}
}

TWCR = TWI_START;
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) == mode) {//start transmitted?
TWDR = sla_r;
TWCR = TWI_DATA;
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) == SLA_R_ACK) {//sla+r transmitted?
err = 0;
i = 0;
for (i = 0; i < length; i++) {
if (i == length - 1)//read last byte
TWCR = TWI_DATA_NACK;
else //read byte then continue read again
TWCR = TWI_DATA;
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) == MR_DATA_ACK || (TWSR & STATUS_CHECK) == MR_DATA_NACK)
eeprom_buffer = TWDR;
else {//break operation if error comm occured
err = 1;
break;
}
}
}
}
TWCR = TWI_STOP;//stop communication
TWCR &= ~(1 << TWEN);//disable TWI function
return err;
}

========

Is there anything wrong???
How to make it work correctly?

Is there someone who have make the circuit work???
Please help ASAP
 

Thread Starter

wisnu

Joined Jan 18, 2009
2
^_^

I've got my code working, it was only problem with some command:p
How pity I am.

Here is the guarantee working code
Configured to work with ATMEGA32 that run on 11.0592 MHz

Below here is my code
I use only three function that is eeprom_init, eeprom_write, eeprom_read
All the data is transfered via eeprom_buffer.
if u want to write to eeprom, just write the data to eeprom_buffer
and if u read the data from eeprom, data will be on eeprom buffer
Oh yeah, mention that maximum sending data is 64 bytes, becoz if u read the datasheet, every data write, only 6 lower bit incremented (64) so if you try to write more than 64, it will be rounded.
Ah yes one more thing, sorry since I am a new user for this stuff
Sorry if I write a bad looking code, please mail me if you change my code into a beautiful one at wize_the_bendit@yahoo.co.id


My code here is just an example
Adjust the code to fix ur requierement

here is the eeprom.h
===================================================
#ifndef __EEPROM_OPERATION__
#define __EEPROM_OPERATION__

//TWI STATUS (TWSR)
#define START 0x08
#define REPEATED_START 0x10
#define SLA_W_ACK 0x18
#define SLA_W_NACK 0x20
#define MT_DATA_ACK 0x28
#define MT_DATA_NACK 0x30
#define SLA_R_ACK 0x40
#define SLA_R_NACK 0x48
#define MR_DATA_ACK 0x50
#define MR_DATA_NACK 0x58
//TWI Function method
#define byte 0
#define page 1
#define current 0
#define random 1
//TWI Spesification
#define SDA PC1
#define SCL PC0
#define EEPROM_DDR DDRC
#define EEPROM_PORT PORTC
#define MAX_ADDR 32768
#define SLAVE_ID 0xA0
//TWI Command List
#define STATUS_CHECK 0xF8
#define TWI_START 0xA4
#define TWI_STOP 0xD4
#define TWI_DATA 0xC4
#define TWI_DATA_NACK 0x84
//EEPROM Address Division
#define LAST_LOG_PTR 4072
#define LOG_BEGIN 3072
#define LOG_TIMESTAMP_BEGIN 3272
#define K_ADDRESS_BEGIN 0
#define INTERNAL_PARAMETER_BEGIN 2816
#define SPARE BEGIN 4096
#define DISPLAY_TEXT_BEGIN 5120
#define DATA_TYPE_BEGIN 16384
#define DATA_TREAT_BEGIN 17152
#define MAX_VALUE_BEGIN 17920
#define MIN_VALUE_BEGIN 19456
#define ADDRESS_BEGIN 20994
#define DATA_TREAT2_BEGIN 22528
#define DECISION_BEGIN 23296
#define RAM_LAST_READED_LOG 346
#define RAM_LOG_BEGIN 328
#define RAM_LOG_END 342
#define RAM_LOG_TIMESTAMP_BEGIN 305
#define RAM_LOG_TIMESTAMP_END 328

extern void init_eeprom(void);
extern unsigned char eeprom_write(unsigned char dev_addr, unsigned short int addr, unsigned char length);
extern unsigned char eeprom_read(unsigned char type, unsigned char dev_addr, unsigned short int addr, unsigned char length);

#endif

here is the eeprom.c
======================================================
//#=============================================================================#
//#Nu revision September 9th 2008, Add init_eeprom, convert AT24C16 to AT24C256 #
//#=============================================================================#

#include <UTIL/DELAY.h>
#include <AVR/io.h>
#include <avr/interrupt.h>
#include "var_parameter.h"
#include "eeprom.h"


void init_eeprom(void)
{
SREG |= 0x80;//global interrupt enabled
EEPROM_DDR |= ((1 << SDA) | (1 << SCL));//SDA &SCL become output line
TWSR &= 0xFC;//no bit rate prescaler
TWBR = 10;//
}

//=====================================================================
// EEPROM Device ATMEL AT24C256, 32 Kilo Byte EEPROM
//=====================================================================

//Up to 64 bytes, address is rounded up if more than 64 bytes written
unsigned char eeprom_write(unsigned char dev_addr, unsigned short int addr, unsigned char length)
{
unsigned char i;
unsigned char err = 1;
unsigned char hi_addr = addr >> 8;
unsigned char lo_addr = (unsigned char)addr;
unsigned char sla_w = dev_addr & 0xFE;//dev_addr & 0xFE;

if (addr > MAX_ADDR)//exit if address invalid
return 1;

//----------Initiate Start Bit
TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
while (!(TWCR & (1 << TWINT)));//wait until TWI interrupt occured
if ((TWSR & STATUS_CHECK) == START) {//start have transmitted?
//-----------Send SLA_W
TWDR = sla_w;
//TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA);
TWCR = 0xC4;
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) == SLA_W_ACK) {//sla+w have transmitted?
//-------------Send High Address
TWDR = hi_addr;
TWCR = (1 << TWINT) | (1 << TWEN);
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) == MT_DATA_ACK) {//High address have transmitted?
//---------------Send Lo Address
TWDR = lo_addr;
TWCR = (1 << TWINT) | (1 << TWEN);
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) == MT_DATA_ACK) {//Low address have transmitted?
//------------------Send Data
err = 0;
for (i = 0; i < length; i++) {
TWDR = eeprom_buffer;
TWCR = (1 << TWINT) | (1 << TWEN);
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) != MT_DATA_ACK) {//data transmitted?
err = 1;
break;
}
}
}
}
}
}
//---------Initiate Communication Stop
TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN);
//---------Disable TWI Function
TWCR &= ~(1 << TWEN);
//---------Delay before to wait exactly TWI stop
_delay_ms(1);
return err;
}

//----Address read rounded after reaching max value
unsigned char eeprom_read(unsigned char type, unsigned char dev_addr, unsigned short int addr, unsigned char length)
{
unsigned char sla_w = dev_addr & 0xFE;
unsigned char sla_r = dev_addr | 0x01;
unsigned char err = 1;
unsigned char i;
unsigned char mode = START;
unsigned char hi_addr = addr >> 8;
unsigned char lo_addr = (unsigned char)addr;
//--------Read using random method, using fake byte write to designated address
if (type == random) {
mode = REPEATED_START;
TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) == START) {//start transmitted?
TWDR = sla_w;
TWCR = (1 << TWINT) | (1 << TWEN);
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) == SLA_W_ACK) {//sla+w transmitted?
TWDR = hi_addr;
TWCR = (1 << TWINT) | (1 << TWEN);
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) == MT_DATA_ACK) {//High Address transmitted?
TWDR = lo_addr;
TWCR = (1 << TWINT) | (1 << TWEN);
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) != MT_DATA_ACK) {//Low Address transmitted?
return err;
}
}
}
}
}
//----------Reading Function, Status will be checked as REPEATED START if using random method
//----------Sending Start Condition
TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) == mode) {//start transmitted?
//---------SLA_R
TWDR = sla_r;
TWCR = (1 << TWINT) | (1 << TWEN);
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) == SLA_R_ACK) {//sla+r transmitted?
err = 0;
for (i = 0; i < length; i++) {
if (i == (length - 1))//read last byte
TWCR = (1 << TWINT) | (1 << TWEN);
else //read byte then continue read again
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA);
while (!(TWCR & (1 << TWINT)));
if ((TWSR & STATUS_CHECK) == MR_DATA_ACK || (TWSR & STATUS_CHECK) == MR_DATA_NACK) {
eeprom_buffer = TWDR;
}
else {//break operation if error comm occured
err = 1;
break;
}
}
}
}
TWCR = TWI_STOP;//stop communication
TWCR &= ~(1 << TWEN);//disable TWI function
_delay_ms(1);
return err;
}

here is the var_parameter.c, actually I cut my code because u won't need that
====================================================
#ifndef __GLOBVAR__
#define __GLOBVAR__

unsigned char eeprom_buffer[128];

#endif


to run it
I have this eeprom_test.c
====================================================
#include <avr/io.h>
#include <UTIL/delay.h>
#include <compat/twi.h>
#include <avr/interrupt.h>
#include "var_parameter.h"
#include "eeprom.h"

int main(void)
{
unsigned char x;
DDRA = 0xFF;
init_eeprom();
eeprom_buffer[0] = 0xCC;
eeprom_buffer[1] = 0xAB;
x = eeprom_write(SLAVE_ID, 0x0000, 2);
eeprom_buffer[0] = 0x0A;
x = eeprom_write(SLAVE_ID, 0x0003, 1);
eeprom_buffer[0] = 0xF0;
x = eeprom_write(SLAVE_ID, 0x0002, 1);
eeprom_buffer[0] = 0x0F;
x = eeprom_write(SLAVE_ID, 0x0003, 1);
eeprom_buffer[0] = 0xDF;
x = eeprom_write(SLAVE_ID, 0x0004, 1);
eeprom_read(random, SLAVE_ID, 0x0003, 2);
PORTA = eeprom_buffer[1];
while(1);
return 0;
}

SIGNAL(TWI_vect)
{
_delay_ms(5000);
}

 
Top