我正在测试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);
}
}
}
}