0

I am testing TWI module in AVR (Atmega328P). I have pulled up SCL and SDA lines. Why TWI interrupt service routine can not fire even once after switch (PB5) clicked?

Please notice that I have this interrupt enabled, I have also TWI module enabled and I have also start transmission after switch clicked.

Please help.

My code is:

#include <avr/io.h>
#include <avr/interrupt.h>

/* define slave (MPU6050) address as 0x68 because AD0 is low */
#define SLAVE_ADDRESS (0x68)
#define WHO_AM_I (0x75)

volatile enum state
{
    IDLE,
    START_BIT_TRANSMIT,
    SLAVE_ADDRESS_TRANSMIT,
    DATA_TRANSMIT
} sm;

void TimerInit()
{
    /* overflow interrupt enable and start timer on frequency 8MHz / 1024 */
    TIMSK0 |= (1 << TOIE0);
    TCCR0B |= (1 << CS00) | (1 << CS02);
}

void TwiInit()
{
    /* 100 kHz frequency of TWI and enable TWI module and interrupt from them */
    TWBR = 8;
    TWCR = (1 << TWEN) | (1 << TWIE);
}

/* TWI interrupt service routine */
ISR(TWI_vect)
{
    PORTB &= ~(1 << PB0);

    switch (sm)
    {
        case IDLE:
        {
            break;
        }

        case START_BIT_TRANSMIT:
        {
            /* clear start bit manually and prepare slave address SLA+W */
            TWCR &= ~(1 << TWSTA);
            TWDR = (SLAVE_ADDRESS << 1);
            TWCR |= (1 << TWINT);

            if ((TWSR == 0x08) || (TWSR == 0x10))
            {
                sm = SLAVE_ADDRESS_TRANSMIT;
            }
            break;
        }

        case SLAVE_ADDRESS_TRANSMIT:
        {
            /* prepare data */
            TWDR = WHO_AM_I;
            TWCR |= (1 << TWINT);

            if ((TWSR == 0x18) || (TWSR == 0x20))
            {
                sm = DATA_TRANSMIT;
            }
            break;
        }

        case DATA_TRANSMIT:
        {
            /* prepare stop bit */
            TWCR |= (1 << TWINT) | (1 << TWSTO);

            if ((TWSR == 0x28) || (TWSR == 0x30))
            {
                sm = IDLE;
            }
            break;
        }

        default:
        {
            break;
        }
    }
}

/* timer overflow interrupt service routine */
ISR(TIMER0_OVF_vect)
{
    PORTD &= ~(1 << PD7);
}

int main(void)
{
    /* diodes output */
    DDRB |= (1 << PB0);
    DDRD |= (1 << PD7);

    /* diodes turn off */
    PORTB |= (1 << PB0);
    PORTD |= (1 << PD7);

    /* pull up resistor on PD5 input switch */
    PORTD |= (1 << PD5);

    TimerInit();
    TwiInit();

    sei();

    while (1)
    {
        if (!((PIND >> PD5) & 1))
        {
            if (sm == IDLE)
            {
                sm = START_BIT_TRANSMIT;
                TWCR |= (1 << TWSTA) | (1 << TWINT);
            }
        }
    }
}
Adamos19
  • 49
  • 5
  • Probably get more interest over on Arduino SE. –  Oct 02 '17 at 20:44
  • Thank you for your advice but I won't use arduino now, maybee later. Now I have my own starting set using prototype board. – Adamos19 Oct 02 '17 at 21:27
  • What are the values of your pull-up resistors? This question might be more suited for the EE stack exchange, because it's completely possible that your circuitry is faulty as well. – Ernest3.14 Oct 05 '17 at 06:21
  • Sorry friends, my fault. I have faulty circuitry like @Ernest3 said. Very sorry and thank you. This code is working well. I can not say what is wrong but after mount this circuitry again based on the same elements, everything is fine. Thank you once again and sorry for wasting your time. Adam. – Adamos19 Oct 05 '17 at 14:08
  • No problem, happens all the time :) – Ernest3.14 Oct 05 '17 at 21:16

0 Answers0