SPI中断问题求教
各位大牛周末好,我被个问题纠缠了2天,一直解决不了,特上来求教我做了个小玩具,ATMEGA8核心,SPI跟接收芯片通信(读写),I2C接OLED(这方式不太好,但为省几根飞线也将就着),本来用按键轮询方式控制一切都好,但想加一个旋转编码器做成个像样点的菜单,问题就出现了。
因为用旋转编码器要用到INT0、INT1,在下面的代码中,一到sei();就重启,在论坛搜了一下,大概明白打开中断必须有相应的中断处理程序,难道我必须用中断方式来处理SPI通信吗?具体该怎么做?void spi_init()
{
SPIDDR |= (1 << 3) | (1 << 5); // MOSI & SCK output
SPIDDR &= ~(1 << 4); // MISO input
SPCR = (1 << SPIE) | (1 << SPE) | (1 << MSTR) | (1 << SPR0); // Enable SPI, Master, clock rate = fuck/4
SPSR = 0x00;
PORT_SS_RECV |= (1 << SS_RECV); // disable Receiver
}
inline void spi_wait()
{
while (!(SPSR & (1 << SPIF)))
{
};
}
void RECV_write(unsigned char reg, unsigned char data)
{
PORTB &= ~(1 << SS_RECV);
SPDR = reg & 0b01111111; // send MAP (register address)
spi_wait();
SPDR = data; // send data
spi_wait();
PORTB |= (1 << SS_RECV); // raise SS_RECV
}
unsigned char RECV_read(unsigned char reg)
{
PORTB &= ~(1 << SS_RECV);
unsigned char datain;
SPDR =reg | ( 1<<7 ); // read operation
spi_wait();
SPSR = 0x00;
SPDR = 0x00;
spi_wait();
datain = SPDR;
PORTB |= (1 << SS_RECV); // raise SS_RECV
return datain;
}
//Interrupt Service Routine for INT0
ISR(INT0_vect)
{
// When an interrupt occurs, check the level of pin PD4 to determine the direction
if (ROTB) //equal (PIND & _BV(PD4))
// Increase enc
{
delayCycle(50);
if (ROTB) enc = 1;
}
else
{
// Decrease enc
delayCycle(50);
if (!ROTB) enc = 2;
}
}
//Interrupt Service Routine for INT1
ISR(INT1_vect)
{
enc = 3;
}
//OLED_ShowString(0,0,"SPI init");
spi_init();
OLED_delay(5000L);
//OLED_ShowString(1,1, "RECV init");
RECV_init(0x01);
GICR |= (1<<INT0) | (1<<INT1); // Enable INT0 and INT1
MCUCR |= (1<<ISC01) | (1<<ISC11); // Falling edge in INT0, INT1 (PD2,PD3) to cause interrupt
GIFR |= (1 << INTF1) | (1 << INTF0); //clear INT0,INT1
sei(); // Enable global interrupts P.S.如果必须有相应的中断处理程序,那I2C也必须添加相应的中断处理程序吗?
但我试验下来如果把上面代码的80行屏蔽(通过SPI读写),OLED显示是正常的,而OLED用的是I2C接口…… 搞掂了,第5行改成:
SPCR =(1 << SPE) | (1 << MSTR) | (1 << SPR0); // Enable SPI, Master, clock rate = fuck/4
去掉了(1 << SPIE) ,原来以为只要用SPI就要开中断的……我错了{:dizzy:}
页:
[1]