Potrzebuję pomocy. Zaprogramowałem Atmege328 z myślą o testach interfejsu TWI (I2C). Hardware'owo linie interfejsu (SCL, SDA) mam przez rezystory podciągnięte do +5V i cały procek tymże napięciem zasilam.
Pytanie brzmi dlaczego PB0 nie clear'uje się, innymi słowy : dlaczego procesor ani razu nie wchodzi w procedurę obsługi przerwania od TWI jeśli przecież ma moduł włączony, poprawnie zainicjalizowany a przerwanie od tego jest załączone.
Efekt powinien moim zdaniem być taki że po kliknięciu przycisku podpiętego do PB5 transmisja powinna się rozpocząć a prędzej czy później przerwanie powinno być odpalone.
#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);
}
}
}
}