atmega 328 i2c not working

Go To Last Post
12 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

guys,

i have been trying to interface pca9557d with atmgea 328p,i have to send a

1.slave address-since the device accepts aloong with 7bit and r/w, i can write data continously rather than right shifting it

2.configuration register

3.data for configuration register

4.i/o port selection

5.data for output

whenever i send the data with i2c the code is sending data and receving acknowledgement but i aint getting an output,i dunno where am going wrong,kindly help me.i have attached th code for your reference,kindly help me solve it

void i2c_write(int addr, char c_reg, char c_data, char i_reg, char i_data)
{
    //int WrAdd;
    //WrAdd = (addr << 1) | 0x00; //Put SLA-W into variable
    
    //Send START
    TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
    while(!(TWCR & (1 << TWINT)));
    //Send SLA-W byte
    TWDR = addr;
    TWCR = (1 << TWINT) | (1 << TWEN);
    while (!(TWCR & (1 << TWINT)));
    //Send data byte
    TWDR = c_reg;
    TWCR = (1 << TWINT) | (1 << TWEN);
    while (!(TWCR & (1 << TWINT)));
    //Send data byte
    TWDR = c_data;
    TWCR = (1 << TWINT) | (1 << TWEN);
    while (!(TWCR & (1 << TWINT)));
    //Send data byte
    TWDR = i_reg;
    TWCR = (1 << TWINT) | (1 << TWEN);
    while (!(TWCR & (1 << TWINT)));
    //Send data byte
    TWDR = i_data;
    TWCR = (1 << TWINT) | (1 << TWEN);
    while (!(TWCR & (1 << TWINT)));
    //Send STOP
    TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
    while(!(TWCR & (1<<TWSTO)));
}

int main(void)
{
    TWSR = 0; /* no prescaler */
    TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */
    DDRB=0xFF;//set SCL to 400kHz
    TWCR = (1<<TWEN)|(1<<TWEA);//to initiate i2c
     while(1)

    {
         i2c_write(0x30,0x03,0x00,0x01,0xFF);
    }
}

Last Edited: Sat. Jan 28, 2017 - 06:43 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If your "home brew" does not work start out with a respected, existing I2C library....

 

http://homepage.hispeed.ch/peter...

 

See the "AVR-GCC Libraries" section there.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sir,

the code i mentioned works like i receive an acknowledgwmwnt from the slave device,

the thing is i send a databyte holding register addresswhich is not getting accessed,i have hereby fragented the code as fusnctions for easy readability,kindly help me overcome the problem with this

/*
* i2c_eprom.c
*
* Created: 20-Jan-17 2:28:28 PM
*  Author: ARVIND
*/

#define F_CPU 18432000UL
#define SCL_CLOCK (100000L)
#include<avr/io.h>
#include<util/delay.h>
//#include<util/twi.h>
void i2c_init();
void i2c_start();
void i2c_stop();
int i2c_startcheck();
int i2c_addresscheck();
int i2c_datacheck();
void i2c_write(unsigned int m_data);
void i2c_slave_write(unsigned char sa,unsigned char ca,unsigned char c_data,unsigned char ps,unsigned char p_data);

int main(void)
{
    i2c_init();
        while(1)    
    {
        i2c_slave_write(0x30,0x03,0x00,0x01,0xFF);
    }
}

void i2c_start()
{
    TWCR= (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
    while (!(TWCR&(1<<TWINT)));
}
void i2c_init()
{
TWSR = 0; /* no prescaler */
TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */
DDRB=0xFF;//set SCL to 400kHz
TWCR = (1<<TWEN)|(1<<TWEA);//to initiate i2c
}

int i2c_startcheck()
{
    if ((TWSR & 0xF8)!=0x08)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

int i2c_addresscheck()
{
    if ((TWSR & 0xF8)!=0x18)
    {
        
        return 0;
    }
    else
    {
        
        return 1;
        //PORTB=0XFF;
    }
}

int i2c_datacheck()
{
    if ((TWSR & 0xF8)!=0x28)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

void i2c_stop()
{
    TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
}

void i2c_write(unsigned int m_data)
{
    TWDR=m_data;
    TWCR = (1<<TWINT) | (1<<TWEN);
    
}

void i2c_slave_write(unsigned char sa,unsigned char ca,unsigned char c_data,unsigned char ps,unsigned char p_data)
{
    i2c_start();
    if(i2c_startcheck())
    {
        i2c_write(sa);//slave address
        while (!(TWCR & (1<<TWINT)));//checking for acknowledge
        if(i2c_addresscheck())
        {
            PORTB=0xFF;
            i2c_write(ca);//configuration address
            while (!(TWCR & (1<<TWINT)));//checking for acknowledge
            if(i2c_datacheck())
            {
                i2c_write(c_data);//register address
                while (!(TWCR & (1<<TWINT)));//checking for acknowledge
                if(i2c_datacheck())
                {
                    i2c_write(ps);
                    while (!(TWCR & (1<<TWINT)));//checking for acknowledge
                    if(i2c_datacheck())
                    {
                        i2c_write(p_data);
                        while (!(TWCR & (1<<TWINT)));
                        if(i2c_datacheck())
                        {
                            i2c_stop();
                        }
                    }
                }
            }
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

See answer #2 above, what happens when you use a proven known good i2c library? 

It even has an example of saving/reading data from an eeprom.

 

Are you using pull up resistors?  if so what value?

 

Jim

 

 

FF = PI > S.E.T

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i aint using any pull up..since atmega 328p holds an inbuilt pullup..i aint using one.actually i checked the code and library both are same i have the same probs when i use the library too..thats y sir,

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You cannot use internal pull ups with I2C, you must use external pull ups. 4k7 is a good typical value (which also shows why you cannot use the internal pull ups, considering that these will typically be somewhere between 30k and 60k. The datasheet for the ATmega328P will confirm what the spec'd range is)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sir 

i have also used the library as you mentioned but yet i didnt get the proper output.this is the code i wrote kindly help me with this

#include <avr/io.h>
#include "i2cmaster.h"
#define Dev9557d  0x30      // device address of EEPROM 24C02, see datasheet
int main(void)
{
    unsigned char ret;
   i2c_init();                                // init I2C interface

    /* write 0x30 to PCA9557D address 0x05 (Byte Write) */
    ret = i2c_start(Dev9557d+I2C_WRITE);       // set device address and write mode
    if ( ret ) 
    {
        /* failed to issue start condition, possibly no device found */
        i2c_stop();
       
    }
    else 
    {
        /* issuing start condition ok, device accessible */
        i2c_write(0x03);                       // write address = 0X03 to select config
        i2c_write(0x00);                       // writeconfig address 0x00 to make ports config
       // i2c_stop();                            // set stop conditon = release bus

        /* write ok, read value back from eeprom address 0x05, wait until 
           the device is no longer busy from the previous write operation */
        //i2c_start_wait(Dev9557d+I2C_WRITE);     // set device address and write mode
        i2c_write(0x01);                        // write address = 0x01 to select the ports as output
        i2c_write(0xFF);//write data 0xff
        i2c_stop();
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sir i tried with 4.7k pull up.yet same problem persists...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

arvindpandi wrote:
#define Dev9557d 0x30 // device address of EEPROM 24C02, see datasheet i

 

Well a 24C02 has eight possible 8-bit slave addresses 0xA0, 0xA2, ..., 0xAE.

Your PCA9557D has eight possible 8-bit slave addresses 0x30, 0x32, ..., 0x3E.

 

The TWI peripheral and the Fleury library both use the 8-bit Slave Address e.g. 0x30/0x31 (W/R)

The Arduino Wire.h library and many other libraries use the 7-bit Slave Address e.g 0x18

 

The Slave addresses of both these devices are dependent on hardware pins: A0, A1, A2

 

Your first job is to wire your chip correctly.  Which means:

1. /RESET, A0, A1, A2 with appropriate pull-ups or pull-downs.

2. SDA, SCL with external pull-up resistors

3. 100nF capacitors on the VDD/VSS pins

 

The Fleury code should work just fine.   Obviously you need to do something on success or failure.  e.g. light an LED or print a message

 

Yes,  it is a good idea to "adapt" proven examples.   However,  this means writing accurate comments.   Hence my point about 24C02 addresses.

 

David.

Last Edited: Wed. Jan 25, 2017 - 07:17 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

THANKS GUYS

THE CODE WORKED,

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

guys

i am trying to read a character present in 0x20h at eeprom of arduino micro throught i2c,

i am using avr 328p xpalined mini board as i2c master,i have set the address of slave as ox30 in twar register,but i find the code not working,i also triend given wire.begin(0x18) as wire lib right shifts by one byte.kindly elp me soleve the problem i have used external pull up of 4.7k for master 328p and internal pull up for micro,i have pasted the codes below kindly help me solve it

 

1.code for master

#include<avr/io.h>
#include "i2cmaster.h"
void EEPROM_write(unsigned int uiAddress, unsigned char ucData);
unsigned char EEPROM_read(unsigned int uiAddress);
#define micro 0x30 
int main(void)
{
    i2c_init();
    DDRB=0xFF;
    unsigned char c;
    unsigned char ret;
    while(1)
    {
        
         i2c_start(micro+I2C_WRITE);          // set device address and write mode
         i2c_write(0x20);                     // write address = 0x20,where data is stored in eeprom of micro
        //  PORTB=0xFF;
        i2c_rep_start(micro+I2C_READ);        // set device address and read mode
         ret = i2c_readAck();                 // read one byte form address 0
         i2c_stop();
         EEPROM_write(0x0020,ret);
         c=EEPROM_read(0X0020);
         if(c=='a')
         {
             PORTB=0xFF;
         }
         else
         {
             PORTB=0x00;
         }                              
    }
}
void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
{
    /* Wait for completion of previous write */
    //while(EECR & (1<<EEPE));
    /* Set up address and Data Registers */
    EEAR = uiAddress;
    EEDR = ucData;
    /* Write logical one to EEMPE */
    EECR |= (1<<EEMPE);
    /* Start eeprom write by setting EEPE */
    EECR |= (1<<EEPE);
}
unsigned char EEPROM_read(unsigned int uiAddress)
{
    /* Wait for completion of previous write */
    //while(EECR & (1<<EEPE));
    /* Set up address register */
    EEAR = uiAddress;
    /* Start eeprom read by writing EERE */
    EECR |= (1<<EERE);
    /* Return data from Data Register */
    return EEDR;
}

 

2.code for slave

#include <Wire.h>
#include <EEPROM.h>
void setup()
{
  
 
  Wire.begin(0x18);
  //Wire.onReceive(receiveEvent);
  Wire.onRequest(requestEvent);
  Serial.begin(9600);
  EEPROM.write(0x20,'a');
pinMode(13,OUTPUT);
}
void loop()
{
  Serial.println(TWAR,HEX);
  unsigned char ret;
  ret=EEPROM.read(0X20);
  //Serial.println("*************************");
  //Serial.println(EEDR);
  //TWDR=ret;

void requestEvent()
{
Wire.write(ret);
}

 

  if(ret='a')
  {
    digitalWrite(13,HIGH);
    delay(500);
    digitalWrite(13,LOW);
    delay(500);
  }
}

 

 

Last Edited: Sat. Jan 28, 2017 - 06:56 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

code worked ,thank you