找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7199|回复: 2
收起左侧

AVR单片机SPI中断方式的疑惑

[复制链接]
ID:68618 发表于 2014-11-22 16:02 | 显示全部楼层 |阅读模式
/******************************************************************************/
/***************************SPI通讯,MASTER程序********************************/
/***************************目标MCU:MEGA8L************************************/
/**************************外部晶振3.6864MHz***********************************/
/******************************************************************************/
/**********************************引脚连接************************************/
/********************** MASTER MISO ---- SLAVE MISO ***************************/
/********************** MASTER MOSI ---- SLAVE MOSI ***************************/
/********************** MASTER SCK  ---- SLAVE SCK  ***************************/
/********************** MASTER /SS  ---- SLAVE /SS  ***************************/
/******************************************************************************/
#include <iom8v.h>
#include <macros.h>

#define uchar unsigned char   
#define uint unsigned int   

#define DDR_SPI DDRB
#define MOSI 3
#define MISO 4
#define SCK 5
#define SS 2
#define PORT_SPI PORTB
#define LED_RED_ON PORTB|=BIT(0)
#define LED_RED_OFF PORTB&=~BIT(0)
#define LED_RED_OUTPUT DDRB|=BIT(0)

#define LED_BLUE_ON PORTD|=BIT(7)
#define LED_BLUE_OFF PORTD&=~BIT(7)
#define LED_BLUE_OUTPUT DDRD|=BIT(7)

/********************************SPI初始化*************************************/     
void SPI_Init(void)
   {
         DDR_SPI|=(1<<MOSI)|(1<<SCK);     
         SPCR=(1<<SPE)|(1<<DORD)|(1<<MSTR)|(1<<SPR0);//主,LSB在先
         SPSR=0;
         //SPCR|=(1<<SPIE);
   }
     
#pragma interrupt_handler spi_stc_isr:11   
void spi_stc_isr(void)
   {
        LED_BLUE_OUTPUT;
        LED_BLUE_ON;
        SPDR=0xaa;
        //SPCR&=~(1<<SPIE);      
   }   
     
/********************************SPI SEND**************************************/
void SPI_Send(uchar command)
   {
        DDR_SPI|=(1<<SS);
        PORT_SPI|=(1<<SS);     
        //SPCR|=(1<<MSTR);
        SPCR|=(1<<SPIE);//开SPI中断     
   }     
      
/***********************************MAIN***************************************/
void main(void)
   {
        Delay_ms(100);
        LED_RED_OUTPUT;
        LED_RED_OFF;
        LED_BLUE_OUTPUT;
        LED_BLUE_OFF;
        SPI_Init();
        SEI();
        while(1)
         {
              Delay_ms(2000);
              LED_RED_ON;
              SPI_Send(0xaa);
              Delay_ms(2000);
              LED_BLUE_OUTPUT;
              LED_BLUE_OFF;
              LED_RED_OFF;
              SEI();
         }     
    }     

偶的本意是想实现每次SPI中断后兰色LED点亮,延时2秒在启动一次SPI中断。
偶现在的问题是发现:
   1,按照这个程序,第一次中断能进去,但以后不行了。现象是2秒后兰色的LED与红色的LED一起亮,再过2秒一起暗掉,然后就是红色的开始每隔2秒闪了,而兰色的不动作,说明SPI中断进不了了;
   2,如果SPI初始化程序里就进行允许SPI中断,则一上电兰色的LED就亮,过了会就灭了,然后兰色的一直不亮,说明SPI中断也是进不了;
   3,后来又调试了几次,发现必须要把MSTR再设置一下,也就是在发送的子程序里重新设置一下,但这样的结果是兰色的LED一直亮,红色的LED到是交替闪烁,偶搞不明白,偶就在SPI中断里设置了点亮兰色的LED,主程序里隔2秒就关掉兰色LED的,为什么会没关掉???
   4,如果中断里最后加上关掉SPI,发送子程序里加上重新设置MSTR,就得到了偶想要的那个红色与兰色LED同时亮灭的效果,这又是为什么啊,为什么MSTR要重新设置一下?
   偶实验的时候,SPI的那几个口什么都没接,SS脚也已经设置成输出高电平,不会有被拉低的可能啊。
   DATASHEET上写:
    When the SPI is configured as a master (MSTR in SPCR is set), the user can determine
the direction of the SS pin.
    If SS is configured as an output, the pin is a general output pin which does not affect the
    SPI system. Typically, the pin will be driving the SS pin of the SPI slave.
   If SS is configured as an input, it must be held high to ensure Master SPI operation. If
   the SS pin is driven low by peripheral circuitry when the SPI is configured as a master
   with the SS pin defined as an input, the SPI system interprets this as another master
   selecting the SPI as a slave and starting to send data to it. To avoid bus contention, the
   SPI system takes the following actions:
   1. The MSTR bit in SPCR is cleared and the SPI system becomes a slave. As a
    result of the SPI becoming a slave, the MOSI and SCK pins become inputs.
   2. The SPIF flag in SPSR is set, and if the SPI interrupt is enabled, and the I-bit in
   SREG is set, the interrupt routine will be executed.
   按照DATASHEET,主的时候MSTR设置,如果SS被设置为输入,且在MSTR为“1“时被外部拉低,则MSTR会被清除,但是偶SS一直设置成输出高电平,不存在被拉低的可能啊,两个困惑的小疑问,或许某一天的将来豁然开朗。
回复

使用道具 举报

ID:68618 发表于 2014-11-22 16:02 | 显示全部楼层
真是TMD邪乎,中断里不关SPIE,发生的现象有时候还不一定是兰色的LED一直亮,还有好几次,偶上电断一断再连上,兰色的LED亮了以后也熄灭了,但就是一直不亮了,红色的LED是一直在那闪的,说明程序也没死啊,晕死了,如果中断里的前面再加一句读取SPSR清SPIF这个位,则很多时候是兰色的LED亮一下熄灭后再也进不了中断,但是偶尔有几次上电会出现兰色LED一直亮的情况,真是匪夷所思,偶现在SPI的口可是什么都没接啊。偶就对中断的工作方式产生了怀疑。
再仔细研究了一下DATASHEET,应该是搞清楚了,SPI中断是串行传输完成响应中断,以前做M8做USART时用的是USART寄存器空这个中断号(13)来做发送中断的,都是在中断里面进行赋值和关中断操作,受这个思路影响,发送子程序里也没有先对SPDR赋值,现在先在发送子程序里给SPDR赋值就好了。MSTR也不一定要重新设置,
回复

使用道具 举报

ID:68618 发表于 2014-11-22 16:04 | 显示全部楼层
唉,还是DATASHEET看的不够仔细,吸取教训。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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