搜索
bottom↓
回复: 2

SPI中断问题求教

[复制链接]

出0入0汤圆

发表于 2012-9-15 11:38:34 | 显示全部楼层 |阅读模式
各位大牛周末好,我被个问题纠缠了2天,一直解决不了,特上来求教
我做了个小玩具,ATMEGA8核心,SPI跟接收芯片通信(读写),I2C接OLED(这方式不太好,但为省几根飞线也将就着),本来用按键轮询方式控制一切都好,但想加一个旋转编码器做成个像样点的菜单,问题就出现了。
因为用旋转编码器要用到INT0、INT1,在下面的代码中,一到sei();就重启,在论坛搜了一下,大概明白打开中断必须有相应的中断处理程序,难道我必须用中断方式来处理SPI通信吗?具体该怎么做?
  1. void spi_init()
  2. {
  3.         SPIDDR |= (1 << 3) | (1 << 5);        // MOSI & SCK output
  4.         SPIDDR &= ~(1 << 4);        // MISO input
  5.         SPCR = (1 << SPIE) | (1 << SPE) | (1 << MSTR) | (1 << SPR0); // Enable SPI, Master, clock rate = fuck/4
  6.         SPSR = 0x00;               
  7.         PORT_SS_RECV |= (1 << SS_RECV); // disable Receiver
  8. }

  9. inline void spi_wait()
  10. {
  11.         while (!(SPSR & (1 << SPIF)))
  12.         {
  13.                
  14.         };
  15. }

  16. void RECV_write(unsigned char reg, unsigned char data)
  17. {
  18.         PORTB &= ~(1 << SS_RECV);
  19.        
  20.         SPDR = reg & 0b01111111; // send MAP (register address)
  21.         spi_wait();
  22.        
  23.         SPDR = data; // send data
  24.         spi_wait();
  25.        
  26.         PORTB |= (1 << SS_RECV); // raise SS_RECV
  27. }

  28. unsigned char RECV_read(unsigned char reg)
  29. {
  30.         PORTB &= ~(1 << SS_RECV);

  31.         unsigned char datain;
  32.        
  33.         SPDR =  reg | ( 1<<7 ); // read operation
  34.         spi_wait();
  35.        
  36.         SPSR = 0x00;
  37.         SPDR = 0x00;
  38.         spi_wait();
  39.         datain = SPDR;
  40.        
  41.         PORTB |= (1 << SS_RECV); // raise SS_RECV
  42.        
  43.         return datain;
  44. }


  45. //Interrupt Service Routine for INT0
  46. ISR(INT0_vect)
  47. {
  48.         // When an interrupt occurs, check the level of pin PD4 to determine the direction
  49.         if (ROTB) //equal (PIND & _BV(PD4))
  50.                 // Increase enc
  51.         {
  52.                 delayCycle(50);
  53.                 if (ROTB) enc = 1;
  54.         }       
  55.         else
  56.         {
  57.                 // Decrease enc
  58.                 delayCycle(50);
  59.                 if (!ROTB) enc = 2;
  60.         }
  61. }

  62. //Interrupt Service Routine for INT1
  63. ISR(INT1_vect)
  64. {
  65.         enc = 3;
  66. }


  67.         //OLED_ShowString(0,0,"SPI init");
  68.         spi_init();
  69.         OLED_delay(5000L);
  70.         //OLED_ShowString(1,1, "RECV init");
  71.         RECV_init(0x01);



  72.        
  73.         GICR |= (1<<INT0) | (1<<INT1); // Enable INT0 and INT1       
  74.         MCUCR |= (1<<ISC01) | (1<<ISC11); // Falling edge in INT0, INT1 (PD2,PD3) to cause interrupt
  75.         GIFR |= (1 << INTF1) | (1 << INTF0);    //clear INT0,INT1
  76.        
  77.         sei(); // Enable global interrupts
复制代码

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2012-9-15 11:46:18 | 显示全部楼层
P.S.如果必须有相应的中断处理程序,那I2C也必须添加相应的中断处理程序吗?
但我试验下来如果把上面代码的80行屏蔽(通过SPI读写),OLED显示是正常的,而OLED用的是I2C接口……

出0入0汤圆

 楼主| 发表于 2012-9-15 14:31:30 | 显示全部楼层
搞掂了,第5行改成:
SPCR =  (1 << SPE) | (1 << MSTR) | (1 << SPR0); // Enable SPI, Master, clock rate = fuck/4
去掉了(1 << SPIE) ,原来以为只要用SPI就要开中断的……我错了
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 06:23

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表