swing 发表于 2012-9-15 11:38:34

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

swing 发表于 2012-9-15 11:46:18

P.S.如果必须有相应的中断处理程序,那I2C也必须添加相应的中断处理程序吗?
但我试验下来如果把上面代码的80行屏蔽(通过SPI读写),OLED显示是正常的,而OLED用的是I2C接口……

swing 发表于 2012-9-15 14:31:30

搞掂了,第5行改成:
SPCR =(1 << SPE) | (1 << MSTR) | (1 << SPR0); // Enable SPI, Master, clock rate = fuck/4
去掉了(1 << SPIE) ,原来以为只要用SPI就要开中断的……我错了{:dizzy:}
页: [1]
查看完整版本: SPI中断问题求教