|
各位大牛周末好,我被个问题纠缠了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
复制代码 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|