ATMEGA32 to at24c256

Discussion in 'Embedded Systems and Microcontrollers' started by wisnu, Jan 18, 2009.

  1. wisnu

    Thread Starter New Member

    Jan 18, 2009
    2
    0
    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
     
  2. wisnu

    Thread Starter New Member

    Jan 18, 2009
    2
    0
    ^_^

    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);
    }

     
Loading...