0

#define sda_on PORTA_DIRSET = PIN1_bm ; PORTA_OUTSET = PIN1_bm ;
#define sda_read PORTA_DIRCLR = PIN1_bm ;while(PORTA_IN & (PIN1_bm));PORTA_DIRSET = PIN1_bm ;
#define sda_off PORTA_DIRSET = PIN1_bm ;PORTA_OUTCLR = PIN1_bm ;
#define scl_on PORTA_DIRSET = PIN2_bm ;PORTA_OUTSET = PIN2_bm ;
#define scl_off PORTA_DIRSET = PIN2_bm ;PORTA_OUTCLR = PIN2_bm ;
#include <xc.h>
#include <util/delay.h>
void i2c_start(void)
{
    sda_on;
    scl_on;
    _delay_ms(10);
    sda_off;
    _delay_ms(10);
    scl_off;
}
void i2c_stop(void)
{
    sda_off;
    scl_off;
    _delay_ms(10);
    scl_on;
    _delay_ms(10);
    sda_on;
}
void i2c_data_write(unsigned char data)
{
    for(int i=0;i<8;i++)
    {
        if(data & 0x80) 
        {
            sda_on;
        }
        else sda_off;
        _delay_ms(10);
        scl_on;
        _delay_ms(10);
        scl_off;
        data = data << 1;
    }
    scl_on;
    sda_on;
    _delay_ms(10);
    sda_read;
    _delay_ms(10);   
    scl_off;
    _delay_ms(10);
}

Its a just write operation in 24c32a eeprom using by Attiny402..its not working ..im using simulating with debugging by proteus software....i2c debugger gives always question mark while im run the simulation help me..

1 Answers1

1

a quick answer: those macros should be changed to use bit-wise-OR assignment |= and bit-wise-AND assignment &= instead.

#define sda_on PORTA_DIRSET = PIN1_bm ; PORTA_OUTSET = PIN1_bm ;
#define scl_on PORTA_DIRSET = PIN2_bm ;PORTA_OUTSET = PIN2_bm ;

The macro sda_on sets PORTA_OUTSET to the value PIN1_bm, while the macro scl_on sets PORTA_OUTSET to the value PIN2_bm.

From those macros, we know the two pins sda and scl are both on PORTA, and the macros operate with bit-mask for the two pins. In general, a bit-mask of port pin would have only one bit set, like 0x01 or 0x02 or 0x04, and so on.

Then, at the beginning of i2c_start(), a sda_on is followed by a scl_on, that makes the value of PORTA set to PIN2_bm but not the correct value PIN1_bm | PIN2_bm which will set both pins to high level for the setup-time of a start-condition of i2c.

void i2c_start(void)
{
  sda_on; // PORTA_DIRSET = PIN1_bm ; PORTA_OUTSET = PIN1_bm ;
  scl_on; // PORTA_DIRSET = PIN2_bm ;PORTA_OUTSET = PIN2_bm ;
  // at this point, PORTA_DIRSET = PIN2_bm ;PORTA_OUTSET = PIN2_bm ;
  // But not, PORTA_DIRSET = PIN1_bm | PIN2_bm ;PORTA_OUTSET = PIN1_bm | PIN2_bm ;
  _delay_ms(10);
  sda_off;
  _delay_ms(10);
  scl_off;
}

So, the rough solution is to change the macros like the followings.

#define scl_on PORTA_DIRSET |= PIN2_bm ;PORTA_OUTSET |= PIN2_bm ;
#define scl_off PORTA_DIRSET &= ~PIN2_bm ;PORTA_OUTCLR &= ~PIN2_bm ;

Or, you could use two ports for the two pins, like sda on PORTA and scl on PORTB, if there is no other pin sharing the same port, then the bit-wise-OR assignment |= and bit-wise-AND assignment &= would be not necessary.

user6099871
  • 131
  • 1
  • 4