为什么来自TWI的中断无法触发

时间:2017-10-02 20:29:25

标签: interrupt avr i2c

我正在测试AVR(Atmega328P)中的TWI模块。 我已经拉高了SCL和SDA线。 为什么TWI中断服务程序在开关(PB5)点击后甚至无法触发一次?

请注意我已启用此中断,我也启用了TWI模块,并且在切换开关后我也开始传输。

请帮忙。

我的代码是:

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

0 个答案:

没有答案