0
\$\begingroup\$

First of all let me say that I am a beginner in embedded programming. I am trying to do write/read using I2C protocol from 24LC256 EEPROM using Atmega16A.

While debugging in Atmel Studio 7, I see I am able to send Start condition and able to write data but when I call Stop, micro-controller just hangs.

I have checked all my connections and they look correct. Following is all my code.

#include<avr/io.h>
#include<util/delay.h>
#include<inttypes.h>

void TWI_start(void);
void TWI_repeated_start(void);
void TWI_init_master(void);
void TWI_write_address(unsigned char);
void TWI_read_address(unsigned char);
void TWI_write_data(unsigned char);
void TWI_read_data(void);
void TWI_stop(void);

unsigned char address=0xA0, read=1, write=0;
unsigned char write_data=0x01, recv_data;
unsigned int dataMemAddress=0x08;

int main(void)
{
    _delay_ms(2000);
    DDRB=0xff;  
    TWI_init_master();  // Function to initialize TWI
    while(1)
    {
        if(write_data==0x00)
        {
            write_data=1;
        }
        TWI_start(); // Function to send start condition
        TWI_write_address(address+write); // Function to write address and data direction bit(write) on SDA
        TWI_write_data(dataMemAddress);
        TWI_write_data(dataMemAddress);
        TWI_write_data(write_data);      // Function to write data in slave
        TWI_stop(); // Function to send stop condition
        _delay_ms(10); // Delay of 10 mili second
        TWI_start();
        TWI_write_address(address+write); // Function to write address and data direction bit(write) on SDA
        TWI_write_data(dataMemAddress);
        TWI_write_data(dataMemAddress);
        TWI_start();
        //TWI_repeated_start();
        TWI_read_address(address+read); // Function to write address and data direction bit(read) on SDA        
        TWI_read_data(); // Function to read data from slave
        TWI_stop();
        _delay_ms(2000);
        write_data = write_data * 2;
    }
}

void TWI_init_master(void) // Function to initialize master
{
    TWSR = 0;
    TWBR = 0x0C;//(1<<TWPS1);
    TWCR = (1<<TWEN);
    //TWBR=0x01; // Bit rate
    //TWSR=(0<<TWPS1)|(0<<TWPS0); // Setting prescalar bits
    // SCL freq= F_CPU/(16+2(TWBR).4^TWPS)
}

void TWI_start(void)
{
    // Clear TWI interrupt flag, Put start condition on SDA, Enable TWI
    TWCR= (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
    while(!(TWCR & (1<<TWINT))); // Wait till start condition is transmitted
    while((TWSR & 0xF8)!= 0x08); // Check for the acknowledgement
}

void TWI_repeated_start(void)
{
    // Clear TWI interrupt flag, Put start condition on SDA, Enable TWI
    TWCR= (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
    while(!(TWCR & (1<<TWINT))); // wait till restart condition is transmitted
    while((TWSR & 0xF8)!= 0x10); // Check for the acknoledgement
}

void TWI_write_address(unsigned char data)
{
    TWDR=data; // Address and write instruction
    TWCR=(1<<TWINT)|(1<<TWEN);    // Clear TWI interrupt flag,Enable TWI
    while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte transmitted
    while((TWSR & 0xF8)!= 0x18);  // Check for the acknoledgement
}

void TWI_read_address(unsigned char data)
{
    TWDR=data; // Address and read instruction
    TWCR=(1<<TWINT)|(1<<TWEN);    // Clear TWI interrupt flag,Enable TWI
    while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte received
    while((TWSR & 0xF8)!= 0x40);  // Check for the acknoledgement
}

void TWI_write_data(unsigned char data)
{
    TWDR=data; // put data in TWDR
    TWCR=(1<<TWINT)|(1<<TWEN);    // Clear TWI interrupt flag,Enable TWI
    while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte transmitted
    while((TWSR & 0xF8) != 0x28); // Check for the acknoledgement
}

void TWI_read_data(void)
{
    TWCR=(1<<TWINT)|(1<<TWEN);    // Clear TWI interrupt flag,Enable TWI
    while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte transmitted
    while((TWSR & 0xF8) != 0x50); // Check for the acknoledgement
    recv_data=TWDR;
    PORTB=recv_data;
}

void TWI_stop(void)
{
    // Clear TWI interrupt flag, Put stop condition on SDA, Enable TWI
    TWCR= (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
    //_delay_ms(100);
    //while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte transmitted
    while(!(TWCR & (1<<TWSTO)));  // Wait till stop condition is transmitted
}

24LC256 Interface with Atmega16A

\$\endgroup\$
  • \$\begingroup\$ Unless you have an explicit timeout mechanism, an I2C operation that does not elicit a response will indeed cause your program to "hang". \$\endgroup\$ – Chris Stratton May 4 '17 at 15:30
  • \$\begingroup\$ @ChrisStratton Do you mean I should use Interrupt ? How/Where can I put timeout ? \$\endgroup\$ – Embedd_Khurja May 4 '17 at 15:56
  • \$\begingroup\$ You'll need to add a means or exiting from the lines you have commented "Check for the acknowledgement" so that they are not eternal loops. It is up to you if you do that by monitoring a hardware timer, or loop count, or by a value or flag set from a timer interrupt. And independently of that, you'll want to figure out why those operations were not being acknowledged. \$\endgroup\$ – Chris Stratton May 4 '17 at 15:58
  • \$\begingroup\$ @ChrisStratton If I use delay(100) then uC hangs in next Start method ... \$\endgroup\$ – Embedd_Khurja May 4 '17 at 16:00
  • \$\begingroup\$ You can't use delay() for this! Doing this right is not simple, and required gaining a real understanding of the organization of computer programs and distinction between blocking and polling operations. \$\endgroup\$ – Chris Stratton May 4 '17 at 16:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.